Skip to content

Commit 3e95003

Browse files
committed
fix(runner): do not send websocket close on tunnel shutdown since pegboard-runner takes care of this
1 parent fb0fa44 commit 3e95003

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

engine/sdks/typescript/runner/src/tunnel.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ interface PendingTunnelMessage {
2323
requestIdStr: string;
2424
}
2525

26+
class RunnerShutdownError extends Error {
27+
constructor() {
28+
super("Runner shut down");
29+
}
30+
}
31+
2632
export class Tunnel {
2733
#runner: Runner;
2834

@@ -49,20 +55,31 @@ export class Tunnel {
4955
}
5056

5157
shutdown() {
58+
// NOTE: Pegboard WS already closed at this point, cannot send
59+
// anything. All teardown logic is handled by pegboard-runner.
60+
5261
if (this.#gcInterval) {
5362
clearInterval(this.#gcInterval);
5463
this.#gcInterval = undefined;
5564
}
5665

5766
// Reject all pending requests
67+
//
68+
// RunnerShutdownError will be explicitly ignored
5869
for (const [_, request] of this.#actorPendingRequests) {
59-
request.reject(new Error("Tunnel shutting down"));
70+
request.reject(new RunnerShutdownError());
6071
}
6172
this.#actorPendingRequests.clear();
6273

6374
// Close all WebSockets
75+
//
76+
// The WebSocket close event with retry is automatically sent when the
77+
// runner WS closes, so we only need to notify the client that the WS
78+
// closed:
79+
// https://github.com/rivet-dev/rivet/blob/00d4f6a22da178a6f8115e5db50d96c6f8387c2e/engine/packages/pegboard-runner/src/lib.rs#L157
6480
for (const [_, ws] of this.#actorWebSockets) {
65-
ws.__closeWithRetry();
81+
// TODO: Trigger close event, but do not send anything over the tunnel
82+
ws.__closeWithoutCallback(1000, "ws.tunnel_shutdown");
6683
}
6784
this.#actorWebSockets.clear();
6885
}
@@ -407,8 +424,16 @@ export class Tunnel {
407424
await this.#sendResponse(requestId, response);
408425
}
409426
} catch (error) {
410-
this.log?.error({ msg: "error handling request", error });
411-
this.#sendResponseError(requestId, 500, "Internal Server Error");
427+
if (error instanceof RunnerShutdownError) {
428+
this.log?.debug({ msg: "catught runner shutdown error" });
429+
} else {
430+
this.log?.error({ msg: "error handling request", error });
431+
this.#sendResponseError(
432+
requestId,
433+
500,
434+
"Internal Server Error",
435+
);
436+
}
412437
} finally {
413438
// Clean up request tracking
414439
const actor = this.#runner.getActor(req.actorId);

engine/sdks/typescript/runner/src/websocket-tunnel-adapter.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,23 @@ export class WebSocketTunnelAdapter {
190190
}
191191

192192
close(code?: number, reason?: string): void {
193-
this.closeInner(code, reason);
193+
this.closeInner(code, reason, false, true);
194194
}
195195

196196
__closeWithRetry(code?: number, reason?: string): void {
197-
this.closeInner(code, reason, true);
197+
this.closeInner(code, reason, true, true);
198198
}
199199

200-
closeInner(code?: number, reason?: string, retry: boolean = false): void {
200+
__closeWithoutCallback(code?: number, reason?: string): void {
201+
this.closeInner(code, reason, false, false);
202+
}
203+
204+
closeInner(
205+
code: number | undefined,
206+
reason: string | undefined,
207+
retry: boolean,
208+
callback: boolean,
209+
): void {
201210
if (
202211
this.#readyState === 2 || // CLOSING
203212
this.#readyState === 3 // CLOSED
@@ -208,7 +217,9 @@ export class WebSocketTunnelAdapter {
208217
this.#readyState = 2; // CLOSING
209218

210219
// Send close through tunnel
211-
this.#closeCallback(code, reason, retry);
220+
if (callback) {
221+
this.#closeCallback(code, reason, retry);
222+
}
212223

213224
// Update state and fire event
214225
this.#readyState = 3; // CLOSED

0 commit comments

Comments
 (0)