Skip to content

Fix the chronic CISqlServer red: give the DLQ expiration suite its own schema - #3743

Merged
jeremydmiller merged 1 commit into
mainfrom
gh/sqlserver-dlq-expiration-schema-isolation
Jul 30, 2026
Merged

Fix the chronic CISqlServer red: give the DLQ expiration suite its own schema#3743
jeremydmiller merged 1 commit into
mainfrom
gh/sqlserver-dlq-expiration-schema-isolation

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

CISqlServer has been red on main since 2a3761d1d, with all ten dead-letter tests in SqlServerMessageStore_with_DeadLetter_Expiration failing on Invalid column name 'expires'. It is unrelated to any PR that happens to be sitting under it — it reproduces on a clean checkout of main.

Root cause

DeadLetterQueueExpirationEnabled changes the shape of the dead letters table — DeadLettersTable adds the expires column and its filtered index only when the setting is on.

Two compliance suites shared the receiver2 schema:

suite expiration schema handling
SqlServerMessageStore_with_IdAndDestination_Identity off (default) DropSchemaAsync("receiver2"), then recreates
SqlServerMessageStore_with_DeadLetter_Expiration on never drops, reuses whatever exists

Whichever ran last won. Once the table existed without expires, every test that writes a dead letter failed. And because the schema outlives the process, it stayed broken for subsequent runs against the same database — which is why CI's retry of a single test in isolation still failed.

The fix

Give the expiration suite a schema of its own (receiver_dlq_expiration) so the two cannot collide. This removes the ordering coupling rather than papering over it with a second drop.

Verified by reproducing the exact CI failure locally (10 failures, same tests, same message), then re-running the poisoning sequence — IdAndDestination first, expiration suite second — with the fix: both green (50 and 45 tests).

Follow-up: there is also a real product bug here

This PR only fixes the test isolation. Separately, Wolverine does not migrate an existing dead letters table to add expires when DeadLetterQueueExpirationEnabled is switched on, even though DatabaseSettings.AutoCreate defaults to CreateOrUpdate. Confirmed empirically:

  • table created fresh by an expiration-enabled host → has expires, tests pass
  • pre-existing table + expiration-enabled host started against it → column never added, and DatabasePersistence still emits insert ... (expires) values (...) because it reads the flag at runtime

So any user who turns this feature on against an established database gets a dead-letter queue that throws Invalid column name 'expires' on every write. Worth its own issue and fix.

🤖 Generated with Claude Code

CISqlServer has been red on main since 2a3761d, with all ten dead-letter
tests in SqlServerMessageStore_with_DeadLetter_Expiration failing on
"Invalid column name 'expires'".

DeadLetterQueueExpirationEnabled changes the *shape* of the dead letters table
-- it adds the `expires` column and its filtered index. That suite shared the
"receiver2" schema with SqlServerMessageStore_with_IdAndDestination_Identity,
which drops and recreates the schema from a host that leaves the setting off,
while the expiration suite never dropped anything and simply reused whatever
was already there. Whichever ran last won. Once the table existed without
`expires`, every test that writes a dead letter failed -- and because the
schema outlives the process, it stayed broken for later runs against the same
database, which is why re-running a single test in isolation still failed on
CI.

Give the expiration suite a schema of its own so the two can't collide. The
ordering coupling is removed rather than papered over with another drop.

Note this is only the test isolation half. Wolverine does not migrate an
existing dead letters table to add `expires` when DeadLetterQueueExpirationEnabled
is turned on, even though AutoCreate defaults to CreateOrUpdate -- a fresh
table built by an expiration-enabled host gets the column, an existing one
never does. That is a real product bug for anyone enabling the feature on an
established database, and is filed separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant