ipchannel
v0.2.8
Published
Elegant and self-hosting channel for inter-process communication.
Downloads
8
Maintainers
Readme
IPChannel
Elegant and self-hosting channel for inter-process communication.
Limits Of Ordinary IPC Modules
- NodeJS
process.on("message")
andprocess.send()
only support messages from the master process to a child-process. - Some situations, e.g. in PM2 cluster mode, developers don't have access to design logic in the master process.
- Third-party IPC modules often require starting the socket server manually, which often needs access to master process as well.
- Third-package IPC modules require setting exact socket protocol to communicate, which doesn't suit all environments. (e.g. cluster doesn't support Windows Named Pipe).
- Internal IPC support and many third-party packages doesn't generate predictable process id, you aren't able to send message to a certain process.
- One the master process or IPC server is down, all communications will be lost.
Advantages When Using IPChannel
- No need to access master process, even all the processes are executed manually (means they are not child-processes at all).
- No need to start IPC server explicitly, automatically choose the best protocol according to the environment.
- Communicate directly from one process to another or to all.
- With predictable peer id, you can distinguish processes from each other.
- When a process exited abnormally and restarted, the IPC channel will automatically rebuild with the same id.
- Even the internal IPC server is down, the remaining processes will ship a new one immediately and guarantee no-downtime period communication.
- Fully support under PM2 supervision.
- Sending messages event before the channel is connected.
How To Use?
It's as almost easy using this module as it will be when using internal
process.on("message")
and process.send()
, and even more, IPChannel allows
you sending messages with a custom event that emitted on the receiver side.
// task.js
import channel from "ipchannel";
// listening messages without event
channel.on("message", (sender, msg) => {
console.log(`Peer ${sender} says: ${msg}`);
});
// By default, the channel is not connnected immediately, and `channel.pid`
// (peer id) will only be available after the connection is established, so the
// following code will output undefined since the channel is not open yet.
console.log(channel.pid); // => undefined
// If you check `channel.connected`, it will be false initially.
console.log(channel.connected); // => false
// Even the channel is not yet connected, you still can send messages now, they
// will be queued and flushed once the connection is established.
channel.to(1).send("This message is sent before connection.");
channel.on("connect", () => {
// now that channel is connected
console.log(channel.connected); // => true
switch (channel.pid) {
case 1:
// listening messages with a custom event
channel.on("custom-event", (sender, ...data) => {
console.log(`Peer ${sender} emits: ${JSON.stringify(data)}`);
});
break;
case 2:
// send message to peer 1
channel.to(1).send("Hi peer 1, I'm peer 2.");
break;
case 3:
// send message with an event to peer 1
channel.to(1).emit("custom-event", "hello world");
break;
case 4:
// send message to all peers
channel.to("all").send("all attention");
// send message with an event to all peers
channel.to("all").emit("custom-event", "all attention");
break;
}
});
In this example, I will use cluster to fork several child-processes, but using
cluster is optional, you can just use child_process
module as you want, or
even run them manually (must provide the absolute path of the script file, e.g.
node $(pwd)/task.js
).
// index.js
const cluster = require("cluster");
if (cluster.isMaster) {
// fork 4 workers
for (let i = 0; i < 4; i++) {
cluster.fork();
}
} else {
require("./task");
}
API
There are very few API in this package, it's designed to be as simple as possible, but brings the major IPC functionality across processes into NodeJS.
channel.connected: boolean
Returnstrue
if the channel is connected,false
otherwise.channel.pid: number
Returns the peer id (starts from1
), this id will persist even after the process is restarted, but only available after connection.channel.disconnect(): void
Closes connection of the channel.channel.on(event: "connect" | "disconnect", listener: () => void): this
Binds a connection/disconnection handler.channel.on(event: "error", listener: (err?: Error) => void): this
Binds a error handler.channel.on(event: "message", listener: (sender: number, msg: any) => void)
Binds a listener function emitted when a message is sent to the current peer (channel.once()
also works).channel.on(event: string, listener: (sender: number, ...data) => void)
Binds a listener function emitted when a message is sent to the current peer with a custom event (channel.once()
also works).channel.to(receiver: number | "all").send(...data): boolean
Sends a message to the receiver, which could be a peer id, or broadcast to all peers (including the current one).channel.to(receiver: number | "all").emit(event: string, ...data): boolean
Sends a message to the receiver with a custom event, it could be a peer id, or broadcast to all peers (including the current one).
What Can't IPChannel Do?
- IPChannel requires all processes run with the same entry file, it won't work with multi-entry applications.
- IPChannel only supports communications on the same machine, it's not designed for network communications with remote services.
- For efficiency concerns, IPChannel currently uses JSON to transfer data through the channel, those data cannot be serialized by JSON will be lost.
License
This package is licensed under MIT license.