bullmq
bullmq copied to clipboard
Repeat options startDate and every are incompatible
When both startDate
and every
are set on a job, startDate
is ignored.
I think the code responsible for this is here.
My use case was to use the startDate in order to spread repeatable jobs during the day. I want them to run once every day, but not at the same time.
If you are open to a PR, I can change the getNextMillis
implementation to repeat at a given interval based on the startDate.
Otherwise it would be probably nice to:
- mention in the docs that startDate will be ignored if
every
is set - throw an exception during job construction, to notify that this use case will not work
In case someone else have the issue, in the meantime you can fix the problem by providing a repeat strategy.
import { getNextMillis, RepeatOptions } from 'bullmq';
export function syncRepeatStrategy(
millis: number,
opts: RepeatOptions,
): number {
if (!opts.startDate || !opts.every) {
return getNextMillis(millis, opts);
}
const startMillis = new Date(opts.startDate).getTime();
if (millis < startMillis) {
return startMillis;
}
return (
startMillis + Math.ceil((millis - startMillis) / opts.every) * opts.every
);
}
And pass it to the Queue constructor:
new Queue('queue', { settings: { repeatStrategy: syncRepeatStrategy } });
@richardgarnier thank you for making this issue and providing the workaround! I found it very helpful.
Just a quick note, the getNextMillis
function returns number | undefined
which isn't compatible with your syncRepeatStrategy
.
It's also possible to import the RepeatStrategy type from bullmq:
https://github.com/taskforcesh/bullmq/blob/4c548735d3c2489f2bdc1cfa870703db6f11f752/src/types/repeat-strategy.ts#L3-L7 which allows us to rewrite syncRepeatStrategy
as:
import { getNextMillis, RepeatStrategy } from 'bullmq';
export const syncRepeatStrategy: RepeatStrategy = (millis, opts) => {
if (!opts.startDate || !opts.every) {
return getNextMillis(millis, opts);
}
const startMillis = new Date(opts.startDate).getTime();
if (millis < startMillis) {
return startMillis;
}
return (
startMillis + Math.ceil((millis - startMillis) / opts.every) * opts.every
);
};
An alternative solution is to use the pattern
and startDate
in the RepeatOptions
, my use case was to trigger a job once a day in specific time, so i need to trigger that every 24hr after startDate or pass the pattern option:
This will be triggered every day at 06:36 PM