Repository navigation
test(integration): background work a test starts is cancelled before the next (B-21) - #439
Merged
Merged
Conversation
…the next (B-21) On SQLite every session shares one physical connection (StaticPool), and work started with spawn_tracked or an in-process task_queue fallback is never awaited by the request that started it. A leftover task that rolls back on that connection can undo the next test's flushed-but-uncommitted insert; that test then commits nothing, finds the object in its identity map, and its UPDATE matches zero rows — the StaleDataError test_learnings_api hit on 2026-09-23 and 2026-09-26, passing alone and on rerun. db_session's teardown now cancels and awaits all such tasks before the rollback and the truncate. test_background_work_does_not_outlive_its_test leaves a task running in one test and asserts the next does not inherit it — red without the drain. Integration suite 702/702 on SQLite. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… (B-21) The first drain cancelled leftover tasks, and a task cancelled mid-statement makes SQLAlchemy invalidate the connection — under StaticPool the replacement is a new, EMPTY :memory: database, so every later test failed with "no such table: users" (263 failed, 965 errors on CI). Now the teardown waits up to 30 s and leaves anything still running alone, naming it in a warning. `_assert_schema_survived` fails at the cause if the shared database ever loses its tables again, instead of a cascade. The guard test uses a task that finishes on its own and asserts the next test sees it finished and not cancelled (red without the drain). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
First CI run: the drain cancelled leftover tasks, and a task cancelled mid-statement makes SQLAlchemy invalidate the connection — under |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
B-21 — the
test_learnings_apiStaleDataError (CI on 2026-09-23 and 2026-09-26; passes alone and on rerun).Mechanism. On SQLite every session shares one physical connection (
StaticPool), and work started withspawn_trackedor an in-processtask_queuefallback is never awaited by the request that started it. A leftover task that rolls back on that connection can undo the NEXT test's flushed-but-uncommitted insert; that test then commits nothing, finds the object in its identity map without a query, and itsUPDATEmatches zero rows. That is exactlyUPDATE … expected to update 1 row(s); 0 were matched. Not reproduced deterministically — this is the mechanism the evidence fits, and the fix removes the precondition.Fix.
db_sessionteardown cancels and awaits every such task before the rollback and the truncate (_drain_background_work).Guard.
test_background_work_does_not_outlive_its_test.py: one test leaves a task running, the next asserts it did not inherit it — red without the drain.Checks: integration 702/702 on SQLite locally (the PostgreSQL job runs here); ruff clean. Only
tests/integrationchanged, so the unit suite is unaffected.🤖 Generated with Claude Code