import assert from 'node:assert/strict'; import { OutboxRepository } from '../dist/tasks/outbox-repository.js'; import { retryDelayMs, taskTypes } from '../dist/tasks/task-repository.js'; import { TaskWorker } from '../dist/tasks/worker.js'; assert.deepEqual(taskTypes, [ 'notification.dispatch', 'order.advance', 'device.command', 'refund.query', 'statistics.aggregate', 'outbox.publish' ]); assert.equal(retryDelayMs(1), 1000); assert.equal(retryDelayMs(4), 8000); assert.equal(retryDelayMs(99), 60 * 60 * 1000); const outboxCalls = []; const outbox = new OutboxRepository({ async execute(sql, params) { outboxCalls.push([sql, params]); return [{ insertId: 7, affectedRows: 1 }, []]; } }); assert.deepEqual( await outbox.append({ tenantId: '1', aggregateType: 'order', aggregateId: '88', eventType: 'order.paid', idempotencyKey: 'order:88:paid', payload: { orderId: '88' } }), { id: '7', created: true } ); assert.match(outboxCalls[0][0], /INSERT IGNORE INTO qipai_outbox_events/); const calls = []; const task = { id: '42', tenantId: '1', taskType: 'notification.dispatch', idempotencyKey: 'notice:42', payload: { channel: 'test' }, status: 'RUNNING', attempts: 1, maxAttempts: 3 }; const repository = { async claimNext() { calls.push('claim'); return task; }, async complete(id) { calls.push(`complete:${id}`); return true; }, async fail() { calls.push('fail'); } }; const worker = new TaskWorker({ repository, handlers: new Map([['notification.dispatch', async (claimed) => { calls.push(`handle:${claimed.id}`); }]]), workerId: 'test-worker' }); assert.equal(await worker.runOnce(), true); assert.deepEqual(calls, ['claim', 'handle:42', 'complete:42']); const failedCalls = []; const failedWorker = new TaskWorker({ repository: { async claimNext() { return task; }, async complete() { return true; }, async fail(claimed, workerId, error) { failedCalls.push([claimed.id, workerId, error.message]); } }, handlers: new Map(), workerId: 'test-worker' }); assert.equal(await failedWorker.runOnce(), true); assert.deepEqual(failedCalls, [['42', 'test-worker', 'No handler registered for task type notification.dispatch.']]); console.log('PASS: M01-C task retry and worker contracts are present.');