sfn-worker
v0.3.4
Published
Simple Friendly Node.js Worker management for communications.
Downloads
9
Maintainers
Readme
SFN-Worker
Simple Friendly Node.js Worker management for communications.
Notes
When you create a new Worker()
, a new worker process will be forked. You can
keep a worker alive, so when it exits accidentally, a new one will be forked
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 and in the worker process.
This module uses predictable and user-defined IDs to differ workers, so you can always know which is which.
The package supports any version of Node.js that higher than 4.0.0.
Install
npm install sfn-worker
Example
const Worker = require("sfn-worker");
if (Worker.isMaster) {
// Master process
// Create two workers A and B, and keep them alive.
new Worker("A", true);
new Worker("B", true);
// Do logics when the worker is online.
Worker.on("online", (worker) => {
worker.on("greeting from worker", (msg) => {
console.log("Worker %s: %s", worker.id, msg);
// greet back
worker.emit("greeting from master", `Hello, worker ${worker.id}!`);
});
});
} else {
// Worker process
Worker.on("online", worker => {
worker.emit("greeting from worker", `Hi, master, I'm worker ${worker.id}!`);
worker.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
worker.to(id).emit("greeting back to another worker", worker.id, `Nice to meet you, worker ${id}!`);
}).on("greeting back to another worker", (id, msg) => {
console.log("Worker %s: %s", id, msg);
});
if (worker.id === "A") {
worker.to("B").emit("greeting from another worker", "A", `Hi, worker B, I'm worker A!`);
}
});
}
Events
These events really mean something if you bind events to them:
online
error
exit
But they don't totally work in all circumstances, e.g. the online
can only
be used by Worker.on()
.
API
constant isMaster
Whether the current process is the master process.
constant isWorker
Whether the current process is a worker process, opposite to isMaster
.
new Worker(id: string, keepAlive?: boolean)
Creates a new worker. Be aware you can only create 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 worker always available.
The worker id
, unlike the id generated by cluster
or process pid
, is
user-defined and predictable, you can use any id you want to name the worker.
And whenever you want to send messages, you can always know the receiver id.
if(isMaster){
// Always create workers in the master process.
new Worker("A");
new Worker("B", true); // Keep B alive.
}
worker.id
The worker id you specified.
worker.keepAlive
Whether the worker should keep alive, default is false
if you don't set
keepAlive
to true
.
worker.state
The state of the worker, possible values are: connecting
, online
and
closed
, in a worker process, only shows online
.
woker.isConnected(): boolean
Whether the worker process is connected (online
).
worker.isDead(): boolean
Whether the worker process is dead (closed
).
worker.on(event: string, listener: (...data?: Any[]) => void): this
Adds a listener function to an event. The listener
function will be
called every time the event
is triggered, it may accept parameters, which
are the data sent by the other end of the worker, or other workers.
worker.on("hi", (msg) => {
console.log("worker says hi: '%s'", msg);
});
worker.once(event: string, listener: (...data?: Any[]) => void): this
This method is similar to worker.on()
, except the listener
will be run only
once.
worker.emit(event: string, ...data?: any[]): boolean
Emits an event
to the other end of the worker, data
will be send to that
end, so its event listeners can receive and manipulate them.
worker.emit("hi", `Hello, I'm worker ${worker.id}.`);
worker.to(...workers: Array<string | Worker>): this
Sets receivers that the event will only be emitted to them. Since 2.0, you
can call to()
multiple times to concatenate several receivers.
worker.to("A").emit("hi", `Hello, I'm worker ${worker.id}.`);
// or
worker.to(workerA).emit("hi", `Hello, I'm worker ${worker.id}.`);
worker.broadcast(event: string, ...data?: any[]): boolean
Emits an event
to all workers (the current one included). Remember, when you
broadcast a message, it will always be sent to worker ends, so listening such
an event in the master process is meaningless and won't work.
The reason why the current worker 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.
worker.broadcast("hi", `Hi everybody, I'm worker ${worker.id}.`);
worker.exit()
Terminates the current worker. If this method is called, even if you set the
worker to keepAlive
, it will be terminated anyway.
worker.reboot(cb?: () => void)
Restarts the current worker. If this method is called, even if you set the
worker not to keepAlive
, it will be restarted anyway.
Be aware, the callback function can only be set in the master process.
Worker.on(event: string, listener: (...data: Any[]) => void): Worker
The static version on()
can only listens two events: online
, and exit
.
When a worker is created and ready for communications, online
event will be
triggered.
Worker.on("online", worker => {
console.log("Worker %s is online.", worker.id);
// ...
}).on("exit", worker => {
console.log("Worker %s exits.", worker.id)
});
Be aware, binding a listener to online
is required, and you must do any
stuffs related to that worker
in the listener function. This principle works
both in master or in a worker process.
Worker.emit(event: string, ...data?: any[]): boolean
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
version. Be aware this method will broadcast messages to all workers, unless
you specify a receiver by calling Worker.to()
.
Worker.to(...workers: Array<string | Worker>): Worker
Similar to the instantiated version, but can only be used in the master
process. Since 2.0, you can call to()
multiple times to concatenate
several receivers.
Worker.to("A").emit("event name", "Hi, worker A!");
// or
Worker.to(workerA).emit("event name", "Hi, worker A!");
Worker.broadcast(event: string, ...data?: any[]): boolean
Similar to the instantiated version, but can only be used in the master process.
Worker.broadcast("event name", "Hi, everyone, I'm your master!");
Worker.getWorkers(cb?: (err: Error, workers: Worker[]) => void): void | Promise<Worker[]>
This method allows you getting all connected workers, whether in the master or
a worker process. If you don't provide cb
, a Promise
will be returned.
Worker.getWorkers((err, workers) => {
// ...
});
// Or
Worker.getWorkers().then(workers => {
// ...
});
Be aware, DON'T add event listeners to the workers got by this method,
they won't work in the worker process. Actually, you should always add event
listeners in the event online
scope.
Worker.getWorker(cb:? (err: Error, worker: Worker) => void): void | Promise<Worker>
This method allows you getting the current worker instance in a worker process
outside the Worker.on("online")
scope. It's very helpful sometimes when you
want to get the worker, but you don't want to or it's hard to put your code
inside Worker.on("online")
(e.g. in separated files or scopes).
If you don't pass a cb
function, this method will return a Promise
. If the
worker isn't ready, then the callback function will be called whenever the
worker is online.
Worker.on("online", worker => {
// ...
});
// Outside the scope:
Worker.getWorker((err, worker) => {
// ...
});
// or
Worker.getWorker().then(worker => {
// ...
});