fix(session queue): count only rows actually transitioned by a bulk cancel - #9387
Conversation
e9ee846 to
4e33017
Compare
|
Rebased onto the current #9263 head ( |
…ancel Two concurrent bulk cancellations could select the same in-progress row; the first canceled it and the second, seeing the already-terminal row returned by _set_queue_item_status(), counted it again — both responses reporting that they canceled the same item. The terminal guard and the UPDATE already ran atomically (a single transaction under SqliteDatabase's process-wide lock); what was missing was exposing WHO performed the transition. _set_queue_item_status() now delegates to _transition_queue_item_status(), which additionally returns whether THIS call moved the row, and _cancel_in_progress_matching() counts only actual transitions — so exactly one racing caller observes itself as the canceller. The docstring records that the atomicity comes from the database lock, not the SQL, so a future move to per-thread connections doesn't silently reintroduce the double count. Includes a two-thread barrier test (in-memory SQLite) asserting each item is counted exactly once across concurrent bulk cancels; the pre-fix counter reports 4 for 2 items under the same interleaving. Follow-up to PR invoke-ai#9263 (JPPhoto review, 2026-07-25). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4e33017 to
61a7de7
Compare
JPPhoto
left a comment
There was a problem hiding this comment.
Approved!
You might want to consider guarded SQL UPDATE plus cursor.rowcount; the current guarantee relies on shared SqliteDatabase._lock.
Summary
Follow-up to #9263, addressing the duplicate bulk-cancel counting deferred in @JPPhoto's 2026-07-25 review:
UPDATEstatement itself:_transition_queue_item_status()performsUPDATE ... WHERE item_id = ? AND status NOT IN ('completed','failed','canceled')and reports viacursor.rowcountwhether THIS call performed the transition._set_queue_item_status()is a thin wrapper preserving its existing contract._cancel_in_progress_matching()counts only actual transitions, so two racing bulk requests each report a disjoint set of canceled items._set_queue_item_status(a row could turn terminal between the read and the write) is gone.Test
test_concurrent_bulk_cancels_count_each_item_onceuses a barrier to hold twocancel_by_batch_idsrequests after their item-id SELECTs (both have selected the same two in-progress rows) and asserts the combinedcanceledcount is exactly 2 — under the old code it was 4. Verified the test fails against the previous counting logic.Merge order
Stacked on #9263 — this branch contains the multi-GPU branch's commits. Draft until #9263 merges; will then rebase onto main and mark ready for review.
Checklist
What's Newcopy (if doing a release after this PR)🤖 Generated with Claude Code