fix: recover transient coordinator dead letters
This commit is contained in:
+55
-1
@@ -10,7 +10,7 @@ const { decide } = require('../src/autonomy/policy');
|
||||
const { validatePaperIntent, createSimulator } = require('../src/autonomy/execution');
|
||||
const { calculateOutcome } = require('../src/autonomy/outcomes');
|
||||
const { createOrderIntent } = require('../src/autonomy/orderIntents');
|
||||
const { reconcileArchiveBatch, reconcileLiveBatch } = require('../workers/autonomyWorker');
|
||||
const { enqueueCoordinatorEvent, reconcileArchiveBatch, reconcileLiveBatch } = require('../workers/autonomyWorker');
|
||||
const { scheduleNext } = require('../workers/replayWorker');
|
||||
|
||||
test('autonomy schema and leased jobs are restart-safe', () => {
|
||||
@@ -143,6 +143,60 @@ test('archive reconciliation prioritizes recent usable events and is bounded', (
|
||||
assert.equal(live.scanned, 1);
|
||||
});
|
||||
|
||||
test('archive reconciliation recovers transient dead-lettered coordinator jobs', () => {
|
||||
const intelligence = new Database(':memory:');
|
||||
initAutonomySchema(intelligence);
|
||||
enqueueJob(intelligence, {
|
||||
jobType: 'coordinator_event', lane: 'historical', priority: 10, entityType: 'event', entityId: 99,
|
||||
idempotencyKey: 'coordinator_event:99',
|
||||
});
|
||||
intelligence.prepare(`
|
||||
UPDATE autonomy_jobs
|
||||
SET status='dead_letter', attempts=5, last_error='TypeError: fetch failed'
|
||||
WHERE idempotency_key='coordinator_event:99'
|
||||
`).run();
|
||||
|
||||
const result = enqueueCoordinatorEvent(intelligence, {
|
||||
event_id: 99,
|
||||
ingested_at: new Date().toISOString(),
|
||||
content: 'content',
|
||||
has_embedding: 1,
|
||||
});
|
||||
assert.equal(result.recovered, true);
|
||||
const job = intelligence.prepare("SELECT status, lane, priority, attempts, last_error FROM autonomy_jobs WHERE idempotency_key='coordinator_event:99'").get();
|
||||
assert.equal(job.status, 'pending');
|
||||
assert.equal(job.lane, 'live');
|
||||
assert.equal(job.priority, 100);
|
||||
assert.equal(job.attempts, 0);
|
||||
assert.match(job.last_error, /Recovered transient coordinator failure/);
|
||||
});
|
||||
|
||||
test('archive reconciliation leaves non-transient coordinator dead letters alone', () => {
|
||||
const intelligence = new Database(':memory:');
|
||||
initAutonomySchema(intelligence);
|
||||
enqueueJob(intelligence, {
|
||||
jobType: 'coordinator_event', lane: 'historical', priority: 10, entityType: 'event', entityId: 100,
|
||||
idempotencyKey: 'coordinator_event:100',
|
||||
});
|
||||
intelligence.prepare(`
|
||||
UPDATE autonomy_jobs
|
||||
SET status='dead_letter', attempts=5, last_error='no tradable instruments are allowlisted'
|
||||
WHERE idempotency_key='coordinator_event:100'
|
||||
`).run();
|
||||
|
||||
const result = enqueueCoordinatorEvent(intelligence, {
|
||||
event_id: 100,
|
||||
ingested_at: new Date().toISOString(),
|
||||
content: 'content',
|
||||
has_embedding: 1,
|
||||
});
|
||||
assert.equal(result.recovered, false);
|
||||
const job = intelligence.prepare("SELECT status, attempts, last_error FROM autonomy_jobs WHERE idempotency_key='coordinator_event:100'").get();
|
||||
assert.equal(job.status, 'dead_letter');
|
||||
assert.equal(job.attempts, 5);
|
||||
assert.equal(job.last_error, 'no tradable instruments are allowlisted');
|
||||
});
|
||||
|
||||
test('outcome calculation uses benchmark-relative return', () => {
|
||||
const outcome = calculateOutcome(
|
||||
{ information_cutoff: '2026-01-02T00:00:00Z', horizon_days: 5, direction: 'positive' },
|
||||
|
||||
Reference in New Issue
Block a user