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();
});
}