From 4ad985070610b512030835d81a35d57b946ba5d1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 2 Jan 2026 16:40:11 -0500 Subject: [PATCH 1/2] Add tests for timeout retry tasks --- test/task.test.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/task.test.js b/test/task.test.js index 525d341..d1a1ed2 100644 --- a/test/task.test.js +++ b/test/task.test.js @@ -316,6 +316,52 @@ describe('Task', function() { assert.ok(repeated.scheduledAt.valueOf() === repeatTaskObj.scheduledAt.valueOf() + 60000); }); + it('creates a retry task when a timed out task has retryOnTimeoutCount', async function() { + Task.registerHandler('timeoutRetry', async () => { + // handler intentionally does nothing (we'll simulate a timeout) + }); + + const scheduledAt = new Date(now.valueOf() - 5000); + const startedRunningAt = new Date(now.valueOf() - 20000); + const timeoutAt = new Date(now.valueOf() - 1000); + + let timedOutTask = await Task.create({ + name: 'timeoutRetry', + scheduledAt, + startedRunningAt, + timeoutAt, + status: 'in_progress', + timeoutMS: 10000, + retryOnTimeoutCount: 2, + params: { foo: 'bar' } + }); + + await Task.expireTimedOutTasks(); + + timedOutTask = await Task.findById(timedOutTask._id); + assert.ok(timedOutTask); + assert.equal(timedOutTask.status, 'timed_out'); + assert.equal(timedOutTask.finishedRunningAt.valueOf(), now.valueOf()); + + const retryTask = await Task.findOne({ + name: 'timeoutRetry', + status: 'pending', + retryOnTimeoutCount: 1 + }); + assert.ok(retryTask, 'Retry task should be created'); + assert.equal(retryTask.scheduledAt.valueOf(), scheduledAt.valueOf()); + assert.strictEqual(retryTask.startedRunningAt, null); + assert.strictEqual(retryTask.finishedRunningAt, null); + assert.strictEqual(retryTask.workerName, null); + assert.strictEqual(retryTask.timeoutAt, null); + assert.strictEqual(retryTask.error, null); + assert.strictEqual(retryTask.result, null); + assert.equal( + retryTask.schedulingTimeoutAt.valueOf(), + now.valueOf() + 10 * 60 * 1000 + ); + }); + it('handles scheduling_timed_out tasks and schedules next repeat if needed', async function() { Task.registerHandler('delayedJob', async () => { // Will not be executed due to scheduling_timed_out logic From bf8ced3492f18b0acfeda5837f0368f48ba1243b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 2 Jan 2026 16:44:42 -0500 Subject: [PATCH 2/2] test improvements --- test/task.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/task.test.js b/test/task.test.js index d1a1ed2..a4f958e 100644 --- a/test/task.test.js +++ b/test/task.test.js @@ -354,7 +354,8 @@ describe('Task', function() { assert.strictEqual(retryTask.finishedRunningAt, null); assert.strictEqual(retryTask.workerName, null); assert.strictEqual(retryTask.timeoutAt, null); - assert.strictEqual(retryTask.error, null); + assert.deepStrictEqual(retryTask.toObject().params, { foo: 'bar' }); + assert.ok(retryTask.error.$isEmpty()); assert.strictEqual(retryTask.result, null); assert.equal( retryTask.schedulingTimeoutAt.valueOf(),