@rivetkit/engine-runner 2.3.0-rc.4 → 2.3.0-rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mod.cjs +34 -11
- package/dist/mod.cjs.map +1 -1
- package/dist/mod.js +36 -13
- package/dist/mod.js.map +1 -1
- package/package.json +3 -3
- package/src/mod.ts +21 -9
- package/src/tunnel.ts +7 -1
- package/src/websocket-tunnel-adapter.ts +49 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivetkit/engine-runner",
|
|
3
|
-
"version": "2.3.0-rc.
|
|
3
|
+
"version": "2.3.0-rc.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"bench": "tsx benches/actor-lifecycle.bench.ts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@rivetkit/virtual-websocket": "2.3.0-rc.
|
|
29
|
-
"@rivetkit/engine-runner-protocol": "2.3.0-rc.
|
|
28
|
+
"@rivetkit/virtual-websocket": "2.3.0-rc.6",
|
|
29
|
+
"@rivetkit/engine-runner-protocol": "2.3.0-rc.6",
|
|
30
30
|
"uuid": "^12.0.0",
|
|
31
31
|
"pino": "^9.9.5",
|
|
32
32
|
"ws": "^8.18.3"
|
package/src/mod.ts
CHANGED
|
@@ -12,9 +12,7 @@ import {
|
|
|
12
12
|
unreachable,
|
|
13
13
|
} from "./utils";
|
|
14
14
|
import { importWebSocket } from "./websocket.js";
|
|
15
|
-
import {
|
|
16
|
-
v4 as uuidv4,
|
|
17
|
-
} from "uuid";
|
|
15
|
+
import { v4 as uuidv4 } from "uuid";
|
|
18
16
|
|
|
19
17
|
export type { HibernatingWebSocketMetadata };
|
|
20
18
|
export { RunnerActor, type ActorConfig };
|
|
@@ -562,9 +560,18 @@ export class Runner {
|
|
|
562
560
|
this.#kvRequests.clear();
|
|
563
561
|
|
|
564
562
|
// Close WebSocket
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
563
|
+
//
|
|
564
|
+
// A CONNECTING socket cannot send graceful stopping messages, so
|
|
565
|
+
// it is always closed directly. Without this, a shutdown that
|
|
566
|
+
// races with a reconnect leaves the in-flight WebSocket alive
|
|
567
|
+
// while the rest of the runner state (tunnel, intervals) has been
|
|
568
|
+
// torn down.
|
|
569
|
+
const pegboardWebSocket = this.#pegboardWebSocket;
|
|
570
|
+
const readyState = pegboardWebSocket?.readyState;
|
|
571
|
+
const isOpen = readyState === 1;
|
|
572
|
+
const isConnecting = readyState === 0;
|
|
573
|
+
if (pegboardWebSocket && (isOpen || isConnecting)) {
|
|
574
|
+
if (immediate || isConnecting) {
|
|
568
575
|
// Stop immediately
|
|
569
576
|
pegboardWebSocket.close(1000, "pegboard.runner_shutdown");
|
|
570
577
|
} else {
|
|
@@ -876,6 +883,10 @@ export class Runner {
|
|
|
876
883
|
if (this.runnerId !== init.runnerId) {
|
|
877
884
|
this.runnerId = init.runnerId;
|
|
878
885
|
|
|
886
|
+
// Invalidate cached child logger so subsequent log
|
|
887
|
+
// lines pick up the new runnerId.
|
|
888
|
+
this.#logCached = undefined;
|
|
889
|
+
|
|
879
890
|
// Clear actors if runner id changed
|
|
880
891
|
this.#stopAllActors();
|
|
881
892
|
}
|
|
@@ -1253,9 +1264,10 @@ export class Runner {
|
|
|
1253
1264
|
actorState = {
|
|
1254
1265
|
tag: "ActorStateStopped",
|
|
1255
1266
|
val: {
|
|
1256
|
-
code:
|
|
1257
|
-
|
|
1258
|
-
|
|
1267
|
+
code:
|
|
1268
|
+
actor.stopIntentSent || this.#draining
|
|
1269
|
+
? protocol.StopCode.Ok
|
|
1270
|
+
: protocol.StopCode.Error,
|
|
1259
1271
|
message: null,
|
|
1260
1272
|
},
|
|
1261
1273
|
};
|
package/src/tunnel.ts
CHANGED
|
@@ -10,7 +10,13 @@ import {
|
|
|
10
10
|
stringifyToClientTunnelMessageKind,
|
|
11
11
|
stringifyToServerTunnelMessageKind,
|
|
12
12
|
} from "./stringify";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
arraysEqual,
|
|
15
|
+
idToStr,
|
|
16
|
+
MAX_PAYLOAD_SIZE,
|
|
17
|
+
stringifyError,
|
|
18
|
+
unreachable,
|
|
19
|
+
} from "./utils";
|
|
14
20
|
import {
|
|
15
21
|
HIBERNATABLE_SYMBOL,
|
|
16
22
|
WebSocketTunnelAdapter,
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
VirtualWebSocket,
|
|
4
|
+
type UniversalWebSocket,
|
|
5
|
+
type RivetMessageEvent,
|
|
6
|
+
} from "@rivetkit/virtual-websocket";
|
|
3
7
|
import type { Tunnel } from "./tunnel";
|
|
4
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
MAX_PAYLOAD_SIZE,
|
|
10
|
+
wrappingAddU16,
|
|
11
|
+
wrappingLteU16,
|
|
12
|
+
wrappingSubU16,
|
|
13
|
+
} from "./utils";
|
|
5
14
|
|
|
6
15
|
export const HIBERNATABLE_SYMBOL = Symbol("hibernatable");
|
|
7
16
|
|
|
@@ -77,18 +86,28 @@ export class WebSocketTunnelAdapter {
|
|
|
77
86
|
|
|
78
87
|
messageData = data;
|
|
79
88
|
} else if (data instanceof ArrayBuffer) {
|
|
80
|
-
if (data.byteLength > MAX_PAYLOAD_SIZE)
|
|
89
|
+
if (data.byteLength > MAX_PAYLOAD_SIZE)
|
|
90
|
+
throw new Error("WebSocket message too large");
|
|
81
91
|
|
|
82
92
|
isBinary = true;
|
|
83
93
|
messageData = data;
|
|
84
94
|
} else if (ArrayBuffer.isView(data)) {
|
|
85
|
-
if (data.byteLength > MAX_PAYLOAD_SIZE)
|
|
95
|
+
if (data.byteLength > MAX_PAYLOAD_SIZE)
|
|
96
|
+
throw new Error("WebSocket message too large");
|
|
86
97
|
|
|
87
98
|
isBinary = true;
|
|
88
99
|
const view = data;
|
|
89
|
-
const buffer =
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
const buffer =
|
|
101
|
+
view.buffer instanceof SharedArrayBuffer
|
|
102
|
+
? new Uint8Array(
|
|
103
|
+
view.buffer,
|
|
104
|
+
view.byteOffset,
|
|
105
|
+
view.byteLength,
|
|
106
|
+
).slice().buffer
|
|
107
|
+
: view.buffer.slice(
|
|
108
|
+
view.byteOffset,
|
|
109
|
+
view.byteOffset + view.byteLength,
|
|
110
|
+
);
|
|
92
111
|
messageData = buffer as ArrayBuffer;
|
|
93
112
|
} else {
|
|
94
113
|
throw new Error("Unsupported data type");
|
|
@@ -101,7 +120,11 @@ export class WebSocketTunnelAdapter {
|
|
|
101
120
|
_handleOpen(requestId: ArrayBuffer): void {
|
|
102
121
|
if (this.#readyState !== 0) return;
|
|
103
122
|
this.#readyState = 1;
|
|
104
|
-
this.#ws.dispatchEvent({
|
|
123
|
+
this.#ws.dispatchEvent({
|
|
124
|
+
type: "open",
|
|
125
|
+
rivetRequestId: requestId,
|
|
126
|
+
target: this.#ws,
|
|
127
|
+
});
|
|
105
128
|
}
|
|
106
129
|
|
|
107
130
|
// Called by Tunnel when message is received
|
|
@@ -147,7 +170,10 @@ export class WebSocketTunnelAdapter {
|
|
|
147
170
|
expectedIndex,
|
|
148
171
|
receivedIndex: serverMessageIndex,
|
|
149
172
|
closeReason,
|
|
150
|
-
gap: wrappingSubU16(
|
|
173
|
+
gap: wrappingSubU16(
|
|
174
|
+
wrappingSubU16(serverMessageIndex, previousIndex),
|
|
175
|
+
1,
|
|
176
|
+
),
|
|
151
177
|
});
|
|
152
178
|
this.#close(1008, closeReason, true);
|
|
153
179
|
return true;
|
|
@@ -162,7 +188,10 @@ export class WebSocketTunnelAdapter {
|
|
|
162
188
|
if (this.#binaryType === "nodebuffer") {
|
|
163
189
|
messageData = Buffer.from(data);
|
|
164
190
|
} else if (this.#binaryType === "arraybuffer") {
|
|
165
|
-
messageData = data.buffer.slice(
|
|
191
|
+
messageData = data.buffer.slice(
|
|
192
|
+
data.byteOffset,
|
|
193
|
+
data.byteOffset + data.byteLength,
|
|
194
|
+
);
|
|
166
195
|
}
|
|
167
196
|
}
|
|
168
197
|
|
|
@@ -178,7 +207,11 @@ export class WebSocketTunnelAdapter {
|
|
|
178
207
|
}
|
|
179
208
|
|
|
180
209
|
// Called by Tunnel when close is received
|
|
181
|
-
_handleClose(
|
|
210
|
+
_handleClose(
|
|
211
|
+
_requestId: ArrayBuffer,
|
|
212
|
+
code?: number,
|
|
213
|
+
reason?: string,
|
|
214
|
+
): void {
|
|
182
215
|
this.#close(code, reason, true);
|
|
183
216
|
}
|
|
184
217
|
|
|
@@ -192,7 +225,11 @@ export class WebSocketTunnelAdapter {
|
|
|
192
225
|
this.#close(code, reason, true);
|
|
193
226
|
}
|
|
194
227
|
|
|
195
|
-
#close(
|
|
228
|
+
#close(
|
|
229
|
+
code: number | undefined,
|
|
230
|
+
reason: string | undefined,
|
|
231
|
+
sendCallback: boolean,
|
|
232
|
+
): void {
|
|
196
233
|
if (this.#readyState >= 2) return;
|
|
197
234
|
|
|
198
235
|
this.#readyState = 2;
|