Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

express-ws how to periodically check a custom event and take action automatically

I am using express-ws https://www.npmjs.com/package/express-ws (API which helps creating server for express and websocket clients).

app.ws('/', function(ws, req) {
  console.log("New connection")
  if (content.length > 0) {
    console.log(content)
    ws.send(content)
  }
  ws.on('message', function(msg, flags) {
    console.log("Received "+ msg);
  });
  ws.on('data', function(msg, flags) {
    var data = []; // List of Buffer objects
    res.on("data", function(chunk) {
      data.push(chunk); // Append Buffer object
      console.log(data)
    })
  })
});

Now as you can see with code above, whenever a connection is created it checks length of content and sends conetent to client if more than 0.

Following router code, on web request, updates the file. Issue with this if sometime after connection creation if this file was modified, this connection doesn't know about it and hence send function is not called. I also tried fs.watch but i am not able to make it to work.

router.post('/run_restart', function(req, res, next) {
  text = '{"to_do": "run_test", "devices":"all", "argv": { "test": "' + req.body.cmd + '", "cycles": "' + req.body.cycles + '", "awake_for": "' + req.body.wt + '" }}'
  path = process.env['HOME']+'/Desktop/automation/Stressem/StressemWeb/bin/task.txt'
  fs.writeFile(path, text)
  res.render('home.jade', { title: 'Stressem' });
});

fs.watch(file, function (event) {
  fs.stat(file, function (err, stats) {
    if(stats.size>80){
      console.log("Event: " + event);
      fs.readFile(file, 'utf8', function (err, data) {
        if (err) throw err;
        content = data.toString();
      });
    }
  });

What i would like is whenever the file is updated, ws.send can be called for one of the websocket connection.

like image 909
bruceparker Avatar asked Mar 17 '16 23:03

bruceparker


2 Answers

Since your server is the one that changes the file, there's no need to use fs.watch as you already know when a file changes. All that's left to do is iterate over a list of open connections and send them the new contents.

var connections = []; // Keeps track of all connections
app.ws('/', function(ws, req) {
   console.log("New connection")
   connections.push(ws); // Add the new connection to the list

  if (content.length > 0) {
    console.log(content)
    ws.send(content)
  }
  ws.on('message', function(msg, flags) {
    console.log("Received "+ msg);
  });
  ws.on('data', function(msg, flags) {
    var data = []; // List of Buffer objects
    res.on("data", function(chunk) {
      data.push(chunk); // Append Buffer object
      console.log(data)
    })
  })
  // TODO: Make sure you remove closed connections from `connections`
  // by listening for the ws `close` event.
});

router.post('/run_restart', function(req, res, next) {
  text = '{"to_do": "run_test", "devices":"all", "argv": { "test": "' + req.body.cmd + '", "cycles": "' + req.body.cycles + '", "awake_for": "' + req.body.wt + '" }}'
  path = process.env['HOME']+'/Desktop/automation/Stressem/StressemWeb/bin/task.txt'
  fs.writeFile(path, text)
  res.render('home.jade', { title: 'Stressem' });

  connections.forEach(function(c){
    c.send(text); // Send the new text to all open connections
  }
});

Please note: this won't work if you have multiple processes or servers, but since you're writing to the local file system instead of a database, I assume this is not a requirement.

like image 140
Rudolf Meijering Avatar answered Sep 24 '22 03:09

Rudolf Meijering


This simple code work good with express. If a few delay not a problem for you, you can use this.

setInterval(milisecondsToCheck, checkFunction)

for more

http://www.w3schools.com/jsref/met_win_setinterval.asp

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval

if you use it like this, you can finish it after your job done:

var timer = setInterval(milisecondsToCheck, checkFunction);

To clear it:

clearInterval(timer);
like image 24
bmavus Avatar answered Sep 22 '22 03:09

bmavus