Files
waooplus/tests/unit/run-runtime/recovery.test.ts

77 lines
2.4 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { RUN_STATUS } from '@/lib/run-runtime/types'
import { isRecoverableRunRecord, selectRecoverableRun } from '@/lib/run-runtime/recovery'
describe('run recovery', () => {
it('treats queued runs as recoverable', () => {
expect(isRecoverableRunRecord({
id: 'run-1',
status: RUN_STATUS.QUEUED,
})).toBe(true)
})
it('rejects running runs with expired lease and no heartbeat extension', () => {
const now = Date.parse('2026-03-30T10:00:00.000Z')
expect(isRecoverableRunRecord({
id: 'run-1',
status: RUN_STATUS.RUNNING,
leaseExpiresAt: '2026-03-30T09:59:00.000Z',
heartbeatAt: '2026-03-30T09:58:30.000Z',
}, now)).toBe(false)
})
it('prefers the latest recoverable run and skips stale leased runs', () => {
const now = Date.parse('2026-03-30T10:00:00.000Z')
const decision = selectRecoverableRun([
{
id: 'run-stale',
status: RUN_STATUS.RUNNING,
createdAt: '2026-03-30T09:00:00.000Z',
updatedAt: '2026-03-30T09:30:00.000Z',
leaseExpiresAt: '2026-03-30T09:59:00.000Z',
heartbeatAt: '2026-03-30T09:58:30.000Z',
},
{
id: 'run-fresh',
status: RUN_STATUS.RUNNING,
createdAt: '2026-03-30T09:50:00.000Z',
updatedAt: '2026-03-30T09:59:30.000Z',
leaseExpiresAt: '2026-03-30T10:02:00.000Z',
heartbeatAt: '2026-03-30T09:59:30.000Z',
},
], now)
expect(decision).toEqual({
runId: 'run-fresh',
reason: 'latest_active',
})
})
it('skips a newer stale active run when an older recoverable run still exists', () => {
const now = Date.parse('2026-03-30T10:00:00.000Z')
const decision = selectRecoverableRun([
{
id: 'run-new-stale',
status: RUN_STATUS.RUNNING,
createdAt: '2026-03-30T09:58:00.000Z',
updatedAt: '2026-03-30T09:59:50.000Z',
leaseExpiresAt: '2026-03-30T09:59:00.000Z',
heartbeatAt: '2026-03-30T09:58:30.000Z',
},
{
id: 'run-older-fresh',
status: RUN_STATUS.RUNNING,
createdAt: '2026-03-30T09:50:00.000Z',
updatedAt: '2026-03-30T09:59:30.000Z',
leaseExpiresAt: '2026-03-30T10:02:00.000Z',
heartbeatAt: '2026-03-30T09:59:30.000Z',
},
], now)
expect(decision).toEqual({
runId: 'run-older-fresh',
reason: 'latest_active',
})
})
})