UNPKG

node-resque

Version:

an opinionated implementation of resque in node

350 lines (299 loc) 9.11 kB
import specHelper from "../utils/specHelper"; import { Scheduler, Queue, Worker } from "../../src"; let queue; let scheduler; const jobs = { brokenJob: { plugins: ["Retry"], pluginOptions: { Retry: { retryLimit: 3, retryDelay: 100, }, }, perform: () => { throw new Error("BUSTED"); }, }, happyJob: { plugins: ["Retry"], pluginOptions: { Retry: { retryLimit: 3, retryDelay: 100, }, }, perform: () => { // no return }, }, }; describe("plugins", () => { describe("retry", () => { beforeAll(async () => { await specHelper.connect(); await specHelper.cleanup(); queue = new Queue( { connection: specHelper.cleanConnectionDetails(), queue: [specHelper.queue], }, jobs ); scheduler = new Scheduler({ connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, }); await scheduler.connect(); scheduler.start(); await queue.connect(); }); afterAll(async () => { await scheduler.end(); await queue.end(); await specHelper.disconnect(); }); afterEach(async () => { await specHelper.cleanup(); }); test("will work fine with non-crashing jobs", async (done) => { await queue.enqueue(specHelper.queue, "happyJob", [1, 2]); const length = await queue.length(specHelper.queue); expect(length).toBe(1); const worker = new Worker( { connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, queues: [specHelper.queue], }, jobs ); worker.on("failure", () => { throw new Error("should not get here"); }); await worker.connect(); worker.on("success", async () => { const length = await specHelper.redis.llen( `${specHelper.namespace}:failed` ); expect(length).toBe(0); await worker.end(); done(); }); worker.start(); }); test("will retry the job n times before finally failing", async (done) => { await queue.enqueue(specHelper.queue, "brokenJob"); const length = await queue.length(specHelper.queue); expect(length).toBe(1); let failButRetryCount = 0; let failureCount = 0; const worker = new Worker( { connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, queues: [specHelper.queue], }, jobs ); worker.on("success", () => { failButRetryCount++; }); await worker.connect(); worker.on("failure", async () => { failureCount++; expect(failButRetryCount).toBe(2); expect(failureCount).toBe(1); expect(failButRetryCount + failureCount).toBe(3); const length = await specHelper.redis.llen( `${specHelper.namespace}:failed` ); expect(length).toBe(1); await worker.end(); done(); }); worker.start(); }); test("can have a retry count set", async (done) => { const customJobs = { jobWithRetryCount: { plugins: ["Retry"], pluginOptions: { Retry: { retryLimit: 5, retryDelay: 100, }, }, perform: () => { throw new Error("BUSTED"); }, }, }; await queue.enqueue(specHelper.queue, "jobWithRetryCount", [1, 2]); const length = await queue.length(specHelper.queue); expect(length).toBe(1); let failButRetryCount = 0; let failureCount = 0; const worker = new Worker( { connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, queues: [specHelper.queue], }, customJobs ); worker.on("success", () => { failButRetryCount++; }); await worker.connect(); worker.on("failure", async () => { failureCount++; expect(failButRetryCount).toBe(4); expect(failureCount).toBe(1); expect(failButRetryCount + failureCount).toBe(5); const length = await specHelper.redis.llen( `${specHelper.namespace}:failed` ); expect(length).toBe(1); await worker.end(); done(); }); worker.start(); }); test("can have custom retry times set", async (done) => { const customJobs = { jobWithBackoffStrategy: { plugins: ["Retry"], pluginOptions: { Retry: { retryLimit: 5, backoffStrategy: [1, 2, 3, 4, 5], }, }, perform: function (a, b, callback) { callback(new Error("BUSTED"), null); }, }, }; await queue.enqueue(specHelper.queue, "jobWithBackoffStrategy", [1, 2]); const length = await queue.length(specHelper.queue); expect(length).toBe(1); let failButRetryCount = 0; let failureCount = 0; const worker = new Worker( { connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, queues: [specHelper.queue], }, customJobs ); worker.on("success", () => { failButRetryCount++; }); await worker.connect(); worker.on("failure", async () => { failureCount++; expect(failButRetryCount).toBe(4); expect(failureCount).toBe(1); expect(failButRetryCount + failureCount).toBe(5); const length = await specHelper.redis.llen( `${specHelper.namespace}:failed` ); expect(length).toBe(1); await worker.end(); done(); }); worker.start(); }); test("when a job fails it should be re-enqueued (and not go to the failure queue)", async (done) => { await queue.enqueue(specHelper.queue, "brokenJob", [1, 2]); const worker = new Worker( { connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, queues: [specHelper.queue], }, jobs ); await worker.connect(); worker.on("success", async () => { const timestamps = await queue.scheduledAt( specHelper.queue, "brokenJob", [1, 2] ); expect(timestamps.length).toBe(1); const length = await specHelper.redis.llen( `${specHelper.namespace}:failed` ); expect(length).toBe(0); await worker.end(); done(); }); worker.start(); }); test("will handle the stats properly for failing jobs", async (done) => { await queue.enqueue(specHelper.queue, "brokenJob", [1, 2]); const worker = new Worker( { connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, queues: [specHelper.queue], }, jobs ); await worker.connect(); worker.on("success", async () => { const globalProcessed = await specHelper.redis.get( `${specHelper.namespace}:stat:processed` ); const globalFailed = await specHelper.redis.get( `${specHelper.namespace}:stat:failed` ); const workerProcessed = await specHelper.redis.get( `${specHelper.namespace}:stat:processed:${worker.name}` ); const workerFailed = await specHelper.redis.get( `${specHelper.namespace}:stat:failed:${worker.name}` ); expect(String(globalProcessed)).toBe("0"); expect(String(globalFailed)).toBe("1"); expect(String(workerProcessed)).toBe("0"); expect(String(workerFailed)).toBe("1"); await worker.end(); done(); }); worker.start(); }); test("will set the retry counter & retry data", async (done) => { await queue.enqueue(specHelper.queue, "brokenJob", [1, 2]); const worker = new Worker( { connection: specHelper.cleanConnectionDetails(), timeout: specHelper.timeout, queues: [specHelper.queue], }, jobs ); await worker.connect(); worker.on("success", async () => { const retryAttempts = await specHelper.redis.get( `${specHelper.namespace}:resque-retry:brokenJob:1-2` ); let failureData = await specHelper.redis.get( `${specHelper.namespace}:failure-resque-retry:brokenJob:1-2` ); expect(String(retryAttempts)).toBe("0"); failureData = JSON.parse(failureData); expect(failureData.payload).toEqual([1, 2]); expect(failureData.exception).toBe("Error: BUSTED"); expect(failureData.worker).toBe("brokenJob"); expect(failureData.queue).toBe("test_queue"); await worker.end(); done(); }); worker.start(); }); }); });