Revert "fix(queue): dead/cancelled jobs no longer block idempotency re-submission (#2253)"

This reverts commit c0cb6c533b.
This commit is contained in:
Garry Tan
2026-07-23 05:03:38 -07:00
parent 6ec5261700
commit 3225bdf768
2 changed files with 1 additions and 83 deletions
+1 -16
View File
@@ -133,27 +133,12 @@ export class MinionQueue {
// 1. Idempotency fast path — if a row already exists for this key, return it
// without doing any other work. The unique partial index guarantees
// no second row can be inserted with the same non-null key.
//
// Dead/cancelled jobs represent permanently-failed work whose
// idempotency slot must be freed so a fresh attempt can be inserted.
// We NULL the key (preserving the row for audit) and fall through
// to the INSERT path below.
if (opts?.idempotency_key) {
const existing = await tx.executeRaw<Record<string, unknown>>(
`SELECT * FROM minion_jobs WHERE idempotency_key = $1`,
[opts.idempotency_key]
);
if (existing.length > 0) {
const existingJob = rowToMinionJob(existing[0]);
if (existingJob.status === 'dead' || existingJob.status === 'cancelled') {
await tx.executeRaw(
`UPDATE minion_jobs SET idempotency_key = NULL WHERE id = $1`,
[existingJob.id]
);
} else {
return existingJob;
}
}
if (existing.length > 0) return rowToMinionJob(existing[0]);
}
// 1b. Submission-time backpressure for high-frequency named jobs.
-67
View File
@@ -1582,73 +1582,6 @@ describe('MinionQueue: Idempotency', () => {
expect(j2.id).toBe(j1.id);
expect(j2.data).toEqual({ v: 1 }); // first wins
});
test('dead job with idempotency_key allows re-submission', async () => {
const j1 = await queue.add('test-synth', { prompt: 'synthesize' }, {
idempotency_key: 'dream:synth:test:abc123',
max_attempts: 1,
});
await engine.executeRaw(
`UPDATE minion_jobs SET status = 'dead', finished_at = now() WHERE id = $1`,
[j1.id]
);
const j2 = await queue.add('test-synth', { prompt: 'synthesize' }, {
idempotency_key: 'dream:synth:test:abc123',
max_attempts: 8,
});
expect(j2.id).not.toBe(j1.id);
expect(j2.status).toBe('waiting');
const oldRow = await engine.executeRaw<{ idempotency_key: string | null }>(
`SELECT idempotency_key FROM minion_jobs WHERE id = $1`,
[j1.id]
);
expect(oldRow[0].idempotency_key).toBeNull();
});
test('cancelled job with idempotency_key allows re-submission', async () => {
const j1 = await queue.add('test-synth', {}, {
idempotency_key: 'dream:synth:test:cancel',
});
await engine.executeRaw(
`UPDATE minion_jobs SET status = 'cancelled', finished_at = now() WHERE id = $1`,
[j1.id]
);
const j2 = await queue.add('test-synth', {}, {
idempotency_key: 'dream:synth:test:cancel',
});
expect(j2.id).not.toBe(j1.id);
expect(j2.status).toBe('waiting');
});
test('completed job with idempotency_key still blocks re-submission', async () => {
const j1 = await queue.add('sync', {}, {
idempotency_key: 'dream:synth:test:completed',
});
await engine.executeRaw(
`UPDATE minion_jobs SET status = 'completed', finished_at = now() WHERE id = $1`,
[j1.id]
);
const j2 = await queue.add('sync', {}, {
idempotency_key: 'dream:synth:test:completed',
});
expect(j2.id).toBe(j1.id);
expect(j2.status).toBe('completed');
});
test('active job with idempotency_key still blocks re-submission', async () => {
const j1 = await queue.add('sync', {}, {
idempotency_key: 'dream:synth:test:active',
});
await engine.executeRaw(
`UPDATE minion_jobs SET status = 'active' WHERE id = $1`,
[j1.id]
);
const j2 = await queue.add('sync', {}, {
idempotency_key: 'dream:synth:test:active',
});
expect(j2.id).toBe(j1.id);
expect(j2.status).toBe('active');
});
});
// --- v7 child_done auto-post ---