fix: resolve message processing failures in multi-session scenarios#899
fix: resolve message processing failures in multi-session scenarios#899hahaschool wants to merge 2 commits intothedotmack:mainfrom
Conversation
This PR fixes two critical bugs that caused message accumulation when
multiple Claude Code sessions were running in the same project:
1. **AbortController State Issue**: When a generator finished naturally
with no pending work, it aborted its AbortController but didn't replace
it. Later HTTP requests got the cached session with the already-aborted
controller, causing the message iterator to exit immediately (~70ms).
Fix: Check if AbortController is already aborted before starting a
generator and create a new one if needed.
2. **FOREIGN KEY Constraint Violation**: After worker restart, the SDK
would generate a new session ID, and we'd try to UPDATE
`sdk_sessions.memory_session_id`. However, existing observations
referenced the old ID, and since the FK constraint doesn't have
`ON UPDATE CASCADE`, SQLite blocked the update.
Fix:
- In SDKAgent: Only update memory_session_id in database if it's NULL
- In ResponseProcessor: Always use the database's memory_session_id
for storage to maintain FK integrity
Also fixed: The queueDepth log was showing 0 from the deprecated
`session.pendingMessages.length` instead of actual database count.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Greptile OverviewGreptile SummaryThis PR fixes three critical issues affecting message processing in multi-session scenarios:
The implementation correctly handles the tension between resume functionality (needs current SDK session_id) and data integrity (needs stable memory_session_id for existing observations). The Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User as User Session
participant WS as WorkerService
participant SM as SessionManager
participant SDK as SDKAgent
participant RP as ResponseProcessor
participant DB as Database
Note over User,DB: Multi-Session Message Processing Flow
User->>WS: Message arrives
WS->>SM: getSession(sessionDbId)
SM->>DB: Load session (if not in memory)
DB-->>SM: session data + memory_session_id
Note over WS: Check AbortController state
alt AbortController is aborted
WS->>WS: Create new AbortController
Note right of WS: Fix #1: Replace aborted controller<br/>to prevent immediate exit
end
WS->>SDK: startSession(session)
Note over SDK: Resume decision logic
alt forceInit flag set
SDK->>SDK: Skip resume (stale session recovery)
SDK->>SDK: Clear forceInit flag
else memorySessionId exists AND lastPromptNumber > 1
SDK->>SDK: Resume with memorySessionId
else
SDK->>SDK: Start fresh session
end
SDK->>DB: Check existing memory_session_id
DB-->>SDK: dbSession.memory_session_id
alt database has memory_session_id
Note right of SDK: Fix #2: Use DB value for FK integrity
SDK->>SDK: Keep DB value, don't update
else database has NULL
SDK->>SDK: Capture new session_id from SDK
SDK->>DB: updateMemorySessionId(new_id)
end
SDK->>RP: Process assistant response
RP->>DB: Get dbSession.memory_session_id
Note right of RP: Fix #2: Use authoritative DB value
RP->>DB: storeObservations(memorySessionIdForStorage)
DB-->>RP: Success (no FK violation)
SDK-->>WS: Generator completes
alt Generator crashed (not aborted)
WS->>SM: Check pending messages
SM-->>WS: pendingCount > 0
WS->>WS: Replace AbortController
WS->>WS: Abort old controller (cleanup)
Note right of WS: Crash recovery with delay
WS-->>WS: setTimeout restart
else Generator naturally completed
WS->>WS: Abort controller (cleanup)
end
Note over WS: Stale Resume Error Handling
alt SDK error: "aborted by user"
WS->>WS: Set forceInit flag
WS->>DB: Clear memory_session_id
WS->>WS: Retry with fresh session
end
|
Update function signature to accept `string | null` instead of using `as any` type assertion. This properly supports clearing memory_session_id during stale resume recovery. - SessionStore.updateMemorySessionId: string → string | null - sessions/create.ts updateMemorySessionId: string → string | null - Remove `as any` cast in worker-service.ts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Thanks for the thorough review, @greptile-apps! I've addressed the type safety concern: Fixed in commit 76227ec:
The function now properly supports clearing |
|
Perfect! The type safety improvements look excellent. You've properly addressed the concern by:
This is a much cleaner solution that properly expresses the intent of the code - that The changes are minimal and focused, which is ideal for this type of type safety fix. Great work addressing this feedback! |
|
Thank you for this thorough fix, @hahaschool! You identified some real issues in the multi-session message processing flow. However, this PR now has significant overlap with several PRs that were merged after yours was opened, and the rebase produces conflicts in 3 files ( Already addressed by recently merged PRs:
Still valuable — consider submitting as focused PRs:
If you'd like to re-submit these as 1-2 focused PRs, they'd be straightforward to review and merge. Thanks for the thorough investigation! |
…, #940 Reviewed PR #899 (multi-session message processing fix). Identified significant overlap with 3 recently merged PRs causing merge conflicts in 3 files. Closed with detailed feedback requesting focused re-submission of the genuinely valuable parts: AbortController stale-check, FK constraint protection, and queueDepth fix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Problem
When multiple Claude Code sessions were running in the same project folder, messages would accumulate without being processed. Root causes:
AbortController reuse: When a generator finished naturally, it aborted its controller but kept the session in memory. New messages would try to start a generator with the already-aborted controller, causing immediate exit.
FK constraint violation: After worker restart, SDK generates new session ID. Updating
sdk_sessions.memory_session_idfailed because existing observations referenced the old ID (FK withoutON UPDATE CASCADE).Solution
memory_session_idfor observation storage (FK integrity)memory_session_idin database when it's NULLTest plan
🤖 Generated with Claude Code