diff --git a/apps/worker/src/commands/__tests__/snapshot.test.ts b/apps/worker/src/commands/__tests__/snapshot.test.ts index 559d1c3b8..c97e11262 100644 --- a/apps/worker/src/commands/__tests__/snapshot.test.ts +++ b/apps/worker/src/commands/__tests__/snapshot.test.ts @@ -6,7 +6,6 @@ const { mockFindTaskRun, mockFindEnvironment, mockDone, - mockUpdateSnapshotStatus, mockSetup, mockInjectEnvVars, mockWorkerEnvFromProcessEnv, @@ -20,7 +19,6 @@ const { mockFindTaskRun: vi.fn(), mockFindEnvironment: vi.fn(), mockDone: vi.fn(), - mockUpdateSnapshotStatus: vi.fn(), mockSetup: vi.fn(), mockInjectEnvVars: vi.fn(), mockWorkerEnvFromProcessEnv: vi.fn(), @@ -38,10 +36,7 @@ vi.mock('@roomote/sdk/client', () => ({ findFirstById: mockFindTaskRun, done: mockDone, }, - environments: { - findEnvironment: mockFindEnvironment, - updateSnapshotStatus: mockUpdateSnapshotStatus, - }, + environments: { findEnvironment: mockFindEnvironment }, }, })); @@ -104,7 +99,6 @@ describe('snapshot', () => { mockWorkerEnvFromProcessEnv.mockReturnValue({}); mockCreateStartupLogger.mockReturnValue({ userLog: { log: vi.fn() } }); mockDone.mockResolvedValue(undefined); - mockUpdateSnapshotStatus.mockResolvedValue(undefined); mockSetup.mockRejectedValue(new Error('setup failed')); }); @@ -113,7 +107,7 @@ describe('snapshot', () => { expect(EXPLICIT_SNAPSHOT_TIMEOUT_MS).toBe(10 * 60 * 1_000); }); - it('treats the failure cleanup status write as a best-effort no-op when it succeeds idempotently', async () => { + it('delegates snapshot failure state to the terminal run path', async () => { const result = await snapshot({ runId: 42, environmentId: 'env-1', @@ -126,10 +120,6 @@ describe('snapshot', () => { status: RunStatus.Failed, error: 'setup failed', }); - expect(mockUpdateSnapshotStatus).toHaveBeenCalledWith({ - environmentId: 'env-1', - snapshotStatus: 'failed', - }); expect(mockSetup).toHaveBeenCalledWith( expect.objectContaining({ workspace: expect.objectContaining({ diff --git a/apps/worker/src/commands/snapshot.ts b/apps/worker/src/commands/snapshot.ts index f5ad71d92..be8a9433a 100644 --- a/apps/worker/src/commands/snapshot.ts +++ b/apps/worker/src/commands/snapshot.ts @@ -159,24 +159,6 @@ export async function snapshot({ error: message, }); - // Mark the environment snapshot as failed so the UI stops showing "Snapshotting..." - try { - await sdk.environments.updateSnapshotStatus({ - environmentId, - snapshotStatus: 'failed', - }); - } catch (envError) { - captureWorkerException(envError, { - runId, - environmentId, - stage: 'snapshot.updateSnapshotStatus', - }); - - console.error( - `Failed to update environment snapshot status: ${envError instanceof Error ? envError.message : String(envError)}`, - ); - } - captureWorkerException(error, { runId, environmentId, diff --git a/packages/sdk/src/server/lib/task-runs/__tests__/finish-run.test.ts b/packages/sdk/src/server/lib/task-runs/__tests__/finish-run.test.ts index 5b88e99b2..32fb80e41 100644 --- a/packages/sdk/src/server/lib/task-runs/__tests__/finish-run.test.ts +++ b/packages/sdk/src/server/lib/task-runs/__tests__/finish-run.test.ts @@ -764,6 +764,21 @@ describe('finishRun', () => { ); }); + it.each([ + RunStatus.Completed, + RunStatus.Failed, + RunStatus.Canceled, + ] as const)( + 'excludes %s snapshot maintenance from task settlement analytics', + async (status) => { + mockFindFirstRun.mockResolvedValue(makeSnapshotRun()); + + await finishRun({ id: 55, status, error: 'boom' }); + + expect(mockCaptureTaskSettled).not.toHaveBeenCalled(); + }, + ); + it('flips the pending row to failed when the run is canceled', async () => { mockFindFirstRun.mockResolvedValue(makeSnapshotRun()); diff --git a/packages/sdk/src/server/lib/task-runs/finish-run.ts b/packages/sdk/src/server/lib/task-runs/finish-run.ts index 60b722b4f..0cd9cc2f0 100644 --- a/packages/sdk/src/server/lib/task-runs/finish-run.ts +++ b/packages/sdk/src/server/lib/task-runs/finish-run.ts @@ -289,11 +289,14 @@ export const finishRun = async ({ ); // Anonymous analytics (no-op unless enabled): terminal task outcome with - // non-identifying routing facts only. + // non-identifying routing facts only. Snapshot maintenance is excluded from + // task_created, so exclude it here too to keep task reliability denominators + // aligned. if ( - status === RunStatus.Completed || - status === RunStatus.Failed || - status === RunStatus.Canceled + payloadKind !== TaskPayloadKind.SnapshotEnvironment && + (status === RunStatus.Completed || + status === RunStatus.Failed || + status === RunStatus.Canceled) ) { void captureTaskSettled(run.id, status, errorCode); }