Skip to content

Commit 1364d96

Browse files
authored
fix(runner): skip closing hibernatable websockets on shutdown (#3397)
1 parent 611023b commit 1364d96

File tree

3 files changed

+23
-4
lines changed

3 files changed

+23
-4
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@ export class Tunnel {
8282
// closed:
8383
// https://github.com/rivet-dev/rivet/blob/00d4f6a22da178a6f8115e5db50d96c6f8387c2e/engine/packages/pegboard-runner/src/lib.rs#L157
8484
for (const [_, ws] of this.#actorWebSockets) {
85-
// TODO: Trigger close event, but do not send anything over the tunnel
86-
ws.__closeWithoutCallback(1000, "ws.tunnel_shutdown");
85+
// Only close non-hibernatable websockets to prevent sending
86+
// unnecessary close messages for websockets that will be hibernated
87+
if (!ws.canHibernate) {
88+
ws.__closeWithoutCallback(1000, "ws.tunnel_shutdown");
89+
}
8790
}
8891
this.#actorWebSockets.clear();
8992
}
@@ -668,6 +671,8 @@ export class Tunnel {
668671
requestId,
669672
request,
670673
);
674+
adapter.canHibernate = hibernationConfig.enabled;
675+
671676
this.#sendMessage(requestId, {
672677
tag: "ToServerWebSocketOpen",
673678
val: {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class WebSocketTunnelAdapter {
1818
#url = "";
1919
#sendCallback: (data: ArrayBuffer | string, isBinary: boolean) => void;
2020
#closeCallback: (code?: number, reason?: string, retry?: boolean) => void;
21+
#canHibernate: boolean = false;
2122

2223
// Event buffering for events fired before listeners are attached
2324
#bufferedEvents: Array<{
@@ -73,6 +74,16 @@ export class WebSocketTunnelAdapter {
7374
return this.#url;
7475
}
7576

77+
/** @experimental */
78+
get canHibernate(): boolean {
79+
return this.#canHibernate;
80+
}
81+
82+
/** @experimental */
83+
set canHibernate(value: boolean) {
84+
this.#canHibernate = value;
85+
}
86+
7687
get onopen(): ((this: any, ev: any) => any) | null {
7788
return this.#onopen;
7889
}

rivetkit-typescript/packages/rivetkit/src/actor/instance.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,10 +2089,13 @@ export class ActorInstance<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
20892089
}
20902090
}
20912091

2092-
// Disconnect existing connections
20932092
const promises: Promise<unknown>[] = [];
2093+
2094+
// Disconnect existing non-hibernatable connections
20942095
for (const connection of this.#connections.values()) {
2095-
promises.push(connection.disconnect());
2096+
if (!connection.isHibernatable) {
2097+
promises.push(connection.disconnect());
2098+
}
20962099

20972100
// TODO: Figure out how to abort HTTP requests on shutdown. This
20982101
// might already be handled by the engine runner tunnel shutdown.

0 commit comments

Comments
 (0)