1

I'm writing a nodejs app, and I need to fork the main process (process.fork). I need a module to be required only once, however this module is required twice. A sample code to illustrate :

a.js

var shared = require('./shared');
var cluster = require('cluster');

if(cluster.isMaster){
    cluster.fork();
} else {
    process.exit(0);
}

shared.js

console.log('Hello world');
module.export = { foo : 'bar' };

The code in shared.js is executed twice. Is there any way to get it exectued once ? Is there a module cache per thread in nodejs ?

EDIT : In my case, shared contains some logging configuration using winston, and exports an API to get logging facilities. I won't post the code for confidential reasons. To get the code working, we decided to let the responsability of each thread requiring this module to configure it.

mguimard
  • 1,881
  • 13
  • 14
  • `NodeJS` is single threaded anyway, this shouldn't be hit twice.. it is something to do with `cluster.fork()`, which would suggest its spawning another instance (but I have not used cluster), which would make sense to execute a second time. `foo` would not be defined for the second instance if it was not spawned.. I don't see a problem here.. It's as designed.. – Pogrindis Feb 01 '16 at 10:00
  • `console.log('Hello world ' + process.pid);` if you try this you can see they are too seperate processes.. – Pogrindis Feb 01 '16 at 10:03
  • Right there are 2 different processes. According to @marcus-ekwall 's answer, I'll execute some code in `shared` only if this is the main thread. – mguimard Feb 01 '16 at 10:13

1 Answers1

2

It is executed once for master and once for the fork, which is why it is executed twice.

If you only want it to execute once you could do it like this:

var cluster = require('cluster');

if (cluster.isMaster) {
    var shared = require('./shared');
    cluster.fork();
} else {
    process.exit(0);
}

You can also add the cluster.isMaster check within the shared file.

Additions regarding your edit

The easiest way to handle logging of your workers is to let the master process handle it. I usually do it by sending messages from the worker to the master, like this:

const cluster = require('cluster');

if (cluster.isMaster) {
    const worker = cluster.fork();
    const pid = worker.process.pid;
    worker.on('message', function(msg) {
        switch (msg.type) {
            case 'uncaughtException':
                // Handle uncaught exception from worker
                // Perhaps fork it again?
            break;
            case 'console':
                // Handle console logging from worker
                // Add winston code here
            break;
        }
    });
} else {
    process.on("uncaughtException", function (err) {
        process.send({ type: "uncaughtException", data: { message: err.message, stack: err.stack } });
        process.exit(1);
    });

    // Override console
    console.log = function () {
        process.send({ type: "console", method: "log", data: [].slice.call(arguments, 0) });
    };

    console.error = function () {
        process.send({ type: "console", method: "error", data: [].slice.call(arguments, 0) });
    };

    console.info = function () {
        process.send({ type: "console", method: "info", data: [].slice.call(arguments, 0) });
    };

    console.warn = function () {
        process.send({ type: "console", method: "warn", data: [].slice.call(arguments, 0) });
    };

    console.debug = function () {
        process.send({ type: "console", method: "debug", data: [].slice.call(arguments, 0) });
    };

}
mekwall
  • 28,614
  • 6
  • 75
  • 77
  • Yes, this would only be executed for the master code, but I need to access `shared` in the child process. Thank you for this answer anyway. I'll try to use cluster.isMaster in `shared` to fix my problem. – mguimard Feb 01 '16 at 10:10
  • @mguimard in that case you may find this useful also : http://stackoverflow.com/questions/8534462/nodejscluster-how-to-send-data-from-master-to-to-all-or-single-child-workers – Pogrindis Feb 01 '16 at 10:16
  • @mguimard What exactly does `shared` contain? Please elaborate in your question. – mekwall Feb 02 '16 at 09:46
  • Edited. But this was more a general question rather than a specific one. – mguimard Feb 02 '16 at 09:55
  • @mguimard Well, there's no general answer to such a question. There are different approaches and they don't suit every situation. I'll add some comments regarding shared logging with cluster to my answer. – mekwall Feb 02 '16 at 10:08
  • Thank you for your feedback, I'll mark this answer as accepted (even if we chose an other strategy) – mguimard Feb 03 '16 at 14:14