Files
jobqueue/tests/RetryStrategy.test.ts

73 lines
1.8 KiB
TypeScript

import { RetryStrategy } from '../src/index.js';
describe('RetryStrategy', () => {
it('uses exponential backoff for recoverable errors', async () => {
const strategy = new RetryStrategy({
maxAttempts: 4,
baseDelayMs: 100,
classifyError: async () => 'recoverable',
});
const decision = await strategy.shouldRetry(new Error('boom'), {
id: 'job-1',
status: 'active',
data: {},
currentPhase: 'run',
phases: [],
phaseResults: {},
progress: 0,
progressMessage: null,
error: null,
retryCount: 1,
maxAttempts: 4,
webhookUrl: null,
webhookSent: false,
createdAt: new Date().toISOString(),
startedAt: null,
completedAt: null,
updatedAt: new Date().toISOString(),
scheduledAt: null,
cancelledAt: null,
});
expect(decision.retry).toBe(true);
expect(decision.delayMs).toBe(200);
expect(decision.disposition).toBe('recoverable');
});
it('does not retry fatal errors', async () => {
const strategy = new RetryStrategy({
maxAttempts: 4,
classifyError: async () => 'fatal',
});
const decision = await strategy.shouldRetry(new Error('fatal'), {
id: 'job-1',
status: 'active',
data: {},
currentPhase: 'run',
phases: [],
phaseResults: {},
progress: 0,
progressMessage: null,
error: null,
retryCount: 0,
maxAttempts: 4,
webhookUrl: null,
webhookSent: false,
createdAt: new Date().toISOString(),
startedAt: null,
completedAt: null,
updatedAt: new Date().toISOString(),
scheduledAt: null,
cancelledAt: null,
});
expect(decision).toEqual({
retry: false,
delayMs: 0,
disposition: 'fatal',
});
});
});