Job#finished never resolves when is job removed [BUG]
Created by: misos1
Description
When calling Job#finished on job which is already removed by call to Job#remove or has removeOnComplete true in JobOpts then this function never resolves or rejects.
Minimal, Working Test code to reproduce the issue.
First test case:
let Queue = require("bull");
let queue = new Queue("queue");
queue.process(_job => console.log("started"));
(async function()
{
let job = await queue.add({});
await job.finished(); // ensure job finished so we can remove it, we could also wait here some time
await job.remove();
console.log("removed");
await job.finished(); // finished on removed job never resolves or rejects
console.log("finished"); // this is never printed
})();
Second test case:
let Queue = require("bull");
let queue = new Queue("queue");
queue.process(_job => console.log("started"));
(async function()
{
let job = await queue.add({}, { removeOnComplete: true });
await job.finished(); // wait until is job completed and removed, also could be used await Promise.delay(1000)
console.log("finished 1");
await job.finished();
console.log("finished 2"); // this is never printed
})();
Bull version
3.10.0
Additional information
In function Job#finished is first check whether is job finished and if yes then it resolves or rejects immediately. In other case it is waiting for global events completed or failed and then either resolves or rejects but in case job is already removed isFinished probably returns that it is not finished and it will never fire completed or failed events.
Also it is not enough to check whether job exists here. Job#finished relies on assumption that job cannot be removed without firing completed or failed events. But it can be removed in case job is removed before it had chance to run. Job#finished must listen also for global:removed event. Unfortunately this event is still not implemented:
removeJob-9.lua:
-- TODO PUBLISH global event 'removed'
At last if would be listeners for global:completed and global:failed registered before call to isFinished then there would be no need to have that "watchdog" checking isFinished every 5 seconds.