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:
@@ -72,6 +72,8 @@ describe('ResponseProcessor', () => {
|
||||
mockDbManager = {
|
||||
getSessionStore: () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}), // FK fix (Issue #846)
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })), // FK fix (Issue #846)
|
||||
}),
|
||||
getChromaSync: () => ({
|
||||
syncObservation: mockChromaSyncObservation,
|
||||
@@ -85,6 +87,7 @@ describe('ResponseProcessor', () => {
|
||||
},
|
||||
getPendingMessageStore: () => ({
|
||||
markProcessed: mock(() => {}),
|
||||
confirmProcessed: mock(() => {}), // CLAIM-CONFIRM pattern: confirm after successful storage
|
||||
cleanupProcessed: mock(() => 0),
|
||||
resetStuckMessages: mock(() => 0),
|
||||
}),
|
||||
@@ -126,6 +129,7 @@ describe('ResponseProcessor', () => {
|
||||
earliestPendingTimestamp: Date.now() - 10000,
|
||||
conversationHistory: [],
|
||||
currentProvider: 'claude',
|
||||
processingMessageIds: [], // CLAIM-CONFIRM pattern: track message IDs being processed
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
@@ -269,6 +273,8 @@ describe('ResponseProcessor', () => {
|
||||
}));
|
||||
(mockDbManager.getSessionStore as any) = () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}),
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })),
|
||||
});
|
||||
|
||||
await processAgentResponse(
|
||||
@@ -367,6 +373,8 @@ describe('ResponseProcessor', () => {
|
||||
}));
|
||||
(mockDbManager.getSessionStore as any) = () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}),
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })),
|
||||
});
|
||||
|
||||
await processAgentResponse(
|
||||
@@ -446,6 +454,8 @@ describe('ResponseProcessor', () => {
|
||||
}));
|
||||
(mockDbManager.getSessionStore as any) = () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}),
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })),
|
||||
});
|
||||
|
||||
await processAgentResponse(
|
||||
@@ -477,6 +487,8 @@ describe('ResponseProcessor', () => {
|
||||
}));
|
||||
(mockDbManager.getSessionStore as any) = () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}),
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })),
|
||||
});
|
||||
|
||||
await processAgentResponse(
|
||||
@@ -519,6 +531,8 @@ describe('ResponseProcessor', () => {
|
||||
}));
|
||||
(mockDbManager.getSessionStore as any) = () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}),
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })),
|
||||
});
|
||||
|
||||
await processAgentResponse(
|
||||
@@ -555,6 +569,8 @@ describe('ResponseProcessor', () => {
|
||||
}));
|
||||
(mockDbManager.getSessionStore as any) = () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}),
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })),
|
||||
});
|
||||
|
||||
await processAgentResponse(
|
||||
@@ -595,6 +611,8 @@ describe('ResponseProcessor', () => {
|
||||
}));
|
||||
(mockDbManager.getSessionStore as any) = () => ({
|
||||
storeObservations: mockStoreObservations,
|
||||
ensureMemorySessionIdRegistered: mock(() => {}),
|
||||
getSessionById: mock(() => ({ memory_session_id: 'memory-session-456' })),
|
||||
});
|
||||
|
||||
await processAgentResponse(
|
||||
@@ -615,7 +633,7 @@ describe('ResponseProcessor', () => {
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
it('should throw error if memorySessionId is missing', async () => {
|
||||
it('should throw error if memorySessionId is missing from session', async () => {
|
||||
const session = createMockSession({
|
||||
memorySessionId: null, // Missing memory session ID
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user