UNPKG

@toolpad/utils

Version:

Shared utilities used by Toolpad packages.

101 lines (98 loc) 2.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createRpcClient = createRpcClient; exports.serveRpc = serveRpc; var _worker_threads = require("worker_threads"); var _errors = require("./errors"); /** * Helpers that are intended to set up rpc between a Node.js worker thread and the main thread. * Create the worker and pass a port in the workerData. * * On the main thread: * * const rpcChannel = new MessageChannel() * const worker = new Worker('./myWorker.js', { * workerData: { rpcPort: rpcChannel.port1 }, * transferList: [rpcChannel.port1] * }) * * // Depending of the direction of communication, either * const client = createRpcClient(rpcChannel.port2) * // or * serveRpc(rpcChannel.port2, { * myMethod * }) * * On the worker thread: * * // Depending of the direction of communication, either * const client = createRpcClient(workerData.rpcPort) * // or * serveRpc(workerData.rpcPort, { * myMethod * }) * * Use multiple channels for bidirectional communication. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function createRpcClient(port, { timeout = 30000 } = {}) { return new Proxy({}, { get: (target, prop) => { if (typeof prop !== 'string') { return Reflect.get(target, prop); } return (...args) => { return new Promise((resolve, reject) => { const { port1, port2 } = new _worker_threads.MessageChannel(); const timeoutId = setTimeout(() => { port1.close(); }, timeout); port1.on('message', msg => { clearTimeout(timeoutId); if (msg.error) { reject(msg.error); } else { resolve(msg.result); } }); port1.start(); port.postMessage({ method: prop, args, port: port2 }, [port2]); }); }; } }); } function serveRpc(port, methods) { const methodMap = new Map(Object.entries(methods)); port.on('message', async msg => { const method = methodMap.get(msg.method); if (method) { try { const result = await method(...msg.args); msg.port.postMessage({ result }); } catch (rawError) { msg.port.postMessage({ error: (0, _errors.serializeError)((0, _errors.errorFrom)(rawError)) }); } } else { msg.port.postMessage({ error: new Error(`Method "${msg.method}" not found`) }); } }); port.start(); }