← Wszystkie zadaniaNode.js · Senior
Kolejka zadań z ponowieniami i dead letter
Napisz createQueue({ handler, retries, backoffMs }). push(job) dodaje zadanie do kolejki i zwraca obietnicę z wynikiem handler(job, attempt). Zadania wykonują się po jednym, w kolejności dodania.
Jeśli handler rzuci błąd, zadanie jest ponawiane do retries razy z przerwą backoffMs, potem backoffMs * 2, backoffMs * 4... (wykładnicze opóźnienie). Gdy próby się skończą, obietnica odrzuca ostatnim błędem, a zadanie trafia do deadLetter(). Błąd jednego zadania nie zatrzymuje kolejki.
Ctrl+Enter uruchamia testy. Tab robi wcięcie; aby wyjść z edytora klawiaturą, naciśnij Esc, a potem Tab. Kod zapisuje się w tej przeglądarce.
Testy (6)
const q = createQueue({ handler: async (job) => job.n * 10, retries: 2, backoffMs: 5 }); expect(await q.push({ n: 4 })).toBe(40); expect(q.deadLetter()).toEqual([]);
let calls = 0; const q = createQueue({ handler: async () => { calls++; if (calls < 3) throw new Error('busy'); return 'done'; }, retries: 3, backoffMs: 5 }); expect(await q.push('job')).toBe('done'); expect(calls).toBe(3);
const handler = fn(async () => { throw new Error('bad payload'); }); const q = createQueue({ handler, retries: 2, backoffMs: 5 }); await expect(q.push({ id: 7 })).rejects.toThrow('bad payload'); expect(handler).toHaveBeenCalledTimes(3); expect(q.deadLetter()).toEqual([{ id: 7 }]);
const times = []; const start = Date.now(); const q = createQueue({ handler: async () => { times.push(Date.now() - start); throw new Error('x'); }, retries: 3, backoffMs: 20 }); await expect(q.push(1)).rejects.toThrow('x'); const gaps = times.slice(1).map((t, i) => t - times[i]); expect(gaps[0] >= 15 && gaps[1] >= 35 && gaps[2] >= 75).toBe(true);
const order = []; let active = 0; let maxActive = 0; const q = createQueue({ handler: async (job) => { active++; maxActive = Math.max(maxActive, active); await wait(10); order.push(job); active--; return job; }, retries: 0, backoffMs: 5 }); await Promise.all([q.push('a'), q.push('b'), q.push('c')]); expect(order).toEqual(['a', 'b', 'c']); expect(maxActive).toBe(1);
const q = createQueue({ handler: async (job) => { if (job === 'bad') throw new Error('nope'); return job; }, retries: 1, backoffMs: 5 }); const bad = q.push('bad').catch((e) => e.message); const good = q.push('good'); expect(await bad).toBe('nope'); expect(await good).toBe('good'); expect(q.deadLetter()).toEqual(['bad']);