UNPKG

@colyseus/core

Version:

Multiplayer Framework for Node.js.

88 lines (87 loc) 2.73 kB
// packages/core/src/IPC.ts import { debugAndPrintError } from "./Debug.mjs"; import { IpcProtocol } from "./Protocol.mjs"; import { generateId, REMOTE_ROOM_SHORT_TIMEOUT } from "./utils/Utils.mjs"; async function requestFromIPC(presence, publishToChannel, method, args, rejectionTimeout = REMOTE_ROOM_SHORT_TIMEOUT) { return new Promise(async (resolve, reject) => { let unsubscribeTimeout; const requestId = generateId(); const channel = `ipc:${requestId}`; const unsubscribe = () => { presence.unsubscribe(channel); clearTimeout(unsubscribeTimeout); }; await presence.subscribe(channel, (message) => { const [code, data] = message; if (code === IpcProtocol.SUCCESS) { resolve(data); } else if (code === IpcProtocol.ERROR) { let error = data; try { error = JSON.parse(data); } catch (e) { } if (typeof error === "string") { error = new Error(error); } reject(error); } unsubscribe(); }); presence.publish(publishToChannel, [method, requestId, args]); unsubscribeTimeout = setTimeout(() => { unsubscribe(); reject(new Error("ipc_timeout")); }, rejectionTimeout); }); } async function subscribeIPC(presence, channel, replyCallback) { await presence.subscribe(channel, (message) => { const [method, requestId, args] = message; const reply = (code, data) => { presence.publish(`ipc:${requestId}`, [code, data]); }; let response; try { response = replyCallback(method, args); } catch (e) { debugAndPrintError(e); const error = typeof e.code !== "undefined" ? { code: e.code, message: e.message } : e.message; return reply(IpcProtocol.ERROR, JSON.stringify(error)); } if (!(response instanceof Promise)) { return reply(IpcProtocol.SUCCESS, response); } response.then((result) => reply(IpcProtocol.SUCCESS, result)).catch((e) => { const err = e && e.message || e; reply(IpcProtocol.ERROR, err); }); }); } function subscribeWithTimeout(presence, channel, timeout) { return new Promise((resolve, reject) => { let timeoutHandle; let resolved = false; const unsubscribe = () => { presence.unsubscribe(channel); clearTimeout(timeoutHandle); }; presence.subscribe(channel, (roomId) => { if (resolved) return; resolved = true; unsubscribe(); resolve(roomId); }); timeoutHandle = setTimeout(() => { if (resolved) return; resolved = true; unsubscribe(); reject(new Error("timeout")); }, timeout); }); } export { requestFromIPC, subscribeIPC, subscribeWithTimeout };