mirror of
https://github.com/thedotmack/claude-mem
synced 2026-04-25 17:15:04 +02:00
MAESTRO: fix(db): prevent FK constraint failures on worker restart
Cherry-picked source changes from PR #889 by @Et9797. Fixes #846. Key changes: - Add ensureMemorySessionIdRegistered() guard in SessionStore.ts - Add ON UPDATE CASCADE migration (schema v21) for observations and session_summaries FK constraints - Change message queue from claim-and-delete to claim-confirm pattern (PendingMessageStore.ts) - Add spawn deduplication and unrecoverable error detection in SessionRoutes.ts and worker-service.ts - Add forceInit flag to SDKAgent for stale session recovery Build artifacts skipped (pre-existing dompurify dep issue). Path fixes (HealthMonitor.ts, worker-utils.ts) already merged via PR #634. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -116,23 +116,44 @@ describe('Session ID Critical Invariants', () => {
|
||||
expect(session?.memory_session_id).not.toBe(contentSessionId);
|
||||
});
|
||||
|
||||
it('should maintain consistent memorySessionId across multiple prompts in same conversation', () => {
|
||||
it('should preserve memorySessionId across createSDKSession calls (pure get-or-create)', () => {
|
||||
// createSDKSession is a pure get-or-create: it never modifies memory_session_id.
|
||||
// Multi-terminal isolation is handled by ON UPDATE CASCADE at the schema level,
|
||||
// and ensureMemorySessionIdRegistered updates the ID when a new generator captures one.
|
||||
const contentSessionId = 'multi-prompt-session';
|
||||
const realMemoryId = 'consistent-memory-id';
|
||||
const firstMemoryId = 'first-generator-memory-id';
|
||||
|
||||
// Prompt 1: Create session
|
||||
// First generator creates session and captures memory ID
|
||||
let sessionDbId = store.createSDKSession(contentSessionId, 'test-project', 'Prompt 1');
|
||||
store.updateMemorySessionId(sessionDbId, realMemoryId);
|
||||
|
||||
// Prompt 2: Look up session (createSDKSession uses INSERT OR IGNORE + SELECT)
|
||||
sessionDbId = store.createSDKSession(contentSessionId, 'test-project', 'Prompt 2');
|
||||
store.updateMemorySessionId(sessionDbId, firstMemoryId);
|
||||
let session = store.getSessionById(sessionDbId);
|
||||
expect(session?.memory_session_id).toBe(realMemoryId);
|
||||
expect(session?.memory_session_id).toBe(firstMemoryId);
|
||||
|
||||
// Prompt 3: Still same memory ID
|
||||
sessionDbId = store.createSDKSession(contentSessionId, 'test-project', 'Prompt 3');
|
||||
// Second createSDKSession call preserves memory_session_id (no reset)
|
||||
sessionDbId = store.createSDKSession(contentSessionId, 'test-project', 'Prompt 2');
|
||||
session = store.getSessionById(sessionDbId);
|
||||
expect(session?.memory_session_id).toBe(realMemoryId);
|
||||
expect(session?.memory_session_id).toBe(firstMemoryId); // Preserved, not reset
|
||||
|
||||
// ensureMemorySessionIdRegistered can update to a new ID (ON UPDATE CASCADE handles FK)
|
||||
store.ensureMemorySessionIdRegistered(sessionDbId, 'second-generator-memory-id');
|
||||
session = store.getSessionById(sessionDbId);
|
||||
expect(session?.memory_session_id).toBe('second-generator-memory-id');
|
||||
});
|
||||
|
||||
it('should NOT reset memorySessionId when it is still NULL (first prompt scenario)', () => {
|
||||
// When memory_session_id is NULL, createSDKSession should NOT reset it
|
||||
// This is the normal first-prompt scenario where SDKAgent hasn't captured the ID yet
|
||||
const contentSessionId = 'new-session';
|
||||
|
||||
// First createSDKSession - creates row with NULL memory_session_id
|
||||
const sessionDbId = store.createSDKSession(contentSessionId, 'test-project', 'Prompt 1');
|
||||
let session = store.getSessionById(sessionDbId);
|
||||
expect(session?.memory_session_id).toBeNull();
|
||||
|
||||
// Second createSDKSession (before SDK has returned) - should still be NULL, no reset needed
|
||||
store.createSDKSession(contentSessionId, 'test-project', 'Prompt 2');
|
||||
session = store.getSessionById(sessionDbId);
|
||||
expect(session?.memory_session_id).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user