fix(host-sweep): reopen outbound DB as writable for orphan claim cleanup#2183
Merged
gavrielc merged 2 commits intoqwibitai:mainfrom May 2, 2026
Merged
fix(host-sweep): reopen outbound DB as writable for orphan claim cleanup#2183gavrielc merged 2 commits intoqwibitai:mainfrom
gavrielc merged 2 commits intoqwibitai:mainfrom
Conversation
PR qwibitai#2151 added deleteOrphanProcessingClaims() to resetStuckProcessingRows(), but outDb is always opened readonly (openOutboundDb uses immutable: true). The write silently failed, leaving orphan processing_ack rows that block future message delivery for the session. Fix: add openOutboundDbRw() alongside the existing readonly opener and use it in resetStuckProcessingRows() to open a short-lived writable handle just for the delete. The readonly handle is still used for all reads above. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Collaborator
|
@cfis Thank you for the fix!! |
This was referenced May 3, 2026
This was referenced May 3, 2026
cfis
added a commit
to cfis/nanoclaw
that referenced
this pull request
May 3, 2026
…ssed in tests qwibitai#2183 added orphan-claim cleanup that reopens `outbound.db` by session path (`openOutboundDbRw(session.agent_group_id, session.id)`) so the delete runs against a writable handle even when callers pass a readonly one. That works for the production caller — there's a real on-disk session DB at the expected path. The test wrapper `_resetStuckProcessingRowsForTesting` (introduced in the same series, qwibitai#2151) is called with in-memory DBs that have no on-disk path. The reopen creates a fresh empty file at `<DATA_DIR>/v2-sessions/ag-test/sess-test/outbound.db`, runs the delete against that, and leaves the in-memory `outDb` (which the test reads afterward) untouched. The two `resetStuckProcessingRows — orphan claim cleanup` tests assert `getProcessingClaims(outDb).toEqual([])` after the call and fail on the row that's still there. Fix: drop the `_…ForTesting` wrapper, export `resetStuckProcessingRows` directly with an optional `writableOutDb` parameter. When omitted (production), the function reopens `outbound.db` RW by session path — existing behavior, existing safety guarantee. When provided (tests, or any future caller that already holds a writable handle), the function uses it directly and skips the reopen. The optional parameter has a real meaning, not a "for tests" hack. Public API surface change: `_resetStuckProcessingRowsForTesting` is gone, `resetStuckProcessingRows` is now exported. No other callers inside the repo besides the test.
cfis
added a commit
to cfis/nanoclaw
that referenced
this pull request
May 3, 2026
…ssed in tests qwibitai#2183 added orphan-claim cleanup that reopens `outbound.db` by session path (`openOutboundDbRw(session.agent_group_id, session.id)`) so the delete runs against a writable handle even when callers pass a readonly one. That works for the production caller — there's a real on-disk session DB at the expected path. The test wrapper `_resetStuckProcessingRowsForTesting` (introduced in the same series, qwibitai#2151) is called with in-memory DBs that have no on-disk path. The reopen creates a fresh empty file at `<DATA_DIR>/v2-sessions/ag-test/sess-test/outbound.db`, runs the delete against that, and leaves the in-memory `outDb` (which the test reads afterward) untouched. The two `resetStuckProcessingRows — orphan claim cleanup` tests assert `getProcessingClaims(outDb).toEqual([])` after the call and fail on the row that's still there. Fix: drop the `_…ForTesting` wrapper, export `resetStuckProcessingRows` directly with an optional `writableOutDb` parameter. When omitted (production), the function reopens `outbound.db` RW by session path — existing behavior, existing safety guarantee. When provided (tests, or any future caller that already holds a writable handle), the function uses it directly and skips the reopen. The optional parameter has a real meaning, not a "for tests" hack. Public API surface change: `_resetStuckProcessingRowsForTesting` is gone, `resetStuckProcessingRows` is now exported. No other callers inside the repo besides the test.
This was referenced May 4, 2026
gavrielc
added a commit
that referenced
this pull request
May 5, 2026
fix(host-sweep): orphan-claim delete missed in tests (regression from #2183)
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.
Problem
PR #2151 added
deleteOrphanProcessingClaims()toresetStuckProcessingRows()inhost-sweep.ts, butoutDbis always opened readonly (immutable: trueviaopenOutboundDb). The write silently fails, leaving orphanprocessing_ackrows that block future message delivery for the session.Fix
Add
openOutboundDbRw()alongside the existing readonly opener insession-db.tsand re-export it fromsession-manager.ts. InresetStuckProcessingRows(), open a short-lived writable handle just for the delete, then close it immediately. The readonly handle is still used for all reads above.This is safe because
resetStuckProcessingRows()is only called after the container has been killed or confirmed not running, so there is no concurrent writer.Changes
src/db/session-db.ts— addopenOutboundDbRw(dbPath)src/session-manager.ts— re-export asopenOutboundDbRw(agentGroupId, sessionId)src/host-sweep.ts— use writable handle for the delete inresetStuckProcessingRows()🤖 Generated with Claude Code