rivetkit 2.0.21 → 2.0.22-rc.2
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/schemas/actor-persist/v2.ts +259 -0
- package/dist/tsup/actor/errors.cjs.map +1 -1
- package/dist/tsup/{chunk-HN7UXCYQ.cjs → chunk-5N6F5PXD.cjs} +31 -12
- package/dist/tsup/chunk-5N6F5PXD.cjs.map +1 -0
- package/dist/tsup/{chunk-FDJ3AVNB.cjs → chunk-5TRXLS6X.cjs} +71 -67
- package/dist/tsup/chunk-5TRXLS6X.cjs.map +1 -0
- package/dist/tsup/{chunk-HUGSRAGL.js → chunk-7RUROQAZ.js} +36 -16
- package/dist/tsup/chunk-7RUROQAZ.js.map +1 -0
- package/dist/tsup/{chunk-Y2QONT7B.js → chunk-AMK3AACS.js} +272 -89
- package/dist/tsup/chunk-AMK3AACS.js.map +1 -0
- package/dist/tsup/{chunk-RZZDFDB6.js → chunk-BHLQTKOD.js} +51 -47
- package/dist/tsup/chunk-BHLQTKOD.js.map +1 -0
- package/dist/tsup/{chunk-DYA34FHW.js → chunk-C4FPCW7T.js} +2 -2
- package/dist/tsup/{chunk-D2LS4X6E.js → chunk-CVLO2OOK.js} +3 -3
- package/dist/tsup/{chunk-6G76WIWL.js → chunk-EJXZYQ3N.js} +2 -2
- package/dist/tsup/{chunk-VLR3TDHT.js → chunk-F7WVJXPB.js} +2 -2
- package/dist/tsup/{chunk-4OINFQBR.js → chunk-FLVL7RGH.js} +3 -3
- package/dist/tsup/{chunk-JKOUXDK6.cjs → chunk-GXIO5YOT.cjs} +8 -8
- package/dist/tsup/chunk-GXIO5YOT.cjs.map +1 -0
- package/dist/tsup/{chunk-2POQCWMA.js → chunk-HLZT5C6A.js} +385 -104
- package/dist/tsup/chunk-HLZT5C6A.js.map +1 -0
- package/dist/tsup/chunk-KSRXX3Z4.cjs.map +1 -1
- package/dist/tsup/{chunk-JTIBPF7N.cjs → chunk-LFP446KS.cjs} +14 -14
- package/dist/tsup/chunk-LFP446KS.cjs.map +1 -0
- package/dist/tsup/{chunk-3UIGKLZW.js → chunk-MQDXPGNE.js} +6 -6
- package/dist/tsup/{chunk-O4GUKGK4.cjs → chunk-NDOG6IQ5.cjs} +6 -6
- package/dist/tsup/chunk-NDOG6IQ5.cjs.map +1 -0
- package/dist/tsup/{chunk-LMJHBF26.cjs → chunk-Q5CAVEKC.cjs} +467 -284
- package/dist/tsup/chunk-Q5CAVEKC.cjs.map +1 -0
- package/dist/tsup/{chunk-65SAIRRY.cjs → chunk-UBMUBNS2.cjs} +12 -12
- package/dist/tsup/chunk-UBMUBNS2.cjs.map +1 -0
- package/dist/tsup/{chunk-FUX6U6TL.js → chunk-VMFBKBJL.js} +26 -7
- package/dist/tsup/chunk-VMFBKBJL.js.map +1 -0
- package/dist/tsup/{chunk-M5BHNJHB.cjs → chunk-YLWF6RFL.cjs} +558 -277
- package/dist/tsup/chunk-YLWF6RFL.cjs.map +1 -0
- package/dist/tsup/{chunk-ELDFBXDV.cjs → chunk-YUBR6XCJ.cjs} +35 -15
- package/dist/tsup/chunk-YUBR6XCJ.cjs.map +1 -0
- package/dist/tsup/{chunk-ZNWE3XBT.cjs → chunk-ZL6NSKF2.cjs} +3 -3
- package/dist/tsup/chunk-ZL6NSKF2.cjs.map +1 -0
- package/dist/tsup/{chunk-LWGCMELP.cjs → chunk-ZY4DKLMT.cjs} +3 -3
- package/dist/tsup/chunk-ZY4DKLMT.cjs.map +1 -0
- package/dist/tsup/client/mod.cjs +9 -9
- package/dist/tsup/client/mod.cjs.map +1 -1
- package/dist/tsup/client/mod.d.cts +2 -2
- package/dist/tsup/client/mod.d.ts +2 -2
- package/dist/tsup/client/mod.js +8 -8
- package/dist/tsup/common/log.cjs +3 -3
- package/dist/tsup/common/log.cjs.map +1 -1
- package/dist/tsup/common/log.js +2 -2
- package/dist/tsup/common/websocket.cjs +4 -4
- package/dist/tsup/common/websocket.cjs.map +1 -1
- package/dist/tsup/common/websocket.js +3 -3
- package/dist/tsup/{conn-Clu655RU.d.ts → conn-BYXlxnh0.d.ts} +111 -102
- package/dist/tsup/{conn-lUvFLo_q.d.cts → conn-BiazosE_.d.cts} +111 -102
- package/dist/tsup/driver-helpers/mod.cjs +5 -5
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +1 -1
- package/dist/tsup/driver-helpers/mod.d.ts +1 -1
- package/dist/tsup/driver-helpers/mod.js +4 -4
- package/dist/tsup/driver-test-suite/mod.cjs +71 -71
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +1 -1
- package/dist/tsup/driver-test-suite/mod.d.ts +1 -1
- package/dist/tsup/driver-test-suite/mod.js +11 -11
- package/dist/tsup/inspector/mod.cjs +6 -6
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.d.cts +2 -2
- package/dist/tsup/inspector/mod.d.ts +2 -2
- package/dist/tsup/inspector/mod.js +5 -5
- package/dist/tsup/mod.cjs +10 -10
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +3 -3
- package/dist/tsup/mod.d.ts +3 -3
- package/dist/tsup/mod.js +9 -9
- package/dist/tsup/test/mod.cjs +11 -11
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +1 -1
- package/dist/tsup/test/mod.d.ts +1 -1
- package/dist/tsup/test/mod.js +10 -10
- package/dist/tsup/utils.cjs +8 -2
- package/dist/tsup/utils.cjs.map +1 -1
- package/dist/tsup/utils.d.cts +8 -1
- package/dist/tsup/utils.d.ts +8 -1
- package/dist/tsup/utils.js +7 -1
- package/package.json +5 -4
- package/src/actor/config.ts +10 -0
- package/src/actor/conn-drivers.ts +43 -1
- package/src/actor/conn-socket.ts +1 -1
- package/src/actor/conn.ts +22 -2
- package/src/actor/context.ts +1 -1
- package/src/actor/driver.ts +13 -2
- package/src/actor/instance.ts +248 -57
- package/src/actor/persisted.ts +7 -0
- package/src/actor/router-endpoints.ts +67 -45
- package/src/actor/router.ts +25 -17
- package/src/client/actor-conn.ts +9 -5
- package/src/common/cors.ts +57 -0
- package/src/common/log.ts +26 -5
- package/src/common/utils.ts +5 -9
- package/src/common/websocket-interface.ts +10 -0
- package/src/driver-helpers/utils.ts +1 -0
- package/src/drivers/engine/actor-driver.ts +261 -14
- package/src/drivers/engine/config.ts +2 -4
- package/src/drivers/file-system/actor.ts +3 -2
- package/src/drivers/file-system/global-state.ts +1 -1
- package/src/drivers/file-system/manager.ts +3 -0
- package/src/engine-process/mod.ts +22 -4
- package/src/inspector/config.ts +0 -45
- package/src/manager/gateway.ts +45 -32
- package/src/manager/hono-websocket-adapter.ts +31 -3
- package/src/manager/router.ts +11 -17
- package/src/registry/run-config.ts +2 -8
- package/src/remote-manager-driver/actor-http-client.ts +5 -8
- package/src/remote-manager-driver/actor-websocket-client.ts +2 -14
- package/src/remote-manager-driver/mod.ts +0 -1
- package/src/schemas/actor-persist/mod.ts +1 -1
- package/src/schemas/actor-persist/versioned.ts +22 -10
- package/src/utils.ts +26 -0
- package/dist/tsup/chunk-2POQCWMA.js.map +0 -1
- package/dist/tsup/chunk-65SAIRRY.cjs.map +0 -1
- package/dist/tsup/chunk-ELDFBXDV.cjs.map +0 -1
- package/dist/tsup/chunk-FDJ3AVNB.cjs.map +0 -1
- package/dist/tsup/chunk-FUX6U6TL.js.map +0 -1
- package/dist/tsup/chunk-HN7UXCYQ.cjs.map +0 -1
- package/dist/tsup/chunk-HUGSRAGL.js.map +0 -1
- package/dist/tsup/chunk-JKOUXDK6.cjs.map +0 -1
- package/dist/tsup/chunk-JTIBPF7N.cjs.map +0 -1
- package/dist/tsup/chunk-LMJHBF26.cjs.map +0 -1
- package/dist/tsup/chunk-LWGCMELP.cjs.map +0 -1
- package/dist/tsup/chunk-M5BHNJHB.cjs.map +0 -1
- package/dist/tsup/chunk-O4GUKGK4.cjs.map +0 -1
- package/dist/tsup/chunk-RZZDFDB6.js.map +0 -1
- package/dist/tsup/chunk-Y2QONT7B.js.map +0 -1
- package/dist/tsup/chunk-ZNWE3XBT.cjs.map +0 -1
- /package/dist/tsup/{chunk-DYA34FHW.js.map → chunk-C4FPCW7T.js.map} +0 -0
- /package/dist/tsup/{chunk-D2LS4X6E.js.map → chunk-CVLO2OOK.js.map} +0 -0
- /package/dist/tsup/{chunk-6G76WIWL.js.map → chunk-EJXZYQ3N.js.map} +0 -0
- /package/dist/tsup/{chunk-VLR3TDHT.js.map → chunk-F7WVJXPB.js.map} +0 -0
- /package/dist/tsup/{chunk-4OINFQBR.js.map → chunk-FLVL7RGH.js.map} +0 -0
- /package/dist/tsup/{chunk-3UIGKLZW.js.map → chunk-MQDXPGNE.js.map} +0 -0
package/src/manager/gateway.ts
CHANGED
|
@@ -134,8 +134,8 @@ async function handleHttpGatewayPathBased(
|
|
|
134
134
|
* Routes requests using either path-based routing or header-based routing:
|
|
135
135
|
*
|
|
136
136
|
* Path-based routing (checked first):
|
|
137
|
-
* - /gateway/
|
|
138
|
-
* - /gateway/
|
|
137
|
+
* - /gateway/{actor_id}/{...path}
|
|
138
|
+
* - /gateway/{actor_id}@{token}/{...path}
|
|
139
139
|
*
|
|
140
140
|
* Header-based routing (fallback):
|
|
141
141
|
* - WebSocket requests: Uses sec-websocket-protocol for routing (target.actor, actor.{id})
|
|
@@ -340,8 +340,8 @@ async function handleHttpGateway(
|
|
|
340
340
|
/**
|
|
341
341
|
* Parse actor routing information from path
|
|
342
342
|
* Matches patterns:
|
|
343
|
-
* - /gateway/
|
|
344
|
-
* - /gateway/
|
|
343
|
+
* - /gateway/{actor_id}/{...path}
|
|
344
|
+
* - /gateway/{actor_id}@{token}/{...path}
|
|
345
345
|
*/
|
|
346
346
|
export function parseActorPath(path: string): ActorPathInfo | null {
|
|
347
347
|
// Find query string position (everything from ? onwards, but before fragment)
|
|
@@ -374,50 +374,63 @@ export function parseActorPath(path: string): ActorPathInfo | null {
|
|
|
374
374
|
// Split the path into segments
|
|
375
375
|
const segments = basePath.split("/").filter((s) => s.length > 0);
|
|
376
376
|
|
|
377
|
-
// Check minimum required segments: gateway,
|
|
378
|
-
if (segments.length <
|
|
377
|
+
// Check minimum required segments: gateway, {actor_id}
|
|
378
|
+
if (segments.length < 2) {
|
|
379
379
|
return null;
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
-
// Verify the
|
|
383
|
-
if (segments[0] !== "gateway"
|
|
382
|
+
// Verify the first segment is "gateway"
|
|
383
|
+
if (segments[0] !== "gateway") {
|
|
384
384
|
return null;
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
-
//
|
|
388
|
-
|
|
387
|
+
// Extract actor_id segment (may contain @token)
|
|
388
|
+
const actorSegment = segments[1];
|
|
389
|
+
|
|
390
|
+
// Check for empty actor segment
|
|
391
|
+
if (actorSegment.length === 0) {
|
|
389
392
|
return null;
|
|
390
393
|
}
|
|
391
394
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
// Check for token or direct route
|
|
395
|
+
// Parse actor_id and optional token from the segment
|
|
396
|
+
let actorId: string;
|
|
395
397
|
let token: string | undefined;
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
if (
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
//
|
|
404
|
-
|
|
405
|
-
|
|
398
|
+
|
|
399
|
+
const atPos = actorSegment.indexOf("@");
|
|
400
|
+
if (atPos !== -1) {
|
|
401
|
+
// Pattern: /gateway/{actor_id}@{token}/{...path}
|
|
402
|
+
const rawActorId = actorSegment.slice(0, atPos);
|
|
403
|
+
const rawToken = actorSegment.slice(atPos + 1);
|
|
404
|
+
|
|
405
|
+
// Check for empty actor_id or token
|
|
406
|
+
if (rawActorId.length === 0 || rawToken.length === 0) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// URL-decode both actor_id and token
|
|
411
|
+
try {
|
|
412
|
+
actorId = decodeURIComponent(rawActorId);
|
|
413
|
+
token = decodeURIComponent(rawToken);
|
|
414
|
+
} catch (e) {
|
|
415
|
+
// Invalid URL encoding
|
|
406
416
|
return null;
|
|
407
417
|
}
|
|
408
|
-
token = segments[4];
|
|
409
|
-
remainingPathStartIdx = 6;
|
|
410
|
-
} else if (segments.length >= 4 && segments[3] === "route") {
|
|
411
|
-
// Pattern without token: /gateway/actors/{actor_id}/route/{...path}
|
|
412
|
-
token = undefined;
|
|
413
|
-
remainingPathStartIdx = 4;
|
|
414
418
|
} else {
|
|
415
|
-
|
|
419
|
+
// Pattern: /gateway/{actor_id}/{...path}
|
|
420
|
+
// URL-decode actor_id
|
|
421
|
+
try {
|
|
422
|
+
actorId = decodeURIComponent(actorSegment);
|
|
423
|
+
} catch (e) {
|
|
424
|
+
// Invalid URL encoding
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
token = undefined;
|
|
416
428
|
}
|
|
417
429
|
|
|
418
|
-
// Calculate
|
|
430
|
+
// Calculate remaining path
|
|
431
|
+
// The remaining path starts after /gateway/{actor_id[@token]}/
|
|
419
432
|
let prefixLen = 0;
|
|
420
|
-
for (let i = 0; i <
|
|
433
|
+
for (let i = 0; i < 2; i++) {
|
|
421
434
|
prefixLen += 1 + segments[i].length; // +1 for the slash
|
|
422
435
|
}
|
|
423
436
|
|
|
@@ -23,16 +23,28 @@ export class HonoWebSocketAdapter implements UniversalWebSocket {
|
|
|
23
23
|
#eventListeners: Map<string, Set<(event: any) => void>> = new Map();
|
|
24
24
|
#closeCode?: number;
|
|
25
25
|
#closeReason?: string;
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
readonly rivetRequestId?: ArrayBuffer;
|
|
27
|
+
readonly isHibernatable: boolean;
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
ws: WSContext,
|
|
31
|
+
rivetRequestId: ArrayBuffer | undefined,
|
|
32
|
+
isHibernatable: boolean,
|
|
33
|
+
) {
|
|
28
34
|
this.#ws = ws;
|
|
35
|
+
this.rivetRequestId = rivetRequestId;
|
|
36
|
+
this.isHibernatable = isHibernatable;
|
|
29
37
|
|
|
30
38
|
// The WSContext is already open when we receive it
|
|
31
39
|
this.#readyState = this.OPEN;
|
|
32
40
|
|
|
33
41
|
// Immediately fire the open event
|
|
34
42
|
setTimeout(() => {
|
|
35
|
-
this.#fireEvent("open", {
|
|
43
|
+
this.#fireEvent("open", {
|
|
44
|
+
type: "open",
|
|
45
|
+
target: this,
|
|
46
|
+
rivetRequestId: this.rivetRequestId,
|
|
47
|
+
});
|
|
36
48
|
}, 0);
|
|
37
49
|
}
|
|
38
50
|
|
|
@@ -155,6 +167,7 @@ export class HonoWebSocketAdapter implements UniversalWebSocket {
|
|
|
155
167
|
code,
|
|
156
168
|
reason,
|
|
157
169
|
wasClean: code === 1000,
|
|
170
|
+
rivetRequestId: this.rivetRequestId,
|
|
158
171
|
});
|
|
159
172
|
} catch (error) {
|
|
160
173
|
logger().error({ msg: "error closing websocket", error });
|
|
@@ -165,6 +178,7 @@ export class HonoWebSocketAdapter implements UniversalWebSocket {
|
|
|
165
178
|
code: 1006,
|
|
166
179
|
reason: "Abnormal closure",
|
|
167
180
|
wasClean: false,
|
|
181
|
+
rivetRequestId: this.rivetRequestId,
|
|
168
182
|
});
|
|
169
183
|
}
|
|
170
184
|
}
|
|
@@ -204,6 +218,8 @@ export class HonoWebSocketAdapter implements UniversalWebSocket {
|
|
|
204
218
|
_handleMessage(data: any): void {
|
|
205
219
|
// Hono may pass either raw data or a MessageEvent-like object
|
|
206
220
|
let messageData: string | ArrayBuffer | ArrayBufferView;
|
|
221
|
+
let rivetRequestId: ArrayBuffer | undefined;
|
|
222
|
+
let rivetMessageIndex: number | undefined;
|
|
207
223
|
|
|
208
224
|
if (typeof data === "string") {
|
|
209
225
|
messageData = data;
|
|
@@ -212,6 +228,14 @@ export class HonoWebSocketAdapter implements UniversalWebSocket {
|
|
|
212
228
|
} else if (data && typeof data === "object" && "data" in data) {
|
|
213
229
|
// Handle MessageEvent-like objects
|
|
214
230
|
messageData = data.data;
|
|
231
|
+
|
|
232
|
+
// Preserve hibernation-related properties from engine runner
|
|
233
|
+
if ("rivetRequestId" in data) {
|
|
234
|
+
rivetRequestId = data.rivetRequestId;
|
|
235
|
+
}
|
|
236
|
+
if ("rivetMessageIndex" in data) {
|
|
237
|
+
rivetMessageIndex = data.rivetMessageIndex;
|
|
238
|
+
}
|
|
215
239
|
} else {
|
|
216
240
|
// Fallback - shouldn't happen in normal operation
|
|
217
241
|
messageData = String(data);
|
|
@@ -222,12 +246,15 @@ export class HonoWebSocketAdapter implements UniversalWebSocket {
|
|
|
222
246
|
dataType: typeof messageData,
|
|
223
247
|
isArrayBuffer: messageData instanceof ArrayBuffer,
|
|
224
248
|
dataStr: typeof messageData === "string" ? messageData : "<binary>",
|
|
249
|
+
rivetMessageIndex,
|
|
225
250
|
});
|
|
226
251
|
|
|
227
252
|
this.#fireEvent("message", {
|
|
228
253
|
type: "message",
|
|
229
254
|
target: this,
|
|
230
255
|
data: messageData,
|
|
256
|
+
rivetRequestId,
|
|
257
|
+
rivetMessageIndex,
|
|
231
258
|
});
|
|
232
259
|
}
|
|
233
260
|
|
|
@@ -249,6 +276,7 @@ export class HonoWebSocketAdapter implements UniversalWebSocket {
|
|
|
249
276
|
code,
|
|
250
277
|
reason,
|
|
251
278
|
wasClean: code === 1000,
|
|
279
|
+
rivetRequestId: this.rivetRequestId,
|
|
252
280
|
});
|
|
253
281
|
}
|
|
254
282
|
|
package/src/manager/router.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
type MiddlewareHandler,
|
|
7
7
|
type Next,
|
|
8
8
|
} from "hono";
|
|
9
|
-
import { cors as corsMiddleware } from "hono/cors";
|
|
10
9
|
import { createMiddleware } from "hono/factory";
|
|
11
10
|
import { streamSSE } from "hono/streaming";
|
|
12
11
|
import invariant from "invariant";
|
|
@@ -23,13 +22,13 @@ import {
|
|
|
23
22
|
WS_PROTOCOL_PATH,
|
|
24
23
|
WS_PROTOCOL_TRANSPORT,
|
|
25
24
|
} from "@/common/actor-router-consts";
|
|
25
|
+
import { cors } from "@/common/cors";
|
|
26
26
|
import {
|
|
27
27
|
handleHealthRequest,
|
|
28
28
|
handleMetadataRequest,
|
|
29
29
|
handleRouteError,
|
|
30
30
|
handleRouteNotFound,
|
|
31
31
|
loggerMiddleware,
|
|
32
|
-
type MetadataResponse,
|
|
33
32
|
} from "@/common/router";
|
|
34
33
|
import {
|
|
35
34
|
assertUnreachable,
|
|
@@ -37,7 +36,7 @@ import {
|
|
|
37
36
|
noopNext,
|
|
38
37
|
stringifyError,
|
|
39
38
|
} from "@/common/utils";
|
|
40
|
-
import {
|
|
39
|
+
import { HEADER_ACTOR_ID } from "@/driver-helpers/mod";
|
|
41
40
|
import type {
|
|
42
41
|
TestInlineDriverCallRequest,
|
|
43
42
|
TestInlineDriverCallResponse,
|
|
@@ -45,11 +44,9 @@ import type {
|
|
|
45
44
|
import { createManagerInspectorRouter } from "@/inspector/manager";
|
|
46
45
|
import { isInspectorEnabled, secureInspector } from "@/inspector/utils";
|
|
47
46
|
import {
|
|
48
|
-
type ActorsCreateRequest,
|
|
49
47
|
ActorsCreateRequestSchema,
|
|
50
48
|
type ActorsCreateResponse,
|
|
51
49
|
ActorsCreateResponseSchema,
|
|
52
|
-
type ActorsGetOrCreateRequest,
|
|
53
50
|
ActorsGetOrCreateRequestSchema,
|
|
54
51
|
type ActorsGetOrCreateResponse,
|
|
55
52
|
ActorsGetOrCreateResponseSchema,
|
|
@@ -57,11 +54,9 @@ import {
|
|
|
57
54
|
ActorsListResponseSchema,
|
|
58
55
|
type Actor as ApiActor,
|
|
59
56
|
} from "@/manager-api/actors";
|
|
60
|
-
import { RivetIdSchema } from "@/manager-api/common";
|
|
61
57
|
import type { AnyClient } from "@/mod";
|
|
62
58
|
import type { RegistryConfig } from "@/registry/config";
|
|
63
59
|
import type { DriverConfig, RunnerConfig } from "@/registry/run-config";
|
|
64
|
-
import { VERSION } from "@/utils";
|
|
65
60
|
import type { ActorOutput, ManagerDriver } from "./driver";
|
|
66
61
|
import { actorGateway, createTestWebSocketProxy } from "./gateway";
|
|
67
62
|
import { logger } from "./log";
|
|
@@ -97,7 +92,7 @@ export function createManagerRouter(
|
|
|
97
92
|
runConfig.basePath,
|
|
98
93
|
);
|
|
99
94
|
|
|
100
|
-
router.use("*", loggerMiddleware(logger()));
|
|
95
|
+
router.use("*", loggerMiddleware(logger()), cors());
|
|
101
96
|
|
|
102
97
|
// HACK: Add Sec-WebSocket-Protocol header to fix KIT-339
|
|
103
98
|
//
|
|
@@ -148,9 +143,6 @@ function addServerlessRoutes(
|
|
|
148
143
|
client: AnyClient,
|
|
149
144
|
router: OpenAPIHono,
|
|
150
145
|
) {
|
|
151
|
-
// Apply CORS
|
|
152
|
-
if (runConfig.cors) router.use("*", corsMiddleware(runConfig.cors));
|
|
153
|
-
|
|
154
146
|
// GET /
|
|
155
147
|
router.get("/", (c) => {
|
|
156
148
|
return c.text(
|
|
@@ -194,6 +186,13 @@ function addServerlessRoutes(
|
|
|
194
186
|
newRunConfig.totalSlots = totalSlots;
|
|
195
187
|
newRunConfig.runnerName = runnerName;
|
|
196
188
|
newRunConfig.namespace = namespace;
|
|
189
|
+
if (newRunConfig.runnerKey) {
|
|
190
|
+
logger().warn({
|
|
191
|
+
msg: "runner keys are not supported by serverless runners, this will be overwritten with a random runner key",
|
|
192
|
+
oldRunnerKey: newRunConfig.runnerKey,
|
|
193
|
+
});
|
|
194
|
+
newRunConfig.runnerKey = undefined;
|
|
195
|
+
}
|
|
197
196
|
|
|
198
197
|
// Create new actor driver with updated config
|
|
199
198
|
const actorDriver = driverConfig.actor(
|
|
@@ -223,8 +222,7 @@ function addManagerRoutes(
|
|
|
223
222
|
managerDriver: ManagerDriver,
|
|
224
223
|
router: OpenAPIHono,
|
|
225
224
|
) {
|
|
226
|
-
//
|
|
227
|
-
// CORS config that should take precedence for the `/inspector` path
|
|
225
|
+
// Inspector
|
|
228
226
|
if (isInspectorEnabled(runConfig, "manager")) {
|
|
229
227
|
if (!managerDriver.inspector) {
|
|
230
228
|
throw new Unsupported("inspector");
|
|
@@ -232,7 +230,6 @@ function addManagerRoutes(
|
|
|
232
230
|
router.route(
|
|
233
231
|
"/inspect",
|
|
234
232
|
new Hono<{ Variables: { inspector: any } }>()
|
|
235
|
-
.use(corsMiddleware(runConfig.inspector.cors))
|
|
236
233
|
.use(secureInspector(runConfig))
|
|
237
234
|
.use((c, next) => {
|
|
238
235
|
c.set("inspector", managerDriver.inspector!);
|
|
@@ -242,9 +239,6 @@ function addManagerRoutes(
|
|
|
242
239
|
);
|
|
243
240
|
}
|
|
244
241
|
|
|
245
|
-
// Apply CORS
|
|
246
|
-
if (runConfig.cors) router.use("*", corsMiddleware(runConfig.cors));
|
|
247
|
-
|
|
248
242
|
// Actor gateway
|
|
249
243
|
router.use("*", actorGateway.bind(undefined, runConfig, managerDriver));
|
|
250
244
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { cors } from "hono/cors";
|
|
2
1
|
import type { Logger } from "pino";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import type { ActorDriverBuilder } from "@/actor/driver";
|
|
@@ -7,9 +6,7 @@ import { EngingConfigSchema as EngineConfigSchema } from "@/drivers/engine/confi
|
|
|
7
6
|
import { InspectorConfigSchema } from "@/inspector/config";
|
|
8
7
|
import type { ManagerDriverBuilder } from "@/manager/driver";
|
|
9
8
|
import type { GetUpgradeWebSocket } from "@/utils";
|
|
10
|
-
import { getEnvUniversal } from "@/utils";
|
|
11
|
-
|
|
12
|
-
type CorsOptions = NonNullable<Parameters<typeof cors>[0]>;
|
|
9
|
+
import { getEnvUniversal, VERSION } from "@/utils";
|
|
13
10
|
|
|
14
11
|
export const DriverConfigSchema = z.object({
|
|
15
12
|
/** Machine-readable name to identify this driver by. */
|
|
@@ -25,9 +22,6 @@ export const RunnerConfigSchema = z
|
|
|
25
22
|
.object({
|
|
26
23
|
driver: DriverConfigSchema.optional(),
|
|
27
24
|
|
|
28
|
-
/** CORS configuration for the router. Uses Hono's CORS middleware options. */
|
|
29
|
-
cors: z.custom<CorsOptions>().optional(),
|
|
30
|
-
|
|
31
25
|
/** @experimental */
|
|
32
26
|
maxIncomingMessageSize: z.number().optional().default(65_536),
|
|
33
27
|
|
|
@@ -51,7 +45,7 @@ export const RunnerConfigSchema = z
|
|
|
51
45
|
.string()
|
|
52
46
|
.optional()
|
|
53
47
|
.default(
|
|
54
|
-
() => getEnvUniversal("RIVET_RUN_ENGINE_VERSION") ??
|
|
48
|
+
() => getEnvUniversal("RIVET_RUN_ENGINE_VERSION") ?? VERSION,
|
|
55
49
|
),
|
|
56
50
|
|
|
57
51
|
/** @experimental */
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import type { ClientConfig } from "@/client/config";
|
|
2
|
-
import {
|
|
3
|
-
HEADER_RIVET_ACTOR,
|
|
4
|
-
HEADER_RIVET_TARGET,
|
|
5
|
-
HEADER_RIVET_TOKEN,
|
|
6
|
-
} from "@/common/actor-router-consts";
|
|
2
|
+
import { HEADER_RIVET_TOKEN } from "@/common/actor-router-consts";
|
|
7
3
|
import { combineUrlPath } from "@/utils";
|
|
8
4
|
import { getEndpoint } from "./api-utils";
|
|
9
5
|
|
|
@@ -15,7 +11,10 @@ export async function sendHttpRequestToActor(
|
|
|
15
11
|
// Route through guard port
|
|
16
12
|
const url = new URL(actorRequest.url);
|
|
17
13
|
const endpoint = getEndpoint(runConfig);
|
|
18
|
-
const guardUrl = combineUrlPath(
|
|
14
|
+
const guardUrl = combineUrlPath(
|
|
15
|
+
endpoint,
|
|
16
|
+
`/gateway/${actorId}${url.pathname}${url.search}`,
|
|
17
|
+
);
|
|
19
18
|
|
|
20
19
|
// Handle body properly based on method and presence
|
|
21
20
|
let bodyToSend: ArrayBuffer | null = null;
|
|
@@ -76,8 +75,6 @@ function buildGuardHeadersForHttp(
|
|
|
76
75
|
headers.set(key, value);
|
|
77
76
|
}
|
|
78
77
|
// Add guard-specific headers
|
|
79
|
-
headers.set(HEADER_RIVET_TARGET, "actor");
|
|
80
|
-
headers.set(HEADER_RIVET_ACTOR, actorId);
|
|
81
78
|
if (runConfig.token) {
|
|
82
79
|
headers.set(HEADER_RIVET_TOKEN, runConfig.token);
|
|
83
80
|
}
|
|
@@ -2,13 +2,11 @@ import type { ClientConfig } from "@/client/config";
|
|
|
2
2
|
import {
|
|
3
3
|
HEADER_CONN_PARAMS,
|
|
4
4
|
HEADER_ENCODING,
|
|
5
|
-
WS_PROTOCOL_ACTOR,
|
|
6
5
|
WS_PROTOCOL_CONN_ID,
|
|
7
6
|
WS_PROTOCOL_CONN_PARAMS,
|
|
8
7
|
WS_PROTOCOL_CONN_TOKEN,
|
|
9
8
|
WS_PROTOCOL_ENCODING,
|
|
10
9
|
WS_PROTOCOL_STANDARD as WS_PROTOCOL_RIVETKIT,
|
|
11
|
-
WS_PROTOCOL_TARGET,
|
|
12
10
|
WS_PROTOCOL_TOKEN,
|
|
13
11
|
} from "@/common/actor-router-consts";
|
|
14
12
|
import { importWebSocket } from "@/common/websocket";
|
|
@@ -30,7 +28,7 @@ export async function openWebSocketToActor(
|
|
|
30
28
|
|
|
31
29
|
// WebSocket connections go through guard
|
|
32
30
|
const endpoint = getEndpoint(runConfig);
|
|
33
|
-
const guardUrl = combineUrlPath(endpoint, path);
|
|
31
|
+
const guardUrl = combineUrlPath(endpoint, `/gateway/${actorId}${path}`);
|
|
34
32
|
|
|
35
33
|
logger().debug({
|
|
36
34
|
msg: "opening websocket to actor via guard",
|
|
@@ -42,14 +40,7 @@ export async function openWebSocketToActor(
|
|
|
42
40
|
// Create WebSocket connection
|
|
43
41
|
const ws = new WebSocket(
|
|
44
42
|
guardUrl,
|
|
45
|
-
buildWebSocketProtocols(
|
|
46
|
-
runConfig,
|
|
47
|
-
actorId,
|
|
48
|
-
encoding,
|
|
49
|
-
params,
|
|
50
|
-
connId,
|
|
51
|
-
connToken,
|
|
52
|
-
),
|
|
43
|
+
buildWebSocketProtocols(runConfig, encoding, params, connId, connToken),
|
|
53
44
|
);
|
|
54
45
|
|
|
55
46
|
// Set binary type to arraybuffer for proper encoding support
|
|
@@ -62,7 +53,6 @@ export async function openWebSocketToActor(
|
|
|
62
53
|
|
|
63
54
|
export function buildWebSocketProtocols(
|
|
64
55
|
runConfig: ClientConfig,
|
|
65
|
-
actorId: string,
|
|
66
56
|
encoding: Encoding,
|
|
67
57
|
params?: unknown,
|
|
68
58
|
connId?: string,
|
|
@@ -70,8 +60,6 @@ export function buildWebSocketProtocols(
|
|
|
70
60
|
): string[] {
|
|
71
61
|
const protocols: string[] = [];
|
|
72
62
|
protocols.push(WS_PROTOCOL_RIVETKIT);
|
|
73
|
-
protocols.push(`${WS_PROTOCOL_TARGET}actor`);
|
|
74
|
-
protocols.push(`${WS_PROTOCOL_ACTOR}${actorId}`);
|
|
75
63
|
protocols.push(`${WS_PROTOCOL_ENCODING}${encoding}`);
|
|
76
64
|
if (runConfig.token) {
|
|
77
65
|
protocols.push(`${WS_PROTOCOL_TOKEN}${runConfig.token}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "../../../dist/schemas/actor-persist/
|
|
1
|
+
export * from "../../../dist/schemas/actor-persist/v2";
|
|
@@ -2,24 +2,36 @@ import {
|
|
|
2
2
|
createVersionedDataHandler,
|
|
3
3
|
type MigrationFn,
|
|
4
4
|
} from "@/common/versioned-data";
|
|
5
|
-
import * as v1 from "../../../dist/schemas/actor-persist/v1";
|
|
5
|
+
import type * as v1 from "../../../dist/schemas/actor-persist/v1";
|
|
6
|
+
import * as v2 from "../../../dist/schemas/actor-persist/v2";
|
|
6
7
|
|
|
7
|
-
export const CURRENT_VERSION =
|
|
8
|
+
export const CURRENT_VERSION = 2;
|
|
8
9
|
|
|
9
|
-
export type CurrentPersistedActor =
|
|
10
|
-
export type CurrentPersistedConnection =
|
|
11
|
-
export type CurrentPersistedSubscription =
|
|
10
|
+
export type CurrentPersistedActor = v2.PersistedActor;
|
|
11
|
+
export type CurrentPersistedConnection = v2.PersistedConnection;
|
|
12
|
+
export type CurrentPersistedSubscription = v2.PersistedSubscription;
|
|
12
13
|
export type CurrentGenericPersistedScheduleEvent =
|
|
13
|
-
|
|
14
|
-
export type CurrentPersistedScheduleEventKind =
|
|
15
|
-
export type CurrentPersistedScheduleEvent =
|
|
14
|
+
v2.GenericPersistedScheduleEvent;
|
|
15
|
+
export type CurrentPersistedScheduleEventKind = v2.PersistedScheduleEventKind;
|
|
16
|
+
export type CurrentPersistedScheduleEvent = v2.PersistedScheduleEvent;
|
|
17
|
+
export type CurrentPersistedHibernatableWebSocket =
|
|
18
|
+
v2.PersistedHibernatableWebSocket;
|
|
16
19
|
|
|
17
20
|
const migrations = new Map<number, MigrationFn<any, any>>();
|
|
18
21
|
|
|
22
|
+
// Migration from v1 to v2: Add hibernatableWebSocket field
|
|
23
|
+
migrations.set(
|
|
24
|
+
1,
|
|
25
|
+
(v1Data: v1.PersistedActor): v2.PersistedActor => ({
|
|
26
|
+
...v1Data,
|
|
27
|
+
hibernatableWebSocket: [],
|
|
28
|
+
}),
|
|
29
|
+
);
|
|
30
|
+
|
|
19
31
|
export const PERSISTED_ACTOR_VERSIONED =
|
|
20
32
|
createVersionedDataHandler<CurrentPersistedActor>({
|
|
21
33
|
currentVersion: CURRENT_VERSION,
|
|
22
34
|
migrations,
|
|
23
|
-
serializeVersion: (data) =>
|
|
24
|
-
deserializeVersion: (bytes) =>
|
|
35
|
+
serializeVersion: (data) => v2.encodePersistedActor(data),
|
|
36
|
+
deserializeVersion: (bytes) => v2.decodePersistedActor(bytes),
|
|
25
37
|
});
|
package/src/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { stringifyError } from "@/common/utils";
|
|
|
2
2
|
export { assertUnreachable } from "./common/utils";
|
|
3
3
|
|
|
4
4
|
import type { Context as HonoContext, Handler as HonoHandler } from "hono";
|
|
5
|
+
import { stringify as uuidstringify } from "uuid";
|
|
5
6
|
|
|
6
7
|
import pkgJson from "../package.json" with { type: "json" };
|
|
7
8
|
|
|
@@ -248,3 +249,28 @@ export function combineUrlPath(
|
|
|
248
249
|
const fullQuery = queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
|
|
249
250
|
return `${baseUrl.protocol}//${baseUrl.host}${fullPath}${fullQuery}`;
|
|
250
251
|
}
|
|
252
|
+
|
|
253
|
+
export function arrayBuffersEqual(
|
|
254
|
+
buf1: ArrayBuffer,
|
|
255
|
+
buf2: ArrayBuffer,
|
|
256
|
+
): boolean {
|
|
257
|
+
if (buf1.byteLength !== buf2.byteLength) return false;
|
|
258
|
+
|
|
259
|
+
const view1 = new Uint8Array(buf1);
|
|
260
|
+
const view2 = new Uint8Array(buf2);
|
|
261
|
+
|
|
262
|
+
for (let i = 0; i < view1.length; i++) {
|
|
263
|
+
if (view1[i] !== view2[i]) return false;
|
|
264
|
+
}
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export const EXTRA_ERROR_LOG = {
|
|
269
|
+
issues: "https://github.com/rivet-dev/rivetkit/issues",
|
|
270
|
+
support: "https://rivet.dev/discord",
|
|
271
|
+
version: VERSION,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
export function idToStr(id: ArrayBuffer): string {
|
|
275
|
+
return uuidstringify(new Uint8Array(id));
|
|
276
|
+
}
|