UNPKG

egg

Version:

A web application framework for Node.js

130 lines (129 loc) • 4.16 kB
import { BaseMessenger } from "./base.js"; import { debuglog } from "node:util"; import workerThreads from "node:worker_threads"; import { sendmessage } from "sendmessage"; //#region src/lib/core/messenger/ipc.ts const debug = debuglog("egg/lib/core/messenger/ipc"); /** * Communication between app worker and agent worker by IPC channel */ var Messenger = class extends BaseMessenger { pid; opids = []; constructor(egg) { super(egg); this.pid = String(process.pid); this.on("egg-pids", (workerIds) => { debug("[%s:%s] got egg-pids %j", this.egg.type, this.pid, workerIds); this.opids = workerIds.map((workerId) => String(workerId)); }); this.onMessage = this.onMessage.bind(this); process.on("message", this.onMessage); if (!workerThreads.isMainThread) workerThreads.parentPort.on("message", this.onMessage); } /** * Send message to all agent and app * @param {String} action - message key * @param {Object} data - message value * @return {Messenger} this */ broadcast(action, data) { debug("[%s:%s] broadcast %s with %j", this.egg.type, this.pid, action, data); this.send(action, data, "app"); this.send(action, data, "agent"); return this; } /** * send message to the specified process * @param {String} workerId - the workerId of the receiver * @param {String} action - message key * @param {Object} data - message value * @return {Messenger} this */ sendTo(workerId, action, data) { debug("[%s:%s] send %s with %j to workerId:%s", this.egg.type, this.pid, action, data, workerId); const message = { action, data, /** * @deprecated Keep compatible, please use receiverWorkerId instead */ receiverPid: String(workerId), receiverWorkerId: String(workerId) }; this.#sendMessage(message); return this; } /** * send message to one app worker by random * - if it's running in agent, it will send to one of app workers * - if it's running in app, it will send to agent * @param {String} action - message key * @param {Object} data - message value * @return {Messenger} this */ sendRandom(action, data) { if (this.opids.length === 0) { debug("[%s:%s] no pids, ignore sendRandom %s with %j", this.egg.type, this.pid, action, data); return this; } const index = Math.floor(Math.random() * this.opids.length); const workerId = this.opids[index]; this.sendTo(workerId, action, data); return this; } /** * send message to app * @param {String} action - message key * @param {Object} data - message value * @return {Messenger} this */ sendToApp(action, data) { debug("[%s:%s] send %s with %j to all app", this.egg.type, this.pid, action, data); this.send(action, data, "app"); return this; } /** * send message to agent * @param {String} action - message key * @param {Object} data - message value * @return {Messenger} this */ sendToAgent(action, data) { debug("[%s:%s] send %s with %j to all agent", this.egg.type, this.pid, action, data); this.send(action, data, "agent"); return this; } /** * @param {String} action - message key * @param {Object} data - message value * @param {String} to - let master know how to send message * @return {Messenger} this */ send(action, data, to) { debug("send message %s with %j to %s", action, data, to); this.#sendMessage({ action, data, to }); return this; } #sendMessage(message) { debug("[%s:%s] send message %j, mode: %s", this.egg.type, this.pid, message, this.egg.options.mode); sendmessage(process, message); } onMessage(message) { if (typeof message?.action === "string") { debug("[%s:%s] got message %s with %j, receiverWorkerId: %s", this.egg.type, this.pid, message.action, message.data, message.receiverWorkerId ?? message.receiverPid); this.emit(message.action, message.data); } else if (message?.type === "Buffer") debug("[%s:%s] got an invalid message: %s", this.egg.type, this.pid, Buffer.from(message.data)); else debug("[%s:%s] got an invalid message %j", this.egg.type, this.pid, message); } close() { process.removeListener("message", this.onMessage); this.removeAllListeners(); } }; //#endregion export { Messenger };