Scheduling Tasks in Node.js Using Timers instead of Scheduled Cron Jobs - node.js

This is my objective:
5 minutes after the last document update, I want to execute a one-time task
So this is what the flow of actions will look like:
User updates document - timer is started and counts down from 5 minutes
If user updates the same document again and the previous timer (identified by the document._id) is running still, reset that timer back to 5 minutes and repeat countdown
When timer has elapsed - the one time task is executed
I have not done something like this before and I am at a loss at where to begin.
I can hook into document changes easily using methods available in Mongoose (i.e. on save, do func to setup or reset timer)
However, I cannot figure out the way to:
create a timer that waits 5 minutes - then executes a task
making the timer accessible so that I can reset the timer
making the timer accessible so I can add extra variables which will be used in the funtion when timer has elapsed
I've investigated Cron jobs but they seem to tasks that schedule at the same time everyday.
I need a timer that delays a task, but also the ability to reset that timer, and add extra data to the timer.
Any hints appreciated.

This is the solution I managed to complete up with.
First of all, it's worth noting that my original assumptions are correct:
Cron jobs are great for repetitive, tasks that are scheduled at the same time everyday. However, for tasks that are created on the fly, and have a countdown element, then cron jobs isn't the right tool.
However, enter node-schedule (https://www.npmjs.com/package/node-schedule)
Node Schedule is a flexible cron-like and not-cron-like job scheduler for Node.js. It allows you to schedule jobs (arbitrary functions) for execution at specific dates, with optional recurrence rules. It only uses a single timer at any given time (rather than reevaluating upcoming jobs every second/minute).
The use of timers is really what these, on-the-fly tasks need.
So my solution looks like this:
var schedule = require('node-schedule'),
email_scheduler = {};
email_scheduler["H1e5nE2GW"] = schedule.scheduleJob(Date.now() + 10000, function(){
console.log('its been a total of 10 seconds since initalization / reset.');
});
var second_attempt = schedule.scheduleJob(Date.now() + 5000, function(){
console.log("5 seconds elapsed from start, time to reset original scheduled job");
email_scheduler["H1e5nE2GW"].cancel();
email_scheduler["H1e5nE2GW"] = schedule.scheduleJob(Date.now() + 10000, function(){
console.log('its been a total of 10 since last one seconds.');
});
schedule.scheduleJob(Date.now() + 5000, function(){
console.log("it's been another 5 seconds since reset");
});
});
My thinking (though not yet tested) is that I can create a singleton-like instance for the email_scheduler object by creating a node module. Like such:
// node_modules/email-scheduler/index.js
module.exports = {};
This way, I can access the scheduleJobs and reset the timers in every file of the node application.

You can use events for that. call a event with some parameter and before your task add sleep and exec your task. But add sleep or settimeout is not a good idea in nodejs.

I had the same puzzle but I ended settling on the javascript native functions.
function intervalFunc() {
//inside this function you can request to get the date and time then decide what to do and how to do it
autogens.serverAutoGenerate();//my function to autogenerate bills
}
setInterval(intervalFunc, 1000);//repeat task after one seconds
Adding the code at the index file or entry file of your node js application will make the function repeatedly execute. You can opt to change the frequency depending on your needs. If you wanted to run the cronjob three times a day, get the number of seconds in 24 hours then divide by 3. If you wanted to run the job on a specific hour, by using the new Date(), you can check to determine if it is the right hour to execute your event or not.

Related

I want a function that will decrement a value automatically everyday

I'm working on an web application using NodeJS and MongoDB/Mongoose, and I want to create a method that everyday, at some hour, will automatically decrement a value from a field by 1.
Can you help me, please?
Use setInterval() If you just want to run it every day at the same time.
setInterval(() => {
// your code
}, 86400000);
where 86400000 is the amount of milliseconds in a day.
If you want more control over the timing, I recommend using node-cron.
And of course your program needs to run on a server for it to run forever. Or you could leave your computer on forever, but that wouldn't be quite ideal.

What is better way to making longer delay inside a series of tasks?

I'm trying to build a workflow system, which will process a series of tasks & delays. Delay can be changed or removed from a running workflow.
What is the better way to making longer delay inside a series of tasks? (Like 3-4 months). Right now two ways are pocking around my head:
Pre-calculating & saving delay time. Setup a scheduler that will check delay repeatedly after a specific interval(1 minute maybe). This will make a lot of database queries, but the delay can be changed instantly.
Schedule a job for a delay. This can reduce a lot of database queries &, but the problem is maintaining & changing delay in these long-running jobs. Also, these jobs need to survive a server crash or restart.
Right now I'm not sure how to do it in a better way and still studying about it. If anyone has a similar experience, please share.
You can store the tasks into the database, like :
{
_id: String,
status: Enum,
executionTime: timestamp,
}
When you declare a new task, push a new entry into the DB.
At your server start, or when a new task is declared, create a setTimeout that will wake up your node.js when it's necessary.
Optimization
To avoid having X setTimeout, with X the number of task to execute. Keep only one setTimeout, with the time to wait equals to the closest task to execute.
For example, you have three task, one must run in 1 hour, one in 2 hour and one in 3 hour. Use a setTimeout of 1 hour. When it get triggered, it execute the task 1 and then look at the remaining tasks to re-run.

How to frequent compare 2 dates for a huge set of objects (as cronjob) - nodejs

My system has tasks that has a deadline (as date stored in the database) differ from task to another, I want to check frequently for these tasks if they exceed their deadline (basically with the current date I guess), and if so send a notification or execute a function
How can I make this function to be executed as cronjob or as it is without the help of cronjob.
I want to do this without making heavy load on the server
I'm using Express and sequelize as ORM
I did see node-cron as scheduler but i don't have the idea to implement something like this
I would appreciate any help :)
You can use later package for this tasl like that:
https://github.com/bunkat/later
var later = require('later');
later.date.UTC();
const DEDLINE_SCHEDULE = later.parse.text('every 1 min');
later.setInterval(createNotificationJob(), DEDLINE_SCHEDULE);
function createNotificationJob() {
// check are tasks exceed their dedline
}
and then every 1 minute you can check that if tasks exceed their deadline and send notification.

Most Ideal Way to Run a Scheduled Job with Angular-Meteor

I'm writing an appointment scheduling app with angular-meteor. One of the requirements is that a text notification be sent out to the customer who made the appointment. The customer provides a cell number. But basically, all I want to do is send out an email X many minutes before the appointment time. Running off the angular-meteor stack, what might be the best way to do this? All of the appointment information is saved to a mongo db.
You might be interested in Meteor job-collection package (not specific to angular-meteor):
A persistent and reactive job queue for Meteor, supporting distributed workers that can run anywhere.
job-collection is a powerful and easy to use job manager designed and built for Meteor.js.
It solves the following problems (and more):
Schedule jobs to run (and repeat) in the future, persisting across server restarts
[…]
In particular job.after(someTimeBeforeAppointment)
// Server
var myJobs = JobCollection('myJobQueue');
// Start the myJobs queue running
myJobs.startJobServer();
// Create a Job (e.g. in a Meteor method)
var job = new Job(myJobs, 'jobType', jobData);
// Specify when it can run and save it.
job.after(someTimeBeforeAppointment).save();
// Server (or could be a different server!)
// How jobs should be processed.
myJobs.processJobs('jobType', function (job, done) {
var jobData = job.data;
// Do something… could be asynchronous.
job.done(); // or job.fail();
// Call done when work on this job has finished.
done();
});
The pollInterval can be specified in processJobs options. Default is every 5 seconds.
Write a node script that sends an email to every customer who has an appointment between X minutes and X+10 minutes from the time of running. Once the email is sent, set a boolean flag on the appointment in mongo so it doesn't get sent twice.
Run a cron that triggers it every 5 minutes.
The overlap should make sure that nothing slips though the cracks, and the flag will prevent multiples from being sent.

How node-scheduler working in this scenerio

I am new in NodeJs and now I want to use node-scheduler, but i have just one query, please give me suggestion regarding this.
https://github.com/node-schedule/node-schedule
When I setup a scheduler that run in every 5 Minutes, If the scheduler does
not completed within 5 minutes. So my question is that then the scheduler
will start another thread or not?
Please solve my query.
Thanks.
Since jobs don't seem to have a mechanism to let the scheduler know they are done, jobs will be scheduled according to their scheduled time alone.
In other words: if you schedule a job to run every 5 minutes, it will be started every 5 minutes, even if the job itself takes more than 5 minutes to complete.
To clarify: this doesn't start a new thread for each job, as JS is single-threaded. If a job blocks the event loop (for instance by doing heavy calculations), it is possible for the scheduler to not be able to start a new job when its time has arrived, but blocking the event loop is not a good thing.

Resources