Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle concurrent file write requests on a node server with socket.io

How to handle concurrent file write requests on a node server with socket.io. I am using this to write:

fs.writefile('abc.txt','datatobewritten','utf8',function(err){});

I have a file abc.txt and suppose two users try to write on the same time on this file then I am getting an error, so how do I queue multiple requests.

like image 314
iniravpatel Avatar asked Mar 15 '16 11:03

iniravpatel


2 Answers

You have to synchronize the writes.

For a single instance of nodejs you can use simple queue, like this:

module.exports = function(path, content, cb){
    var queue = queues[path];
    if (queue == null)
        queue = queues[path] = new Queue;

    queue.add(path, content, (err) => {
        cb(err);
        queue.next();
    });         
};

var fs = require('fs');
var queues = {};

class Queue {
    constructor () {
        this.queue = [];
    }
    next () {
        if (this.queue.length === 0)
            return;

        var [path, content, cb] = this.queue[0];
        fs.writeFile(path, content, 'utf8', (err) => {
            this.queue.shift(); 
            cb(err);
        }); 
    }       
    add (...args) {
        this.queue.push(args);
        if (this.queue.length === 1) {
            this.next();
        }
    }
}

In multi-process instance you have to use some locking, for example with lockfile.

var lockFile = require('lockfile');
var fs = require('fs');


module.exports = function(path, content, cb) {
    lockFile.lock('foo.lock', function (err) {
        if (err) return cb(err);

        fs.writeFile(path, content, cb);
        lockFile.unlock('foo.lock');
    });
}

For better performance you can even combine 2 approaches here.

like image 180
tenbits Avatar answered Oct 21 '22 21:10

tenbits


You should write a module names logs or what ever you like.

logs.js

var fs = require('fs');
var writeStream = fs.createWriteStream('./abc.txt');

module.exports = {
  /* PUSH */
  write: function (message, cb) {
      writeStream.write(message, cb);
  }
}

Then in your socket.io related module just require the module at the top like

var logs = require('./logs');

and write message like this in the socket.io callbacks ! :)

logs.write('datatobewritten');

Bottom line "use fs.createWriteStream instead of fs.writefile"

Hope this makes sense :)

like image 37
Dave Amit Avatar answered Oct 21 '22 22:10

Dave Amit