0

I am stuck here due to a simple event related issue. Here is the issue:

  • I have created a cluster using cluster.js and forked server.js from cluster.js.
  • I have put a timer from cluster.js and after every 1 min I am triggering an event 'testTimer'. I have used a event file to do
    it.
  • I am trying to capture this event 'testTimer' from the child
    process using the same file I have imported into server.js and doing a .on('testTimer', callback)

However, the events are not captured in any of the processes. I have tried making the event global and assign the event globally to a symbol but was unable to get it work/capture event as well.

Here is the codes:

cluster.js (child process creator)

...require > events.js...
... create cluster logic...
setInterval(function () {
 evt.emit('testTimer', {tester: 'test'});
 evt.tester();
}, 1000);

server.js (child process)

...require > events.js...
evt.on('testTimer', function (data) {

    console.log('Starting Sync ', data);
});

events.js (common file for events)

var util         = require("util");
var EventEmitter = require("events").EventEmitter;

function test () {
    EventEmitter.call(this);
}
test.prototype.tester = function (){
    this.emit('testTimer', {missed: 'this'})
}
util.inherits(test, EventEmitter);
module.exports = test;
Gary
  • 2,293
  • 2
  • 25
  • 47

1 Answers1

3

EventEmitter instances can't reach beyond the bounds of a process. If you want to communicate between parent and children, use worker.send():

// cluster.js
setInterval(function () {
  for (const id in cluster.workers) {
    cluster.workers[id].send({ type : 'testTimer', data : { tester : 'test' }});
  }
}, 1000);

// server.js
process.on('message', function(message) {
  if (message.type === 'testTimer') { 
    console.log('Starting Sync ', message.data);
  }
})
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Hmm.... Did I look so stupid. Ouch... Let me try this. I ignored this fact completely/ But will globals also not be captured? I tried this as well ... `const EVT_KEY = Symbol.for('commonseventservice'); global[EVT_KEY] = new EventsClass();` – Gary Apr 26 '17 at 14:04
  • 1
    Globals, or even regular variables, will work, but they should be considered read-only: if you change such a variable in the master process, those changes won't be transferred to the children. A newly forked process will initially share its memory with its parent, until you make changes. – robertklep Apr 26 '17 at 14:07
  • Ok does that mean that globals for each process master or child will be a different object respectively? – Gary Apr 26 '17 at 14:09
  • 2
    Yes and no. They will refer to the same piece of memory, so in that respect they are the same object. But once you make any change to the object (from either the parent or the child), that piece of memory is copied "into" the process that changes it and the changes will be local to the process that is making the changes (this is called [_copy-on-write_](https://en.wikipedia.org/wiki/Copy-on-write)). – robertklep Apr 26 '17 at 14:12
  • Hmm... this is exactly the behavior I was seeing in the global assignation. Thanks a ton. I must mention I did try assigning the global object with a singleton without a object freeze since I was unable to make changes/add eventlisteners and it had not worked as well. It showed one set of listeners in child and one set of listeners in cluster.js Now I see the reason. – Gary Apr 26 '17 at 14:15
  • Can I move away from copy-on-write? – Gary Apr 26 '17 at 14:16
  • 1
    Not from Node (or at least, not easily). You'd need threads, which come with their own challenges (like having to synchronize changes). – robertklep Apr 26 '17 at 14:17
  • Any good read or resource for the same? Its okay even if you just point me to them. Though I will go with workers/master communication for the moment, I would definitely want to explore how it can be done. – Gary Apr 26 '17 at 14:27
  • I have no idea if there are working threading implementations for Node, tbh. – robertklep Apr 26 '17 at 14:46
  • No. I was looking at `having to synchronize changes`. I had heard it is possible but never looked at a resource mentioning the same. I am not sure if multi-threading might be possible without an extension that creates tailing threads/pool from single threaded nodejs. May be I am wrong. – Gary Apr 27 '17 at 05:14
  • I means "synchronizing changes" in the context of multithreading. What you're looking for (I think) is to coordinate between processes, for which the easiest solution would be the IPC offered by `worker.send()`. – robertklep Apr 27 '17 at 08:20
  • Ok got your point. I actually thought 'synchronizing changes' literally – Gary Apr 27 '17 at 08:23