From 1fb15628dc5912e83220d430aa14e19e90d1cc53 Mon Sep 17 00:00:00 2001 From: Rogger Valverde Date: Thu, 16 May 2024 23:17:05 -0600 Subject: [PATCH] fix(job): validate job existence when adding log (#2738) --- lib/commands/addLog-2.lua | 30 ++++++++++++++++++++++++++++++ lib/job.js | 3 +-- lib/scripts.js | 16 ++++++++++++++++ test/test_job.js | 10 ++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 lib/commands/addLog-2.lua diff --git a/lib/commands/addLog-2.lua b/lib/commands/addLog-2.lua new file mode 100644 index 000000000..92748de9a --- /dev/null +++ b/lib/commands/addLog-2.lua @@ -0,0 +1,30 @@ +--[[ + Add job log + + Input: + KEYS[1] job id key + KEYS[2] job logs key + + ARGV[1] id + ARGV[2] log + ARGV[3] keepLogs + + Output: + -1 - Missing job. +]] +local rcall = redis.call + +if rcall("EXISTS", KEYS[1]) == 1 then -- // Make sure job exists + local logCount = rcall("RPUSH", KEYS[2], ARGV[2]) + + if ARGV[3] ~= '' then + local keepLogs = tonumber(ARGV[3]) + rcall("LTRIM", KEYS[2], -keepLogs, -1) + + return math.min(keepLogs, logCount) + end + + return logCount +else + return -1 +end diff --git a/lib/job.js b/lib/job.js index 246e00a3e..8bf21075a 100644 --- a/lib/job.js +++ b/lib/job.js @@ -394,8 +394,7 @@ Job.prototype.retry = function() { * */ Job.prototype.log = function(logRow) { - const logsKey = this.toKey(this.id) + ':logs'; - return this.queue.client.rpush(logsKey, logRow); + return scripts.addLog(this.queue, this.id, logRow); }; Job.prototype.isCompleted = function() { diff --git a/lib/scripts.js b/lib/scripts.js index f3aed40a8..27705d8c3 100644 --- a/lib/scripts.js +++ b/lib/scripts.js @@ -67,6 +67,22 @@ const scripts = { return queue.client.pause(keys.concat([pause ? 'paused' : 'resumed'])); }, + async addLog(queue, jobId, logRow, keepLogs) { + const client = await queue.client; + + const keys = [queue.toKey(jobId), queue.toKey(jobId) + ':logs']; + + const result = await client.addLog( + keys.concat([jobId, logRow, keepLogs ? keepLogs : '']) + ); + + if (result < 0) { + throw scripts.finishedErrors(result, jobId, 'addLog'); + } + + return result; + }, + moveToActive(queue, jobId) { const queueKeys = queue.keys; const keys = [queueKeys.wait, queueKeys.active, queueKeys.priority]; diff --git a/test/test_job.js b/test/test_job.js index 1846e28e8..ec538fd9e 100644 --- a/test/test_job.js +++ b/test/test_job.js @@ -593,6 +593,16 @@ describe('Job', () => { .then(logs => expect(logs).to.be.eql({ logs: [], count: 0 })) ); }); + + describe('when job was removed', () => { + it('throws an error', async () => { + const job = await Job.create(queue, { foo: 'bar' }); + await job.remove(); + await job.log('some log text 1').catch(err => { + expect(err.message).to.be.equal('Missing key for job 1 addLog'); + }); + }); + }); }); describe('.moveToCompleted', () => {