Periodical tasks with node-cron

Maybe you are familiar with cron (http://en.wikipedia.org/wiki/Cron). It's a Unix-based task scheduling system that makes running tasks easy. One problem with it is that it's linked to your platform, and it's not trivial to turn it on and off from code.

Meet node-cron (https://github.com/ncb000gt/node-cron). It's basically the same task scheduler but it runs directly from your Node application, so as long as it is up, your jobs should run.

Our strategy is simple: Periodically select all meetings that need mailing, call our mailer with each of these meetings, and then mark it as emailed.

Following this app's convention, let's separate concerns into their own folders, starting with src/tasks/index.js, as shown in the following code:

var CronJob = require('cron').CronJob;

module.exports = function(models, mailer) {
  var tasks = {};

  tasks.followupMail = require('./followupMail')(models,mailer);

  tasks.init = function() {
    (new CronJob('00 */15 * * * *', tasks.followupMail)).start();
  };

  return tasks;
}

It needs to take models and mailer as parameters, which can be used inside tasks. followupMail is the single user defined for now because it's all we need. The exported method init is what will kick start the cron job, the timer presenting respectively: 00 defined as the seconds, meaning it will run at second 00, for every */15 minutes, any hour, any day of the month, any month, any day of the week. For the actual task, see src/mailer/followUp.js

'''
module.exports = function(Model, mailer) {
  return function() {
    Model.Meeting.needMailing(function(err,meetings) {
      if(err) return console.warn("needMailing", err);
      if(!meetings || meetings.length < 1) return;
      meetings.forEach(function(meeting) {
        mailer.followUp(meeting, function(err) {
          if(err) return console.warn("needMailing followup failed "+meeting._id.toString(), err);
          Model.Meeting.markAsMailed(meeting._id);
        });
      });
      Model.Meeting.markAsMailed(meetings);
    });
  };
};
'''

It returns a function, which when executed, looks up all meeting documents that still need to be mailed and for each one, use mailer.followUp as we defined before and upon completion, mark each email as sent. Notice that fails here have nowhere to communicate and that's because it's an automated task. It's important for web servers to have meaningful log reporting, so in this case, the warning messages should be reported.

Of course, this would require us to add two methods to src/models/meeting.js, which you should be able to easily make sense of by now:

  // all meetings that are due and not mailed yet
  methods.needMailing = function(cb) {
    Meeting.find({
      at: {$lt: new Date},
      mailed: {$exists: false}
    },cb);
  };

  // mark a meeting as mailed
  methods.markAsMailed = function(id,cb) {
    Meeting.findAndModify({
      query: {
        _id: id
      },
      update:{
        $set: {mailed: new Date()}
      }
    },cb);
  };

For our final test, we'll be creating four users implying 2 meetings, travel 2 days in the future and try sending the emails through the task, it should work and mark both emails as sent.

  • Clear DB
  • Register users 1, 2, 3, and 4 at the same location
  • Travel time after the meeting is done
  • Task should send an email
  • Verify that the emails were sent
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.206.254