Reputation: 21
I need to run a node-cron task that invokes an async function, which returns a Moment object as the next scheduled time. However, I found that it cannot enter the cron.schedule method twice, and the code gets stuck. Can you guys help me figure out where the problem is?
THE CODE
import cron from 'node-cron';
import moment, {Moment} from 'moment-timezone';
const doTask = async (): Promise<Moment>=> {
const currentMo = moment()
const nextMo = currentMo.add(10, 'seconds')
console.log('do tasking....')
console.log(`doTask: next schedule time ${nextMo.format('YYYY-MM-DD HH:mm:ss')}`)
return nextMo
}
class ScheduleManager {
private task: cron.ScheduledTask | null = null;
constructor(private scheduleTime: string) {
this.scheduleTask(this.scheduleTime);
}
private scheduleTask(cronExpress: string) {
if (this.task) {
console.log(`stop current task`)
this.task.stop();
}
console.log(`start new task with cronExpress: ${cronExpress}`)
this.task = cron.schedule(cronExpress, async () => {
const currentMoment = moment()
console.log('Scheduled task triggered at:', currentMoment.format('YYYY-MM-DD HH:mm:ss'));
const nextMoment = await doTask();
this.rescheduleAtMoment(nextMoment);
});
}
private rescheduleAtMoment(nextMoment: Moment) {
const currentMoment = moment()
const delay = nextMoment.diff(currentMoment)
const duration = moment.duration(delay)
const nextCronExpress = nextMoment.format('ss mm HH DD MM ddd')
console.log('next schedule time:', nextMoment.format('YYYY-MM-DD HH:mm:ss'));
const hours = Math.floor(duration.asHours());
const minutes = Math.floor(duration.asMinutes()) % 60;
const seconds = Math.floor(duration.asSeconds()) % 60;
const formattedCountdown = `${hours}Hours,${minutes}Minutes,${seconds}Seconds`;
console.log(`next schedule time countdown: ${formattedCountdown}`)
setTimeout(() => {
console.log(`setTimeout Invoke`)
this.scheduleTask(nextCronExpress);
}, delay);
}
}
const initialScheduleTime = moment().add(5, 'seconds').format('ss mm HH DD MM ddd')
const scheduleManager = new ScheduleManager(initialScheduleTime);
Expected to happen
ScheduleManager continuously calls its own scheduleTask through the rescheduleAtMoment method to achieve self-driving
what actually happened
When ScheduleManager enters scheduleTask for the second time, the code is stuck at
console.log(`start new task with cronExpress: ${cronExpress}`)
Reproduce
npm install node-cron moment-timezone
npm install -g ts-node
# save above code in to test.ts file
ts-node test.ts
I hope to create an automatically driven node-cron task that schedules a task to get the next expected scheduling time. Then, using setTimeout
, reschedule a new task at the next scheduled time.
Upvotes: 2
Views: 28