Assessor_2.0/tests/postgres/ingestion-terminal-failure....

31 lines
2.0 KiB
TypeScript

import type { Pool } from 'pg';
import { expect, it } from 'vitest';
import { PostgresAssessorRepository } from '../../server/postgres/postgres-assessor-repository';
import type { IngestionJob } from '../../src/domain/ingestion-persistence';
it('commits a non-retryable first failure as dead-letter with accurate attempts and no lease', async () => {
const now = '2026-09-17T10:00:00.000Z';
let job: IngestionJob = { version: 1, id: 'synthetic-job', projectId: 'synthetic-project', artifactId: 'synthetic-artifact',
kind: 'analyze-gpo-backup', idempotencyKey: 'synthetic', status: 'running', attempts: 1, maxAttempts: 3,
leaseOwner: 'worker', leaseExpiresAt: '2026-09-17T10:01:00.000Z', availableAt: now, createdAt: now, updatedAt: now };
const statements: string[] = [];
const query = async (sql: string, values: unknown[] = []) => {
statements.push(sql);
if (sql.startsWith('SELECT revision FROM assessor_repository_state')) return { rows: [{ revision: 0 }], rowCount: 1 };
if (sql.startsWith('UPDATE assessor_repository_state')) return { rows: [{ revision: 1 }], rowCount: 1 };
if (sql.startsWith('SELECT data FROM assessor_ingestion_jobs')) return { rows: [{ data: structuredClone(job) }], rowCount: 1 };
if (sql.startsWith('UPDATE assessor_ingestion_jobs')) {
expect(values[1]).toBe('dead-letter');
expect(sql).toContain('lease_owner = NULL, lease_expires_at = NULL');
job = JSON.parse(values[4] as string);
}
return { rows: [], rowCount: 0 };
};
const repository = await PostgresAssessorRepository.create({ query, connect: async () => ({ query, release() {} }) } as unknown as Pool);
await expect(repository.failIngestionJob(job.id, 'worker', now, 'artifact-store-object-missing', now, false))
.resolves.toMatchObject({ status: 'dead-letter', attempts: 1, maxAttempts: 3, lastErrorCode: 'artifact-store-object-missing' });
expect(job).not.toHaveProperty('leaseOwner');
expect(job).not.toHaveProperty('leaseExpiresAt');
expect(statements.at(-1)).toBe('COMMIT');
});