fix(dev): reject closed gateway websocket calls

This commit is contained in:
Vincent Koc
2026-05-30 05:46:14 +02:00
parent 28ffcf88bd
commit 723b5085d9
2 changed files with 111 additions and 5 deletions

View File

@@ -65,8 +65,20 @@ export function createGatewayWsClient(params: {
}
>();
const rejectPending = (error: Error) => {
for (const waiter of pending.values()) {
clearTimeout(waiter.timeout);
waiter.reject(error);
}
pending.clear();
};
const request = (method: string, paramsObj?: unknown, timeoutMs = 12_000) =>
new Promise<GatewayResFrame>((resolve, reject) => {
if (ws.readyState !== WebSocket.OPEN) {
reject(new Error(`gateway websocket is not open for ${method}`));
return;
}
const id = randomUUID();
const frame: GatewayReqFrame = { type: "req", id, method, params: paramsObj };
const timeout = setTimeout(() => {
@@ -74,7 +86,24 @@ export function createGatewayWsClient(params: {
reject(new Error(`timeout waiting for ${method}`));
}, timeoutMs);
pending.set(id, { resolve, reject, timeout });
ws.send(JSON.stringify(frame));
try {
ws.send(JSON.stringify(frame), (err) => {
if (!err) {
return;
}
const waiter = pending.get(id);
if (!waiter) {
return;
}
pending.delete(id);
clearTimeout(waiter.timeout);
waiter.reject(err instanceof Error ? err : new Error(String(err)));
});
} catch (err) {
pending.delete(id);
clearTimeout(timeout);
reject(err instanceof Error ? err : new Error(String(err)));
}
});
const waitOpen = () =>
@@ -119,12 +148,16 @@ export function createGatewayWsClient(params: {
params.onEvent?.(evt);
}
});
ws.on("close", (code, reason) => {
const suffix = reason.length > 0 ? `: ${reason.toString("utf8")}` : "";
rejectPending(new Error(`gateway websocket closed (${code})${suffix}`));
});
ws.on("error", (err) => {
rejectPending(err instanceof Error ? err : new Error(String(err)));
});
const close = () => {
for (const waiter of pending.values()) {
clearTimeout(waiter.timeout);
}
pending.clear();
rejectPending(new Error("gateway websocket client closed"));
ws.close();
};