Files
wehub-resource-sync d18ada4ee7
Docker Publish / docker (web, apps/web/Dockerfile, web) (push) Failing after 0s
Docker Publish / docker (api, apps/api/Dockerfile, api) (push) Failing after 1s
Publish Extension / detect-version (push) Has been skipped
Publish Extension / submit (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:24:41 +08:00

78 lines
2.4 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import { MemoryPersistAdapter } from '../src/persist'
import { ProcessRegistry } from '../src/process'
describe('ProcessRegistry', () => {
it('records spawn + close pairs in the journal', async () => {
const persist = new MemoryPersistAdapter()
const reg = new ProcessRegistry({ persist, kill: vi.fn(), sleep: async () => {} })
await reg.recordSpawn({
taskId: 't',
attemptId: 'a',
pid: 100,
pidStartedAt: 50,
kind: 'yt-dlp',
spawnedAt: Date.now()
})
await reg.recordClose('t', 'a', 0, null)
const journal = persist.journalSnapshot()
expect(journal.map((r) => r.op)).toEqual(['spawn', 'close'])
const open = await persist.findOpenSpawns()
expect(open).toHaveLength(0)
})
it('cancel issues SIGTERM then SIGKILL after grace', async () => {
const persist = new MemoryPersistAdapter()
const kill = vi.fn()
const reg = new ProcessRegistry({
persist,
kill,
sleep: async () => {},
// Simulate the process never dying so SIGKILL fires.
killGracePeriodMs: 0
})
await reg.recordSpawn({
taskId: 't',
attemptId: 'a',
pid: 100,
pidStartedAt: 50,
kind: 'yt-dlp',
spawnedAt: Date.now()
})
await reg.cancel('t', 'a')
expect(kill).toHaveBeenCalledWith(100, 'SIGTERM')
// killed row written
const journal = persist.journalSnapshot()
expect(journal.map((r) => r.op)).toContain('killed')
})
it('reconcile finds spawn rows without a matching close and journals killed', async () => {
const persist = new MemoryPersistAdapter()
// Pretend the process has been killed externally by the OS — kill stub is
// a noop but isPidAlive returns false because the pid is fake.
const reg = new ProcessRegistry({
persist,
kill: vi.fn(),
sleep: async () => {},
killGracePeriodMs: 0
})
// Append an orphan spawn directly (simulating a previous app instance).
await persist.appendJournal({
ts: Date.now(),
op: 'spawn',
taskId: 't1',
attemptId: 'a1',
pid: 999_999, // surely dead
pidStartedAt: 0,
exitCode: null,
signal: null
})
const reconciled = await reg.reconcile()
expect(reconciled).toHaveLength(1)
expect(reconciled[0]!.taskId).toBe('t1')
const ops = persist.journalSnapshot().map((r) => r.op)
expect(ops).toContain('killed')
})
})