Motivation
Having just implemented a server-side task scheduler with Meteor that allows the user to schedule a given task to take place exactly once in the future, and then answered a question on the same subject on Stack Overflow, I thought I’d share my method here.
Synced-Cron
As the number of Meteor packages on Atmosphere increases exponentially, one of the best guarantees of quality is the percolate
namespace. They’ve released the excellent synced-cron
package, which is far more powerful than the requirements of this use case, but it still works better than any other package I’ve come across.
$ meteor add percolate:synced-cron
Set up your task and a schedule collection
Set up a server-side collection to store your tasks in case of server reboot, and the body of the task you want to complete (in this case, sending an email).
FutureTasks = new Meteor.Collection('future_tasks'); // server-side only
// In this case, "details" should be an object containing a date, plus required e-mail details (recipient, content, etc.)
function sendMail(details) {
Email.send({
from: details.from,
to: details.to,
etc....
});
}
Add functions to schedule and record your tasks
function addTask(id, details) {
SyncedCron.add({
name: id,
schedule: function(parser) {
return parser.recur().on(details.date).fullDate();
},
job: function() {
sendMail(details);
FutureTasks.remove(id);
SyncedCron.remove(id);
return id;
}
});
}
function scheduleMail(details) {
if (details.date < new Date()) {
sendMail(details);
} else {
var thisId = FutureTasks.insert(details);
addTask(thisId, details);
}
return true;
}
Process existing tasks on reboot, and start the Cron
Meteor.startup(function() {
FutureTasks.find().forEach(function(mail) {
if (mail.date < new Date()) {
sendMail(mail)
} else {
addTask(mail._id, mail);
}
});
SyncedCron.start();
});
Then, you can just call scheduleMail
from the server whenever you want to add a new task to the queue.
Conclusion
Hopefully, the code above is straightforward, as is the path to generalising to other use cases beyond sending email. If there are any questions or suggestions, just let me know.