@colyseus/core
Version:
Multiplayer Framework for Node.js.
88 lines (87 loc) • 2.73 kB
JavaScript
// 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
};