diff --git a/lib/commands/cleanJobsInSet-3.lua b/lib/commands/cleanJobsInSet-3.lua index 98a98d906..bc43db38d 100644 --- a/lib/commands/cleanJobsInSet-3.lua +++ b/lib/commands/cleanJobsInSet-3.lua @@ -53,7 +53,8 @@ local jobTS -- - Once, if limit is -1 or 0 -- - As many times as needed if limit is positive while ((limit <= 0 or deletedCount < limit) and next(jobIds, nil) ~= nil) do - for _, jobId in ipairs(jobIds) do + local jobIdsLen = #jobIds + for i, jobId in ipairs(jobIds) do if limit > 0 and deletedCount >= limit then break end @@ -63,7 +64,10 @@ while ((limit <= 0 or deletedCount < limit) and next(jobIds, nil) ~= nil) do jobTS = rcall("HGET", jobKey, "timestamp") if (not jobTS or jobTS < maxTimestamp) then if isList then - rcall("LREM", setKey, 0, jobId) + -- Job ids can't be the empty string. Use the empty string as a + -- deletion marker. The actual deletion will occur at the end of the + -- script. + rcall("LSET", setKey, rangeEnd - jobIdsLen + i, "") else rcall("ZREM", setKey, jobId) end @@ -101,4 +105,8 @@ while ((limit <= 0 or deletedCount < limit) and next(jobIds, nil) ~= nil) do end end +if isList then + rcall("LREM", setKey, 0, "") +end + return deleted diff --git a/test/test_queue.js b/test/test_queue.js index 87fc4ea48..f3753000c 100644 --- a/test/test_queue.js +++ b/test/test_queue.js @@ -2983,6 +2983,16 @@ describe('Queue', () => { }); }); + it('should succeed when the limit is higher than the actual number of jobs', async () => { + await queue.add({ some: 'data' }); + await queue.add({ some: 'data' }); + await delay(100); + const deletedJobs = await queue.clean(0, 'wait', 100); + expect(deletedJobs).to.have.length(2); + const remainingJobsCount = await queue.count(); + expect(remainingJobsCount).to.be.eql(0); + }); + it("should clean the number of jobs requested even if first jobs timestamp doesn't match", async () => { // This job shouldn't get deleted due to the 5000 grace await queue.add({ some: 'data' });