From 87479d170692679e3699792738087b0c3c3c603d Mon Sep 17 00:00:00 2001 From: JOUNGWOOK KWON Date: Fri, 17 Apr 2026 09:13:19 +0900 Subject: [PATCH] fix: reset session when age limit exceeded, not just when completed Previous fix only reset sessions with completed_at_epoch set. But mac sleep/resume without SessionEnd leaves sessions alive with stale started_at_epoch, causing age limit to block all processing on next use. Now resets started_at_epoch whenever the session is older than the 4-hour wall-clock limit (MAX_SESSION_MS), matching SDKAgent's threshold. Co-Authored-By: Claude Sonnet 4.6 --- src/services/sqlite/sessions/create.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/services/sqlite/sessions/create.ts b/src/services/sqlite/sessions/create.ts index b7cf2267..f55d40bf 100644 --- a/src/services/sqlite/sessions/create.ts +++ b/src/services/sqlite/sessions/create.ts @@ -43,16 +43,24 @@ export function createSDKSession( // Check for existing session const existing = db.prepare(` - SELECT id, platform_source, completed_at_epoch FROM sdk_sessions WHERE content_session_id = ? - `).get(contentSessionId) as { id: number; platform_source: string | null; completed_at_epoch: number | null } | undefined; + SELECT id, platform_source, completed_at_epoch, started_at_epoch FROM sdk_sessions WHERE content_session_id = ? + `).get(contentSessionId) as { id: number; platform_source: string | null; completed_at_epoch: number | null; started_at_epoch: number } | undefined; + + // 4-hour wall-clock limit (must match SDKAgent.MAX_SESSION_WALL_CLOCK_MS) + const MAX_SESSION_MS = 4 * 60 * 60 * 1000; if (existing) { - // If the session was previously completed (e.g., mac sleep/resume without proper SessionEnd), - // reset it so the age limit check starts fresh from now. - if (existing.completed_at_epoch) { - logger.info('SESSION', 'Resetting completed session on resume (mac sleep/resume detected)', { + // Reset session if it was completed OR if it's older than the wall-clock age limit. + // This handles mac sleep/resume scenarios where the worker restarts but SessionEnd + // never fired, leaving the session with a stale started_at_epoch that causes the + // age limit check to abort all observations and summaries. + const ageMs = nowEpoch - existing.started_at_epoch; + const needsReset = !!existing.completed_at_epoch || ageMs > MAX_SESSION_MS; + if (needsReset) { + logger.info('SESSION', 'Resetting stale session on resume (mac sleep/worker-restart detected)', { contentSessionId, - previousCompletedAt: new Date(existing.completed_at_epoch).toISOString() + ageHours: Math.round(ageMs / 36e5 * 10) / 10, + wasCompleted: !!existing.completed_at_epoch }); db.prepare(` UPDATE sdk_sessions