I'm running StrongLoop's Loopback API server in production mode. This means that master process creates as many workers, how many cores your CPU has. So master process only controls workers and never execute your code.
My purpose is to execute periodic task just once at the time, because now it is runs on all 4 workers.
Is there any suggestions, except cron or 'key lock' in Redis-like storage?
In iojs and node v0.12 it is possible to do an exclusive socket binding. This could be used as a form of locking similar to a filesystem based approach. The method is the same for both:
attempt exclusive access to resource
if success:
perform task
else:
do not perform task
With sockets you would do something like this:
net.createServer().on('error', function(err) {
console.log('did not get lock', err);
}).listen({ port: 4321, exclusive: true }, function() {
singleProcessTask();
this.close();
});
Note that exclusive: true is only required for cluster mode because it defaults to sharing sockets.
Similarly with fs.open:
fs.open('lock.file', 'wx', function(err, fd) {
if (err) {
console.log('did not get lock', err);
} else{
singleProcessTask();
fs.close(fd, function(err) {
// insert error handling here
fs.unlink('lock.file', function(err) {
// insert error handling here
});
});
});
In both cases there is potential for race conditions if your task is very quick and your processes are on slightly different timer schedules. In these cases the task will still only be performed by one process at a time, but it may be processed multiple times per scheduled period depending on how you implement your scheduling.
edit: more illustrative example
var net = require('net');
var HOUR = 60*60*1000;
setInterval(myTask, HOUR);
function myTask() {
locked(function() {
// task code here
});
}
function locked(fn) {
net.createServer().on('error', function(err) {
console.log('did not get lock', err);
}).listen({ host: '127.0.0.1', port: 4321, exclusive: true }, function() {
fn();
this.close();
});
}