Simple Friendly Node.js Channel for communications between processes.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.gitignore
LICENSE
README.md
index.js
package.json
test.js

README.md

SFN-Channel

Simple Friendly Node.js Channel for communications between processes.

Warinig: This module is deprecated, please check out sfn-worker instead.

Notes

This module can be used as a process manager, when you initiate a new Channel, a new worker process will be forked. You can keep a channel alive, so when the worker exits accidentally, a new one will be created to replace it.

This module is designed as convenient as it can, many of its methods can be used both in the master or in a worker process, and you can add event listeners and emit events both in the master or in the worker process.

This module uses predictable and user-defined IDs to differ channels, so you can always know which is which.

Install

npm install sfn-channel

Example

const Channel = require("sfn-channel");

if (Channel.isMaster) {
    // Master process
    // Create two channels listens to worker processes A and B, and keep them 
    // alive.
    new Channel("A", true);
    new Channel("B", true);

    // Do logics when the channel is online.
    Channel.on("online", (channel) => {
        channel.on("greeting from worker", (msg) => {
            console.log("Worker %s: %s", channel.id, msg);
            // greet back
            channel.emit("greeting from master", `Hello, worker ${channel.id}!`);
        });
    });
} else {
    // Worker process
    Channel.on("online", channel => {
        channel.emit("greeting from worker", `Hi, master, I'm worker ${channel.id}!`);

        channel.on("greeting from master", msg => {
            console.log("Master: %s", msg);
        }).on("greeting from another worker", (id, msg) => {
            console.log("Worker %s: %s", id, msg);
            // greet back
            channel.to(id).emit("greeting back to another worker", channel.id, `Nice to meet you, worker ${id}!`);
        }).on("greeting back to another worker", (id, msg) => {
            console.log("Worker %s: %s", id, msg);
        })

        if (channel.id === "A") {
            channel.to("B").emit("greeting from another worker", "A", `Hi, worker B, I'm worker A!`);
        }
    });
}

API

Channel.isMaster

Whether the current process is the master process.

Channel.isWorker

Whether the current process is a worker process, opposite to Channel.isMaster.

new Channel(id: string, keepAlive?: boolean)

This constructor creates both a channel and a worker process, be aware you can only create channels and workers in the master process. If you set keepAlive to true, then when the worker process accidentally exits, a new one will be created to replace it immediately, thus keeping the channel always available.

The channel id, unlike the worker id generated by cluster or process pid, is user-defined and predictable, you can use any id you want to name the channel. And whenever you want to send messages, you can always know the channel id.

if(Channel.isMaster){
    // Always create channels in the master process.
    new Channel("A");
    new Channel("B", true); // Keep B alive.
}

channel.id

The channel id you specified.

channel.on(event: string, handler: Function)

Adds a listener function to an event. The handler function will be called every time the event is triggered, it may accept parameters, which are sent by the other end of the channel, or other workers.

channel.on("hi", (msg)=>{
    console.log("worker says hi: '%s'", msg);
});

channel.once(event: string, handler: Function)

This method is very much the same as channel.on(), except the handler will only be run once.

channel.emit(event: string, ...data: any)

Emits an event to the other end of the channel, data will be send to that end, so its event listeners can receive and manipulate them.

channel.emit("hi", `Hello, I'm worker ${channel.id}.`);

channel.to(...id: string)

Sets receivers that the event will only be emitted to them.

channel.to("A").emit("hi", `Hello, I'm worker ${channel.id}.`);

channel.broadcast()

Emits an event to all worker ends of channels (the current channel included). Remember, when you broadcast a message, it will always be sent to worker ends of channels, so listening such an event in the master process is meaningless and won't work.

The reason why the current channel included is meant to reduce your work, if some event acts the same in all workers, then your can just write one piece of code at where listens the event.

channel.broadcast("hi", `Hi everybody, I'm worker ${channel.id}.`);

channel.getWorkers(cb?: Function)

This method allows you getting all workers forked by cluster. If you provide the argument cb, it accepts one parameter, which is an object that carries all worker objects. If you don't provide cb, then a promise will be returned, and the callback function of then() is very much the same as cb.

channel.getWorkers(workers=>{
    // ...
});

// Or
channel.getWorkers().then(workers=>{
    // ...
});

This method acts different in master process and in worker processes, when in master process, you can get the real workers, but in a worker process, you can just get an object that carries few details about those workers.

channel.exit()

Terminates the current worker/channel. If this method is called, even if you set the channel to keepAlive, it will be terminated anyway.

channel.reboot()

Restarts the current worker/channel. If this method is called, even if you set the channel not to keepAlive, it will be restarted anyway.

Channel.on(event: string, handler: Function)

The static version on() can only listens two events: online and exit. When a channel is created and ready for communications, online event will be triggered. When the channel is closed, exit will be triggered.

Channel.on("online", channel=>{
    console.log("Channel %s is online.", channel.id);
    // ...
}).on("exit", channel=>{
    console.log("Channel %s exits.", channel.id)
});

Be aware, binding a listener to exit is optional, while online is required, and you must do any stuffs related to that channel in the listener function. This principle works both in master process or in worker processes.

Channel.emit(event: string, ...data: any)

Similar to the instantiated version, but can only be used in the master process.

If you want to send messages in the master process actively, you can call this static version emit(), its usage is pretty much the same as the instantiated one. be aware this method will broadcast messages to every worker process, unless you specify a receiver by calling Channel.to().

Channel.to(...id: string)

Similar to the instantiated version, but can only be used in the master process.

Be aware, you must call emit() very after calling this method, because its a static version, if you don't do this, there is no guarantee that its state won't be changed when you calling emit() after a while.

Channel.to("A").emit("event name", "Hi, worker A!");

Channel.broadcast(event: string, ...data: any)

Similar to the instantiated version, but can only be used in the master process.

Channel.broadcast("event name", "Hi, everyone, I'm your master!");

Channel.getWorkers(cb?: Function)

Similar to the instantiated version, but can only be used in the master process.

Channel.getWorkers(workers=>{
    // ...
});

// Or
Channel.getWorkers().then(workers=>{
    // ...
});

Channel.getChannel(cb:? Function)

This method allows you getting the current channel in a worker process outside the Channel.on("online") scope. It's very helpful sometimes when you want to get the the current channel, but you don't want to or it's hard to put your code inside Channel.on("online").

If you don't pass a cb function, then this method will return a Promise.

Channel.on("online", channel=>{
    // ...
});

// Outside the scope:
Channel.getChannel(channel=>{
    // ...
});