-
Notifications
You must be signed in to change notification settings - Fork 414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Omission of Delayed creation for RepeatJob #2744
Comments
Second this. We faced the same issue! |
To address this issue, when adding to the class RepeatJobService {
constructor(private readonly queue: Queue) {}
async startJob() {
const options = {
repeat: '0 * * * *',
// Additional Options
prevMillis: (await this.queue.getCompleted())[0].opts.prevMillis || 0,
};
return await this.queue.add(jobName, jobData, options);
}
} I believe that when using However, if modifying the core logic is difficult due to potential side effects, a viable alternative would be to include this information in the official documentation and comments. |
hi guys, I tried to replicate your case but I couldn't, could you pls take a look on my test case that I added and let me know how you are reproducing it |
Hi, The issue occurs within the Specifically, it happens in the Below is a portion of the // Check if we reached the end date of the repeatable job
let now = Date.now();
const { endDate } = repeatOpts;
if (!(typeof endDate === undefined) && now > new Date(endDate!).getTime()) {
return;
}
const prevMillis = opts.prevMillis || 0;
now = prevMillis < now ? now : prevMillis;
const nextMillis = await this.repeatStrategy(now, repeatOpts, name);
const { every, pattern } = repeatOpts; If the Below is the export const getNextMillis = (
millis: number,
opts: RepeatOptions,
): number | undefined => {
const pattern = opts.pattern;
if (pattern && opts.every) {
throw new Error(
'Both .pattern and .every options are defined for this repeatable job',
);
}
if (opts.every) {
return (
Math.floor(millis / opts.every) * opts.every +
(opts.immediately ? 0 : opts.every)
);
}
const currentDate =
opts.startDate && new Date(opts.startDate) > new Date(millis)
? new Date(opts.startDate)
: new Date(millis);
const interval = parseExpression(pattern, {
...opts,
currentDate,
});
try {
if(opts.immediately){
return new Date().getTime();
} else {
return interval.next().getTime();
}
} catch (e) {
// Ignore error
}
}; Here, it takes Based on the test you shared, it seems the issue can be reproduced by modifying it to add a repeat job with the same job name after restarting the worker following Currently, I am outside, so if possible, I will write a PR that includes the test code later. |
@Feelw00 the job that was created in a given iteration includes prevMillis in its options. Therefore when you promote a given delayed job, and this job is processed, it will add the next iteration based on the job's prevMillis. So this method should work. Now I am confused why a "server restart" is required in order to reproduce the issue, maybe you can give more context. |
Hi, As you commented, during the However, when the worker is restarted in this state, it seems that due to the issue, already completed delayed jobs are being generated and overwritten as completed jobs. In my operating environment, server restarts mostly occur due to deployments. We are currently using a container environment with K8s, and deployments happen several times a day. Besides deployments, there may also be situations where we need to restart the worker due to server load or unexpected errors. Would this explanation provide sufficient justification for fixing the issue? |
This sounds really strange to me. Could provide a test that demonstrates this issue for us so that we can look into? |
Hi, As I mentioned in the PR, In my service, the missing However, I still believe this issue needs to be resolved. What are your thoughts? |
@Feelw00 as soon as we have a reproducible test case we can look into it. |
thank you @Feelw00, your test case was useful. I create a pr to address it |
Hi,
After prioritizing the execution of a RepeatJob through Promote, the creation of Delayed is omitted when the server restarts.
There is a RepeatJob scheduled to run every day at 09:00. However, if I promote this job to prioritize its execution through the Bull Dashboard and then restart the server, the job is not created in Delayed, resulting in an issue.
This issue arises because, due to the nature of RepeatJob, a Completed Job with the same ID already exists.
When the
getNextMillis
function in thesrc/classes/repeat.ts
file calculates the next execution time, it generates an ID based on the current time without checking for existing Completed Jobs, leading to this issueTo resolve this issue, I modified the process to check for Completed Jobs using the
getCompleted
method of theQueueGetters
class before executing theadd
method of theQueue
class.This allows us to retrieve the
prevMillis
value of the most recent job and include it in theopts
object when creating a new job with theadd
methodWhen using RepeatJob, this issue may cause regularly scheduled jobs to be missed. I would appreciate it if you could consider adding a fix for this to the core
Here is an example code to resolve the issue.
The text was updated successfully, but these errors were encountered: