sfn-worker
TypeScript icon, indicating that this package has built-in type declarations

0.3.4 • Public • Published

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 => {
    // ...
});

Package Sidebar

Install

npm i sfn-worker

Weekly Downloads

1

Version

0.3.4

License

MIT

Unpacked Size

70.1 kB

Total Files

10

Last publish

Collaborators

  • ayonli