rivetkit 2.0.22-rc.1 → 2.0.22
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/{chunk-LCQDY73V.cjs → chunk-2GJILCGQ.cjs} +3 -3
- package/dist/tsup/{chunk-LCQDY73V.cjs.map → chunk-2GJILCGQ.cjs.map} +1 -1
- package/dist/tsup/{chunk-JN6GPVFY.js → chunk-2K2LR56Q.js} +3 -3
- package/dist/tsup/{chunk-EEXX243L.js → chunk-2WVCZCJL.js} +6 -6
- package/dist/tsup/{chunk-FETQGZN4.js → chunk-3BJJSSTM.js} +272 -89
- package/dist/tsup/chunk-3BJJSSTM.js.map +1 -0
- package/dist/tsup/{chunk-ZZYMCYAY.cjs → chunk-3LFMVAJV.cjs} +14 -14
- package/dist/tsup/{chunk-ZZYMCYAY.cjs.map → chunk-3LFMVAJV.cjs.map} +1 -1
- package/dist/tsup/{chunk-NDLOG2JH.js → chunk-6YQKMAMV.js} +2 -2
- package/dist/tsup/{chunk-C2U6KGOG.cjs → chunk-AR4S2QJ7.cjs} +3 -3
- package/dist/tsup/{chunk-C2U6KGOG.cjs.map → chunk-AR4S2QJ7.cjs.map} +1 -1
- package/dist/tsup/{chunk-PELXJCJS.cjs → chunk-B4QZKOMH.cjs} +8 -8
- package/dist/tsup/{chunk-PELXJCJS.cjs.map → chunk-B4QZKOMH.cjs.map} +1 -1
- package/dist/tsup/{chunk-5EB77IQ2.cjs → chunk-CYA35VI3.cjs} +6 -6
- package/dist/tsup/{chunk-5EB77IQ2.cjs.map → chunk-CYA35VI3.cjs.map} +1 -1
- package/dist/tsup/{chunk-UBCUW7HD.js → chunk-D7AA2DK5.js} +2 -2
- package/dist/tsup/{chunk-I7EJWHYV.js → chunk-EBSGEDD3.js} +51 -47
- package/dist/tsup/chunk-EBSGEDD3.js.map +1 -0
- package/dist/tsup/{chunk-R6XOZKMU.cjs → chunk-HSO2H2SB.cjs} +467 -284
- package/dist/tsup/chunk-HSO2H2SB.cjs.map +1 -0
- package/dist/tsup/{chunk-VJLGVVGP.cjs → chunk-HZ4ZM3FL.cjs} +31 -12
- package/dist/tsup/chunk-HZ4ZM3FL.cjs.map +1 -0
- package/dist/tsup/{chunk-7FEMVD3D.cjs → chunk-LMZSOCYD.cjs} +12 -12
- package/dist/tsup/{chunk-7FEMVD3D.cjs.map → chunk-LMZSOCYD.cjs.map} +1 -1
- package/dist/tsup/{chunk-ZVEDMBFT.js → chunk-PBFLG45S.js} +3 -3
- package/dist/tsup/{chunk-GJPOIJHZ.js → chunk-ST6FGRCH.js} +26 -7
- package/dist/tsup/chunk-ST6FGRCH.js.map +1 -0
- package/dist/tsup/{chunk-BIOPK7IB.cjs → chunk-TI72NLP3.cjs} +71 -67
- package/dist/tsup/chunk-TI72NLP3.cjs.map +1 -0
- package/dist/tsup/{chunk-RPI45FGS.js → chunk-TQ4OAC2G.js} +2 -2
- package/dist/tsup/{chunk-4B25D5OW.js → chunk-UB4OHFDW.js} +385 -104
- package/dist/tsup/chunk-UB4OHFDW.js.map +1 -0
- package/dist/tsup/{chunk-6Z3YA6QR.cjs → chunk-V6C34TVH.cjs} +35 -15
- package/dist/tsup/chunk-V6C34TVH.cjs.map +1 -0
- package/dist/tsup/{chunk-OAB7ECAB.cjs → chunk-WVUAO2F7.cjs} +558 -277
- package/dist/tsup/chunk-WVUAO2F7.cjs.map +1 -0
- package/dist/tsup/{chunk-JKNDUKFI.js → chunk-WWAZJHTS.js} +36 -16
- package/dist/tsup/chunk-WWAZJHTS.js.map +1 -0
- package/dist/tsup/client/mod.cjs +9 -9
- 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.js +2 -2
- package/dist/tsup/common/websocket.cjs +4 -4
- 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.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.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.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.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.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-4B25D5OW.js.map +0 -1
- package/dist/tsup/chunk-6Z3YA6QR.cjs.map +0 -1
- package/dist/tsup/chunk-BIOPK7IB.cjs.map +0 -1
- package/dist/tsup/chunk-FETQGZN4.js.map +0 -1
- package/dist/tsup/chunk-GJPOIJHZ.js.map +0 -1
- package/dist/tsup/chunk-I7EJWHYV.js.map +0 -1
- package/dist/tsup/chunk-JKNDUKFI.js.map +0 -1
- package/dist/tsup/chunk-OAB7ECAB.cjs.map +0 -1
- package/dist/tsup/chunk-R6XOZKMU.cjs.map +0 -1
- package/dist/tsup/chunk-VJLGVVGP.cjs.map +0 -1
- /package/dist/tsup/{chunk-JN6GPVFY.js.map → chunk-2K2LR56Q.js.map} +0 -0
- /package/dist/tsup/{chunk-EEXX243L.js.map → chunk-2WVCZCJL.js.map} +0 -0
- /package/dist/tsup/{chunk-NDLOG2JH.js.map → chunk-6YQKMAMV.js.map} +0 -0
- /package/dist/tsup/{chunk-UBCUW7HD.js.map → chunk-D7AA2DK5.js.map} +0 -0
- /package/dist/tsup/{chunk-ZVEDMBFT.js.map → chunk-PBFLG45S.js.map} +0 -0
- /package/dist/tsup/{chunk-RPI45FGS.js.map → chunk-TQ4OAC2G.js.map} +0 -0
|
@@ -7,12 +7,12 @@ import { ActionContext } from "@/actor/action";
|
|
|
7
7
|
import type { AnyConn } from "@/actor/conn";
|
|
8
8
|
import {
|
|
9
9
|
generateConnId,
|
|
10
|
-
|
|
10
|
+
generateConnRequestId,
|
|
11
11
|
generateConnToken,
|
|
12
12
|
} from "@/actor/conn";
|
|
13
13
|
import { ConnDriverKind } from "@/actor/conn-drivers";
|
|
14
14
|
import * as errors from "@/actor/errors";
|
|
15
|
-
import type
|
|
15
|
+
import { type AnyActorInstance, PERSIST_SYMBOL } from "@/actor/instance";
|
|
16
16
|
import type { InputData } from "@/actor/protocol/serde";
|
|
17
17
|
import { type Encoding, EncodingSchema } from "@/actor/protocol/serde";
|
|
18
18
|
import {
|
|
@@ -38,7 +38,11 @@ import {
|
|
|
38
38
|
deserializeWithEncoding,
|
|
39
39
|
serializeWithEncoding,
|
|
40
40
|
} from "@/serde";
|
|
41
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
arrayBuffersEqual,
|
|
43
|
+
bufferToArrayBuffer,
|
|
44
|
+
promiseWithResolvers,
|
|
45
|
+
} from "@/utils";
|
|
42
46
|
import type { ActorDriver } from "./driver";
|
|
43
47
|
import { loggerWithoutContext } from "./log";
|
|
44
48
|
import { parseMessage } from "./protocol/old";
|
|
@@ -111,8 +115,9 @@ export async function handleWebSocketConnect(
|
|
|
111
115
|
actorId: string,
|
|
112
116
|
encoding: Encoding,
|
|
113
117
|
parameters: unknown,
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
requestId: string,
|
|
119
|
+
connId: string | undefined,
|
|
120
|
+
connToken: string | undefined,
|
|
116
121
|
): Promise<UpgradeWebSocketArgs> {
|
|
117
122
|
const exposeInternalError = req
|
|
118
123
|
? getRequestExposeInternalError(req)
|
|
@@ -157,7 +162,9 @@ export async function handleWebSocketConnect(
|
|
|
157
162
|
|
|
158
163
|
// Promise used to wait for the websocket close in `disconnect`
|
|
159
164
|
const closePromise = promiseWithResolvers<void>();
|
|
160
|
-
|
|
165
|
+
|
|
166
|
+
// Track connection outside of scope for cleanup
|
|
167
|
+
let createdConn: AnyConn | undefined;
|
|
161
168
|
|
|
162
169
|
return {
|
|
163
170
|
onOpen: (_evt: any, ws: WSContext) => {
|
|
@@ -179,7 +186,7 @@ export async function handleWebSocketConnect(
|
|
|
179
186
|
|
|
180
187
|
conn = await actor.createConn(
|
|
181
188
|
{
|
|
182
|
-
|
|
189
|
+
requestId: requestId,
|
|
183
190
|
driverState: {
|
|
184
191
|
[ConnDriverKind.WEBSOCKET]: {
|
|
185
192
|
encoding,
|
|
@@ -194,6 +201,9 @@ export async function handleWebSocketConnect(
|
|
|
194
201
|
connToken,
|
|
195
202
|
);
|
|
196
203
|
|
|
204
|
+
// Store connection so we can clean on close
|
|
205
|
+
createdConn = conn;
|
|
206
|
+
|
|
197
207
|
// Unblock other handlers
|
|
198
208
|
handlersResolve({ conn, actor, connId: conn.id });
|
|
199
209
|
} catch (error) {
|
|
@@ -294,20 +304,13 @@ export async function handleWebSocketConnect(
|
|
|
294
304
|
// https://github.com/cloudflare/workerd/issues/2569
|
|
295
305
|
ws.close(1000, "hack_force_close");
|
|
296
306
|
|
|
297
|
-
//
|
|
298
|
-
handlersPromise
|
|
299
|
-
|
|
307
|
+
// Wait for actor.createConn to finish before removing the connection
|
|
308
|
+
handlersPromise.finally(() => {
|
|
309
|
+
if (createdConn) {
|
|
300
310
|
const wasClean = event.wasClean || event.code === 1000;
|
|
301
|
-
actor.__connDisconnected(
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
deconstructError(
|
|
305
|
-
error,
|
|
306
|
-
actor.rLog,
|
|
307
|
-
{ wsEvent: "close" },
|
|
308
|
-
exposeInternalError,
|
|
309
|
-
);
|
|
310
|
-
});
|
|
311
|
+
actor.__connDisconnected(createdConn, wasClean, requestId);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
311
314
|
},
|
|
312
315
|
onError: (_error: unknown) => {
|
|
313
316
|
try {
|
|
@@ -338,7 +341,7 @@ export async function handleSseConnect(
|
|
|
338
341
|
|
|
339
342
|
const encoding = getRequestEncoding(c.req);
|
|
340
343
|
const parameters = getRequestConnParams(c.req);
|
|
341
|
-
const
|
|
344
|
+
const requestId = generateConnRequestId();
|
|
342
345
|
|
|
343
346
|
// Check for reconnection parameters
|
|
344
347
|
const connId = c.req.header(HEADER_CONN_ID);
|
|
@@ -361,7 +364,7 @@ export async function handleSseConnect(
|
|
|
361
364
|
|
|
362
365
|
conn = await actor.createConn(
|
|
363
366
|
{
|
|
364
|
-
|
|
367
|
+
requestId: requestId,
|
|
365
368
|
driverState: {
|
|
366
369
|
[ConnDriverKind.SSE]: {
|
|
367
370
|
encoding,
|
|
@@ -392,7 +395,7 @@ export async function handleSseConnect(
|
|
|
392
395
|
|
|
393
396
|
// Cleanup
|
|
394
397
|
if (conn) {
|
|
395
|
-
actor.__connDisconnected(conn, false,
|
|
398
|
+
actor.__connDisconnected(conn, false, requestId);
|
|
396
399
|
}
|
|
397
400
|
|
|
398
401
|
abortResolver.resolve(undefined);
|
|
@@ -431,7 +434,7 @@ export async function handleSseConnect(
|
|
|
431
434
|
|
|
432
435
|
// Cleanup on error
|
|
433
436
|
if (conn && actor !== undefined) {
|
|
434
|
-
actor.__connDisconnected(conn, false,
|
|
437
|
+
actor.__connDisconnected(conn, false, requestId);
|
|
435
438
|
}
|
|
436
439
|
|
|
437
440
|
// Close the stream on error
|
|
@@ -461,7 +464,7 @@ export async function handleAction(
|
|
|
461
464
|
HTTP_ACTION_REQUEST_VERSIONED,
|
|
462
465
|
);
|
|
463
466
|
const actionArgs = cbor.decode(new Uint8Array(request.args));
|
|
464
|
-
const
|
|
467
|
+
const requestId = generateConnRequestId();
|
|
465
468
|
|
|
466
469
|
// Invoke the action
|
|
467
470
|
let actor: AnyActorInstance | undefined;
|
|
@@ -475,7 +478,7 @@ export async function handleAction(
|
|
|
475
478
|
// Create conn
|
|
476
479
|
conn = await actor.createConn(
|
|
477
480
|
{
|
|
478
|
-
|
|
481
|
+
requestId: requestId,
|
|
479
482
|
driverState: { [ConnDriverKind.HTTP]: {} },
|
|
480
483
|
},
|
|
481
484
|
parameters,
|
|
@@ -488,7 +491,7 @@ export async function handleAction(
|
|
|
488
491
|
} finally {
|
|
489
492
|
if (conn) {
|
|
490
493
|
// HTTP connections don't have persistent sockets, so no socket ID needed
|
|
491
|
-
actor?.__connDisconnected(conn, true,
|
|
494
|
+
actor?.__connDisconnected(conn, true, requestId);
|
|
492
495
|
}
|
|
493
496
|
}
|
|
494
497
|
|
|
@@ -595,38 +598,38 @@ export async function handleRawWebSocketHandler(
|
|
|
595
598
|
|
|
596
599
|
// Return WebSocket event handlers
|
|
597
600
|
return {
|
|
598
|
-
onOpen: (
|
|
601
|
+
onOpen: (evt: any, ws: any) => {
|
|
602
|
+
// Extract rivetRequestId provided by engine runner
|
|
603
|
+
const rivetRequestId = evt?.rivetRequestId;
|
|
604
|
+
const isHibernatable =
|
|
605
|
+
actor[PERSIST_SYMBOL].hibernatableWebSocket.findIndex((ws) =>
|
|
606
|
+
arrayBuffersEqual(ws.requestId, rivetRequestId),
|
|
607
|
+
) !== -1;
|
|
608
|
+
|
|
599
609
|
// Wrap the Hono WebSocket in our adapter
|
|
600
|
-
const adapter = new HonoWebSocketAdapter(
|
|
610
|
+
const adapter = new HonoWebSocketAdapter(
|
|
611
|
+
ws,
|
|
612
|
+
rivetRequestId,
|
|
613
|
+
isHibernatable,
|
|
614
|
+
);
|
|
601
615
|
|
|
602
616
|
// Store adapter reference on the WebSocket for event handlers
|
|
603
617
|
(ws as any).__adapter = adapter;
|
|
604
618
|
|
|
605
|
-
|
|
606
|
-
// Use URL API for cleaner parsing
|
|
607
|
-
const url = new URL(path, "http://actor");
|
|
608
|
-
const pathname =
|
|
609
|
-
url.pathname.replace(/^\/raw\/websocket\/?/, "") || "/";
|
|
610
|
-
const normalizedPath =
|
|
611
|
-
(pathname.startsWith("/") ? pathname : "/" + pathname) +
|
|
612
|
-
url.search;
|
|
613
|
-
|
|
619
|
+
const newPath = truncateRawWebSocketPathPrefix(path);
|
|
614
620
|
let newRequest: Request;
|
|
615
621
|
if (req) {
|
|
616
|
-
newRequest = new Request(`http://actor${
|
|
622
|
+
newRequest = new Request(`http://actor${newPath}`, req);
|
|
617
623
|
} else {
|
|
618
|
-
newRequest = new Request(`http://actor${
|
|
624
|
+
newRequest = new Request(`http://actor${newPath}`, {
|
|
619
625
|
method: "GET",
|
|
620
626
|
});
|
|
621
627
|
}
|
|
622
628
|
|
|
623
629
|
actor.rLog.debug({
|
|
624
630
|
msg: "rewriting websocket url",
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
pathname: url.pathname,
|
|
628
|
-
search: url.search,
|
|
629
|
-
normalizedPath,
|
|
631
|
+
fromPath: path,
|
|
632
|
+
toUrl: newRequest.url,
|
|
630
633
|
});
|
|
631
634
|
|
|
632
635
|
// Call the actor's onWebSocket handler with the adapted WebSocket
|
|
@@ -711,3 +714,22 @@ export function getRequestConnParams(req: HonoRequest): unknown {
|
|
|
711
714
|
);
|
|
712
715
|
}
|
|
713
716
|
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Truncase the PATH_RAW_WEBSOCKET_PREFIX path prefix in order to pass a clean
|
|
720
|
+
* path to the onWebSocket handler.
|
|
721
|
+
*
|
|
722
|
+
* Example:
|
|
723
|
+
* - `/raw/websocket/foo` -> `/foo`
|
|
724
|
+
* - `/raw/websocket` -> `/`
|
|
725
|
+
*/
|
|
726
|
+
export function truncateRawWebSocketPathPrefix(path: string): string {
|
|
727
|
+
// Extract the path after prefix and preserve query parameters
|
|
728
|
+
// Use URL API for cleaner parsing
|
|
729
|
+
const url = new URL(path, "http://actor");
|
|
730
|
+
const pathname = url.pathname.replace(/^\/raw\/websocket\/?/, "") || "/";
|
|
731
|
+
const normalizedPath =
|
|
732
|
+
(pathname.startsWith("/") ? pathname : "/" + pathname) + url.search;
|
|
733
|
+
|
|
734
|
+
return normalizedPath;
|
|
735
|
+
}
|
package/src/actor/router.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Hono, type Context as HonoContext } from "hono";
|
|
2
|
-
import { cors } from "hono/cors";
|
|
3
2
|
import invariant from "invariant";
|
|
4
3
|
import { EncodingSchema } from "@/actor/protocol/serde";
|
|
5
4
|
import {
|
|
@@ -42,6 +41,7 @@ import {
|
|
|
42
41
|
} from "@/inspector/actor";
|
|
43
42
|
import { isInspectorEnabled, secureInspector } from "@/inspector/utils";
|
|
44
43
|
import type { RunnerConfig } from "@/registry/run-config";
|
|
44
|
+
import { generateConnRequestId } from "./conn";
|
|
45
45
|
import { ConnDriverKind } from "./conn-drivers";
|
|
46
46
|
import type { ActorDriver } from "./driver";
|
|
47
47
|
import { InternalError } from "./errors";
|
|
@@ -77,6 +77,17 @@ export function createActorRouter(
|
|
|
77
77
|
|
|
78
78
|
router.use("*", loggerMiddleware(loggerWithoutContext()));
|
|
79
79
|
|
|
80
|
+
// Track all HTTP requests to prevent actor from sleeping during active requests
|
|
81
|
+
router.use("*", async (c, next) => {
|
|
82
|
+
const actor = await actorDriver.loadActor(c.env.actorId);
|
|
83
|
+
actor.__beginHonoHttpRequest();
|
|
84
|
+
try {
|
|
85
|
+
await next();
|
|
86
|
+
} finally {
|
|
87
|
+
actor.__endHonoHttpRequest();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
80
91
|
router.get("/", (c) => {
|
|
81
92
|
return c.text(
|
|
82
93
|
"This is an RivetKit actor.\n\nLearn more at https://rivetkit.org",
|
|
@@ -175,6 +186,7 @@ export function createActorRouter(
|
|
|
175
186
|
c.env.actorId,
|
|
176
187
|
encoding,
|
|
177
188
|
connParams,
|
|
189
|
+
generateConnRequestId(),
|
|
178
190
|
connIdRaw,
|
|
179
191
|
connTokenRaw,
|
|
180
192
|
);
|
|
@@ -307,22 +319,18 @@ export function createActorRouter(
|
|
|
307
319
|
new Hono<
|
|
308
320
|
ActorInspectorRouterEnv & { Bindings: ActorRouterBindings }
|
|
309
321
|
>()
|
|
310
|
-
.use(
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
c.set("inspector", inspector);
|
|
323
|
-
return next();
|
|
324
|
-
},
|
|
325
|
-
)
|
|
322
|
+
.use(secureInspector(runConfig), async (c, next) => {
|
|
323
|
+
const inspector = (
|
|
324
|
+
await actorDriver.loadActor(c.env.actorId)
|
|
325
|
+
).inspector;
|
|
326
|
+
invariant(
|
|
327
|
+
inspector,
|
|
328
|
+
"inspector not supported on this platform",
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
c.set("inspector", inspector);
|
|
332
|
+
return next();
|
|
333
|
+
})
|
|
326
334
|
.route("/", createActorInspectorRouter()),
|
|
327
335
|
);
|
|
328
336
|
}
|
package/src/client/actor-conn.ts
CHANGED
|
@@ -563,17 +563,21 @@ enc
|
|
|
563
563
|
// TODO: Handle queue
|
|
564
564
|
// TODO: Reconnect with backoff
|
|
565
565
|
|
|
566
|
-
// Reject open promise
|
|
567
|
-
if (this.#onOpenPromise) {
|
|
568
|
-
this.#onOpenPromise.reject(new Error("Closed"));
|
|
569
|
-
}
|
|
570
|
-
|
|
571
566
|
// We can't use `event instanceof CloseEvent` because it's not defined in NodeJS
|
|
572
567
|
//
|
|
573
568
|
// These properties will be undefined
|
|
574
569
|
const closeEvent = event as CloseEvent;
|
|
575
570
|
const wasClean = closeEvent.wasClean;
|
|
576
571
|
|
|
572
|
+
// Reject open promise
|
|
573
|
+
if (this.#onOpenPromise) {
|
|
574
|
+
this.#onOpenPromise.reject(
|
|
575
|
+
new Error(
|
|
576
|
+
`websocket closed with code ${closeEvent.code}: ${closeEvent.reason}`,
|
|
577
|
+
),
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
|
|
577
581
|
logger().info({
|
|
578
582
|
msg: "socket closed",
|
|
579
583
|
code: closeEvent.code,
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Simple CORS middleware that matches the gateway behavior.
|
|
5
|
+
*
|
|
6
|
+
* - Echoes back the Origin header from the request
|
|
7
|
+
* - Echoes back the Access-Control-Request-Headers from preflight
|
|
8
|
+
* - Supports credentials
|
|
9
|
+
* - Allows common HTTP methods
|
|
10
|
+
* - Caches preflight for 24 hours
|
|
11
|
+
* - Adds Vary header to prevent cache poisoning
|
|
12
|
+
*/
|
|
13
|
+
export const cors = (): MiddlewareHandler => {
|
|
14
|
+
return async (c, next) => {
|
|
15
|
+
// Extract origin from request
|
|
16
|
+
const origin = c.req.header("origin") || "*";
|
|
17
|
+
|
|
18
|
+
// Handle preflight OPTIONS request
|
|
19
|
+
if (c.req.method === "OPTIONS") {
|
|
20
|
+
const requestHeaders =
|
|
21
|
+
c.req.header("access-control-request-headers") || "*";
|
|
22
|
+
|
|
23
|
+
c.header("access-control-allow-origin", origin);
|
|
24
|
+
c.header("access-control-allow-credentials", "true");
|
|
25
|
+
c.header(
|
|
26
|
+
"access-control-allow-methods",
|
|
27
|
+
"GET, POST, PUT, DELETE, OPTIONS, PATCH",
|
|
28
|
+
);
|
|
29
|
+
c.header("access-control-allow-headers", requestHeaders);
|
|
30
|
+
c.header("access-control-expose-headers", "*");
|
|
31
|
+
c.header("access-control-max-age", "86400");
|
|
32
|
+
|
|
33
|
+
// Add Vary header to prevent cache poisoning when echoing origin
|
|
34
|
+
if (origin !== "*") {
|
|
35
|
+
c.header("vary", "Origin");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Remove content headers from preflight response
|
|
39
|
+
c.res.headers.delete("content-length");
|
|
40
|
+
c.res.headers.delete("content-type");
|
|
41
|
+
|
|
42
|
+
return c.body(null, 204);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await next();
|
|
46
|
+
|
|
47
|
+
// Add CORS headers to actual request
|
|
48
|
+
c.header("access-control-allow-origin", origin);
|
|
49
|
+
c.header("access-control-allow-credentials", "true");
|
|
50
|
+
c.header("access-control-expose-headers", "*");
|
|
51
|
+
|
|
52
|
+
// Add Vary header to prevent cache poisoning when echoing origin
|
|
53
|
+
if (origin !== "*") {
|
|
54
|
+
c.header("vary", "Origin");
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
package/src/common/log.ts
CHANGED
|
@@ -146,7 +146,7 @@ export async function configureDefaultLogger(
|
|
|
146
146
|
},
|
|
147
147
|
},
|
|
148
148
|
hooks: {
|
|
149
|
-
logMethod(inputArgs,
|
|
149
|
+
logMethod(inputArgs, method, level) {
|
|
150
150
|
// TODO: This is a hack to not implement our own transport target. We can get better perf if we have our own transport target.
|
|
151
151
|
|
|
152
152
|
const levelMap: Record<number, string> = {
|
|
@@ -162,20 +162,41 @@ export async function configureDefaultLogger(
|
|
|
162
162
|
getEnvUniversal("LOG_TIMESTAMP") === "1"
|
|
163
163
|
? Date.now()
|
|
164
164
|
: undefined;
|
|
165
|
+
|
|
166
|
+
// Get bindings from the logger instance (child logger fields)
|
|
167
|
+
const bindings = (this as any).bindings?.() || {};
|
|
168
|
+
|
|
165
169
|
// TODO: This can be simplified in logfmt.ts
|
|
166
170
|
if (inputArgs.length >= 2) {
|
|
167
171
|
const [objOrMsg, msg] = inputArgs;
|
|
168
172
|
if (typeof objOrMsg === "object" && objOrMsg !== null) {
|
|
169
|
-
customWrite(levelName, {
|
|
173
|
+
customWrite(levelName, {
|
|
174
|
+
...bindings,
|
|
175
|
+
...objOrMsg,
|
|
176
|
+
msg,
|
|
177
|
+
time,
|
|
178
|
+
});
|
|
170
179
|
} else {
|
|
171
|
-
customWrite(levelName, {
|
|
180
|
+
customWrite(levelName, {
|
|
181
|
+
...bindings,
|
|
182
|
+
msg: String(objOrMsg),
|
|
183
|
+
time,
|
|
184
|
+
});
|
|
172
185
|
}
|
|
173
186
|
} else if (inputArgs.length === 1) {
|
|
174
187
|
const [objOrMsg] = inputArgs;
|
|
175
188
|
if (typeof objOrMsg === "object" && objOrMsg !== null) {
|
|
176
|
-
customWrite(levelName, {
|
|
189
|
+
customWrite(levelName, {
|
|
190
|
+
...bindings,
|
|
191
|
+
...objOrMsg,
|
|
192
|
+
time,
|
|
193
|
+
});
|
|
177
194
|
} else {
|
|
178
|
-
customWrite(levelName, {
|
|
195
|
+
customWrite(levelName, {
|
|
196
|
+
...bindings,
|
|
197
|
+
msg: String(objOrMsg),
|
|
198
|
+
time,
|
|
199
|
+
});
|
|
179
200
|
}
|
|
180
201
|
}
|
|
181
202
|
},
|
package/src/common/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Next } from "hono";
|
|
2
2
|
import type { ContentfulStatusCode } from "hono/utils/http-status";
|
|
3
3
|
import * as errors from "@/actor/errors";
|
|
4
|
-
import { getEnvUniversal } from "@/utils";
|
|
4
|
+
import { EXTRA_ERROR_LOG, getEnvUniversal, VERSION } from "@/utils";
|
|
5
5
|
import type { Logger } from "./log";
|
|
6
6
|
|
|
7
7
|
export function assertUnreachable(x: never): never {
|
|
@@ -228,8 +228,7 @@ export function deconstructError(
|
|
|
228
228
|
group,
|
|
229
229
|
code,
|
|
230
230
|
message,
|
|
231
|
-
|
|
232
|
-
support: "https://rivet.dev/discord",
|
|
231
|
+
...EXTRA_ERROR_LOG,
|
|
233
232
|
...extraLog,
|
|
234
233
|
});
|
|
235
234
|
} else if (exposeInternalError) {
|
|
@@ -246,8 +245,7 @@ export function deconstructError(
|
|
|
246
245
|
group,
|
|
247
246
|
code,
|
|
248
247
|
message,
|
|
249
|
-
|
|
250
|
-
support: "https://rivet.dev/discord",
|
|
248
|
+
...EXTRA_ERROR_LOG,
|
|
251
249
|
...extraLog,
|
|
252
250
|
});
|
|
253
251
|
} else {
|
|
@@ -262,8 +260,7 @@ export function deconstructError(
|
|
|
262
260
|
group,
|
|
263
261
|
code,
|
|
264
262
|
message,
|
|
265
|
-
|
|
266
|
-
support: "https://rivet.dev/discord",
|
|
263
|
+
...EXTRA_ERROR_LOG,
|
|
267
264
|
...extraLog,
|
|
268
265
|
});
|
|
269
266
|
}
|
|
@@ -281,8 +278,7 @@ export function deconstructError(
|
|
|
281
278
|
msg: "internal error",
|
|
282
279
|
error: getErrorMessage(error),
|
|
283
280
|
stack: (error as Error)?.stack,
|
|
284
|
-
|
|
285
|
-
support: "https://rivet.dev/discord",
|
|
281
|
+
...EXTRA_ERROR_LOG,
|
|
286
282
|
...extraLog,
|
|
287
283
|
});
|
|
288
284
|
}
|
|
@@ -3,10 +3,20 @@ export interface RivetEvent {
|
|
|
3
3
|
type: string;
|
|
4
4
|
target?: any;
|
|
5
5
|
currentTarget?: any;
|
|
6
|
+
/**
|
|
7
|
+
* @experimental
|
|
8
|
+
* Request ID for hibernatable websockets (provided by engine runner)
|
|
9
|
+
**/
|
|
10
|
+
rivetRequestId?: ArrayBuffer;
|
|
6
11
|
}
|
|
7
12
|
|
|
8
13
|
export interface RivetMessageEvent extends RivetEvent {
|
|
9
14
|
data: any;
|
|
15
|
+
/**
|
|
16
|
+
* @experimental
|
|
17
|
+
* Message index for hibernatable websockets (provided by engine runner)
|
|
18
|
+
**/
|
|
19
|
+
rivetMessageIndex?: number;
|
|
10
20
|
}
|
|
11
21
|
|
|
12
22
|
export interface RivetCloseEvent extends RivetEvent {
|