rivetkit 2.0.6 → 2.0.7-rc.1
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/v1.ts +0 -6
- package/dist/tsup/actor-router-consts-B3Lu87yJ.d.cts +28 -0
- package/dist/tsup/actor-router-consts-B3Lu87yJ.d.ts +28 -0
- package/dist/tsup/{chunk-MRRT2CZD.cjs → chunk-3MBP4WNC.cjs} +7 -7
- package/dist/tsup/{chunk-MRRT2CZD.cjs.map → chunk-3MBP4WNC.cjs.map} +1 -1
- package/dist/tsup/{chunk-TWGATZ3X.cjs → chunk-3Y45CIF4.cjs} +922 -872
- package/dist/tsup/chunk-3Y45CIF4.cjs.map +1 -0
- package/dist/tsup/chunk-4GP7BZSR.js +102 -0
- package/dist/tsup/chunk-4GP7BZSR.js.map +1 -0
- package/dist/tsup/{chunk-UFWAK3X2.cjs → chunk-5ZOHIKWG.cjs} +660 -385
- package/dist/tsup/chunk-5ZOHIKWG.cjs.map +1 -0
- package/dist/tsup/{chunk-5JBFVV4C.cjs → chunk-6EUWRXLT.cjs} +21 -7
- package/dist/tsup/chunk-6EUWRXLT.cjs.map +1 -0
- package/dist/tsup/{chunk-UTI5NCES.cjs → chunk-6OVKCDSH.cjs} +6 -6
- package/dist/tsup/{chunk-UTI5NCES.cjs.map → chunk-6OVKCDSH.cjs.map} +1 -1
- package/dist/tsup/{chunk-VPV4MWXR.js → chunk-7N56ZUC7.js} +3 -3
- package/dist/tsup/{chunk-DIAYNQTE.cjs → chunk-B3TLRM4Q.cjs} +12 -12
- package/dist/tsup/{chunk-DIAYNQTE.cjs.map → chunk-B3TLRM4Q.cjs.map} +1 -1
- package/dist/tsup/{chunk-4CKHQRXG.js → chunk-BW5DPM6Z.js} +515 -240
- package/dist/tsup/chunk-BW5DPM6Z.js.map +1 -0
- package/dist/tsup/{chunk-NTCUGYSD.cjs → chunk-DFS77KAA.cjs} +34 -31
- package/dist/tsup/chunk-DFS77KAA.cjs.map +1 -0
- package/dist/tsup/{chunk-VCEHU56K.js → chunk-E4UVJKSV.js} +2 -2
- package/dist/tsup/chunk-G4ABMAQY.cjs +102 -0
- package/dist/tsup/chunk-G4ABMAQY.cjs.map +1 -0
- package/dist/tsup/{chunk-ZYLTS2EM.js → chunk-GZVBFXBI.js} +2 -2
- package/dist/tsup/{chunk-W6LN7AF5.js → chunk-HPT3I7UU.js} +866 -816
- package/dist/tsup/chunk-HPT3I7UU.js.map +1 -0
- package/dist/tsup/{chunk-7OUKNSTU.js → chunk-JD54PXWP.js} +17 -14
- package/dist/tsup/chunk-JD54PXWP.js.map +1 -0
- package/dist/tsup/{chunk-KG3C7MKR.cjs → chunk-K4ENQCC4.cjs} +3 -3
- package/dist/tsup/{chunk-KG3C7MKR.cjs.map → chunk-K4ENQCC4.cjs.map} +1 -1
- package/dist/tsup/{chunk-WC2PSJWN.js → chunk-PUSQNDJG.js} +2 -2
- package/dist/tsup/{chunk-RGQR2J7S.js → chunk-RVP5RUSC.js} +20 -6
- package/dist/tsup/chunk-RVP5RUSC.js.map +1 -0
- package/dist/tsup/{chunk-TCUI5JFE.cjs → chunk-SAZCNSVY.cjs} +45 -18
- package/dist/tsup/chunk-SAZCNSVY.cjs.map +1 -0
- package/dist/tsup/{chunk-G75SVQON.js → chunk-SBKRVQS2.js} +9 -5
- package/dist/tsup/chunk-SBKRVQS2.js.map +1 -0
- package/dist/tsup/{chunk-6P6RA47N.cjs → chunk-TZGUSEIJ.cjs} +14 -10
- package/dist/tsup/chunk-TZGUSEIJ.cjs.map +1 -0
- package/dist/tsup/{chunk-2K3JMDAN.js → chunk-YQ4XQYPM.js} +40 -13
- package/dist/tsup/chunk-YQ4XQYPM.js.map +1 -0
- package/dist/tsup/client/mod.cjs +9 -9
- package/dist/tsup/client/mod.d.cts +7 -8
- package/dist/tsup/client/mod.d.ts +7 -8
- 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/{connection-BLemxi4f.d.ts → conn-DCSQgIlw.d.ts} +1605 -1353
- package/dist/tsup/{connection-CpDIydXf.d.cts → conn-DdzHTm2E.d.cts} +1605 -1353
- package/dist/tsup/driver-helpers/mod.cjs +31 -5
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +7 -8
- package/dist/tsup/driver-helpers/mod.d.ts +7 -8
- package/dist/tsup/driver-helpers/mod.js +33 -7
- package/dist/tsup/driver-test-suite/mod.cjs +317 -222
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +7 -7
- package/dist/tsup/driver-test-suite/mod.d.ts +7 -7
- package/dist/tsup/driver-test-suite/mod.js +582 -487
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +16 -6
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.d.cts +34 -7
- package/dist/tsup/inspector/mod.d.ts +34 -7
- package/dist/tsup/inspector/mod.js +17 -7
- package/dist/tsup/mod.cjs +10 -20
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +9 -7
- package/dist/tsup/mod.d.ts +9 -7
- package/dist/tsup/mod.js +9 -19
- package/dist/tsup/test/mod.cjs +11 -11
- package/dist/tsup/test/mod.d.cts +6 -7
- package/dist/tsup/test/mod.d.ts +6 -7
- package/dist/tsup/test/mod.js +10 -10
- package/dist/tsup/utils.cjs +4 -2
- package/dist/tsup/utils.cjs.map +1 -1
- package/dist/tsup/utils.d.cts +11 -1
- package/dist/tsup/utils.d.ts +11 -1
- package/dist/tsup/utils.js +3 -1
- package/package.json +8 -4
- package/src/actor/action.ts +1 -1
- package/src/actor/config.ts +1 -1
- package/src/actor/conn-drivers.ts +205 -0
- package/src/actor/conn-socket.ts +6 -0
- package/src/actor/{connection.ts → conn.ts} +78 -84
- package/src/actor/context.ts +1 -1
- package/src/actor/driver.ts +4 -43
- package/src/actor/instance.ts +162 -86
- package/src/actor/mod.ts +1 -11
- package/src/actor/persisted.ts +2 -5
- package/src/actor/protocol/old.ts +1 -1
- package/src/actor/router-endpoints.ts +142 -106
- package/src/actor/router.ts +81 -45
- package/src/actor/utils.ts +5 -1
- package/src/client/actor-conn.ts +154 -23
- package/src/client/client.ts +1 -1
- package/src/client/config.ts +7 -0
- package/src/common/actor-router-consts.ts +29 -8
- package/src/common/router.ts +2 -1
- package/src/common/versioned-data.ts +5 -5
- package/src/driver-helpers/mod.ts +14 -1
- package/src/driver-test-suite/mod.ts +11 -2
- package/src/driver-test-suite/test-inline-client-driver.ts +36 -18
- package/src/driver-test-suite/tests/actor-conn-state.ts +66 -22
- package/src/driver-test-suite/tests/actor-conn.ts +65 -126
- package/src/driver-test-suite/tests/actor-reconnect.ts +160 -0
- package/src/driver-test-suite/tests/actor-sleep.ts +0 -1
- package/src/driver-test-suite/tests/raw-websocket.ts +0 -35
- package/src/driver-test-suite/utils.ts +3 -3
- package/src/drivers/default.ts +8 -7
- package/src/drivers/engine/actor-driver.ts +53 -31
- package/src/drivers/engine/config.ts +4 -0
- package/src/drivers/file-system/actor.ts +0 -6
- package/src/drivers/file-system/global-state.ts +3 -14
- package/src/drivers/file-system/manager.ts +12 -8
- package/src/inspector/actor.ts +4 -3
- package/src/inspector/config.ts +10 -1
- package/src/inspector/mod.ts +1 -0
- package/src/inspector/utils.ts +23 -4
- package/src/manager/driver.ts +11 -1
- package/src/manager/gateway.ts +407 -0
- package/src/manager/router.ts +269 -468
- package/src/manager-api/actors.ts +61 -0
- package/src/manager-api/common.ts +4 -0
- package/src/mod.ts +1 -1
- package/src/registry/mod.ts +119 -10
- package/src/remote-manager-driver/actor-http-client.ts +30 -19
- package/src/remote-manager-driver/actor-websocket-client.ts +43 -16
- package/src/remote-manager-driver/api-endpoints.ts +19 -21
- package/src/remote-manager-driver/api-utils.ts +10 -1
- package/src/remote-manager-driver/mod.ts +51 -48
- package/src/remote-manager-driver/ws-proxy.ts +2 -9
- package/src/test/mod.ts +6 -2
- package/src/utils.ts +21 -2
- package/dist/tsup/actor-router-consts-BK6arfy8.d.cts +0 -17
- package/dist/tsup/actor-router-consts-BK6arfy8.d.ts +0 -17
- package/dist/tsup/chunk-2K3JMDAN.js.map +0 -1
- package/dist/tsup/chunk-42I3OZ3Q.js +0 -15
- package/dist/tsup/chunk-42I3OZ3Q.js.map +0 -1
- package/dist/tsup/chunk-4CKHQRXG.js.map +0 -1
- package/dist/tsup/chunk-5JBFVV4C.cjs.map +0 -1
- package/dist/tsup/chunk-6P6RA47N.cjs.map +0 -1
- package/dist/tsup/chunk-7OUKNSTU.js.map +0 -1
- package/dist/tsup/chunk-G75SVQON.js.map +0 -1
- package/dist/tsup/chunk-KUPQZYUQ.cjs +0 -15
- package/dist/tsup/chunk-KUPQZYUQ.cjs.map +0 -1
- package/dist/tsup/chunk-NTCUGYSD.cjs.map +0 -1
- package/dist/tsup/chunk-RGQR2J7S.js.map +0 -1
- package/dist/tsup/chunk-TCUI5JFE.cjs.map +0 -1
- package/dist/tsup/chunk-TWGATZ3X.cjs.map +0 -1
- package/dist/tsup/chunk-UFWAK3X2.cjs.map +0 -1
- package/dist/tsup/chunk-W6LN7AF5.js.map +0 -1
- package/dist/tsup/common-CXCe7s6i.d.cts +0 -218
- package/dist/tsup/common-CXCe7s6i.d.ts +0 -218
- package/src/actor/generic-conn-driver.ts +0 -246
- package/src/common/fake-event-source.ts +0 -267
- package/src/manager-api/routes/actors-create.ts +0 -16
- package/src/manager-api/routes/actors-delete.ts +0 -4
- package/src/manager-api/routes/actors-get-by-id.ts +0 -7
- package/src/manager-api/routes/actors-get-or-create-by-id.ts +0 -29
- package/src/manager-api/routes/actors-get.ts +0 -7
- package/src/manager-api/routes/common.ts +0 -18
- /package/dist/tsup/{chunk-VPV4MWXR.js.map → chunk-7N56ZUC7.js.map} +0 -0
- /package/dist/tsup/{chunk-VCEHU56K.js.map → chunk-E4UVJKSV.js.map} +0 -0
- /package/dist/tsup/{chunk-ZYLTS2EM.js.map → chunk-GZVBFXBI.js.map} +0 -0
- /package/dist/tsup/{chunk-WC2PSJWN.js.map → chunk-PUSQNDJG.js.map} +0 -0
package/src/manager/router.ts
CHANGED
|
@@ -1,64 +1,70 @@
|
|
|
1
1
|
import { createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
|
2
2
|
import * as cbor from "cbor-x";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Hono,
|
|
5
|
+
Context as HonoContext,
|
|
6
|
+
type MiddlewareHandler,
|
|
7
|
+
Next,
|
|
8
|
+
} from "hono";
|
|
4
9
|
import { cors as corsMiddleware } from "hono/cors";
|
|
5
10
|
import { createMiddleware } from "hono/factory";
|
|
6
|
-
import
|
|
11
|
+
import { streamSSE } from "hono/streaming";
|
|
7
12
|
import invariant from "invariant";
|
|
8
13
|
import { z } from "zod";
|
|
14
|
+
import { ActorNotFound, Unsupported } from "@/actor/errors";
|
|
15
|
+
import { serializeActorKey } from "@/actor/keys";
|
|
16
|
+
import type { Encoding, Transport } from "@/client/mod";
|
|
9
17
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
WS_PROTOCOL_ACTOR,
|
|
19
|
+
WS_PROTOCOL_CONN_ID,
|
|
20
|
+
WS_PROTOCOL_CONN_PARAMS,
|
|
21
|
+
WS_PROTOCOL_CONN_TOKEN,
|
|
22
|
+
WS_PROTOCOL_ENCODING,
|
|
23
|
+
WS_PROTOCOL_PATH,
|
|
24
|
+
WS_PROTOCOL_TRANSPORT,
|
|
25
|
+
} from "@/common/actor-router-consts";
|
|
17
26
|
import {
|
|
18
27
|
handleRouteError,
|
|
19
28
|
handleRouteNotFound,
|
|
20
29
|
loggerMiddleware,
|
|
21
30
|
} from "@/common/router";
|
|
22
|
-
import { deconstructError, noopNext } from "@/common/utils";
|
|
23
|
-
import { HEADER_ACTOR_ID } from "@/driver-helpers/mod";
|
|
31
|
+
import { deconstructError, noopNext, stringifyError } from "@/common/utils";
|
|
32
|
+
import { type ActorDriver, HEADER_ACTOR_ID } from "@/driver-helpers/mod";
|
|
24
33
|
import type {
|
|
25
34
|
TestInlineDriverCallRequest,
|
|
26
35
|
TestInlineDriverCallResponse,
|
|
27
36
|
} from "@/driver-test-suite/test-inline-client-driver";
|
|
28
37
|
import { createManagerInspectorRouter } from "@/inspector/manager";
|
|
29
|
-
import { secureInspector } from "@/inspector/utils";
|
|
38
|
+
import { isInspectorEnabled, secureInspector } from "@/inspector/utils";
|
|
30
39
|
import {
|
|
31
40
|
type ActorsCreateRequest,
|
|
32
41
|
ActorsCreateRequestSchema,
|
|
42
|
+
type ActorsCreateResponse,
|
|
33
43
|
ActorsCreateResponseSchema,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
} from "@/manager-api/
|
|
43
|
-
import { RivetIdSchema } from "@/manager-api/routes/common";
|
|
44
|
-
import type { UniversalWebSocket, UpgradeWebSocketArgs } from "@/mod";
|
|
44
|
+
type ActorsGetOrCreateRequest,
|
|
45
|
+
ActorsGetOrCreateRequestSchema,
|
|
46
|
+
type ActorsGetOrCreateResponse,
|
|
47
|
+
ActorsGetOrCreateResponseSchema,
|
|
48
|
+
type ActorsListResponse,
|
|
49
|
+
ActorsListResponseSchema,
|
|
50
|
+
type Actor as ApiActor,
|
|
51
|
+
} from "@/manager-api/actors";
|
|
52
|
+
import { RivetIdSchema } from "@/manager-api/common";
|
|
45
53
|
import type { RegistryConfig } from "@/registry/config";
|
|
46
54
|
import type { RunConfig } from "@/registry/run-config";
|
|
47
|
-
import {
|
|
48
|
-
import
|
|
55
|
+
import type { ActorOutput, ManagerDriver } from "./driver";
|
|
56
|
+
import { actorGateway, createTestWebSocketProxy } from "./gateway";
|
|
49
57
|
import { logger } from "./log";
|
|
50
58
|
|
|
51
|
-
function buildOpenApiResponses<T>(schema: T
|
|
59
|
+
function buildOpenApiResponses<T>(schema: T) {
|
|
52
60
|
return {
|
|
53
61
|
200: {
|
|
54
62
|
description: "Success",
|
|
55
|
-
content:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
: {},
|
|
63
|
+
content: {
|
|
64
|
+
"application/json": {
|
|
65
|
+
schema,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
62
68
|
},
|
|
63
69
|
400: {
|
|
64
70
|
description: "User error",
|
|
@@ -73,8 +79,8 @@ export function createManagerRouter(
|
|
|
73
79
|
registryConfig: RegistryConfig,
|
|
74
80
|
runConfig: RunConfig,
|
|
75
81
|
managerDriver: ManagerDriver,
|
|
76
|
-
|
|
77
|
-
): { router: Hono; openapi: OpenAPIHono } {
|
|
82
|
+
serverlessActorDriverBuilder: (() => ActorDriver) | undefined,
|
|
83
|
+
): { router: Hono; openapi: OpenAPIHono; cors: MiddlewareHandler } {
|
|
78
84
|
const router = new OpenAPIHono({ strict: false }).basePath(
|
|
79
85
|
runConfig.basePath,
|
|
80
86
|
);
|
|
@@ -85,80 +91,55 @@ export function createManagerRouter(
|
|
|
85
91
|
? corsMiddleware(runConfig.cors)
|
|
86
92
|
: createMiddleware((_c, next) => next());
|
|
87
93
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (target === "actor") {
|
|
94
|
-
if (!actorId) {
|
|
95
|
-
throw new MissingActorHeader();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
logger().debug({
|
|
99
|
-
msg: "proxying request to actor",
|
|
100
|
-
actorId,
|
|
101
|
-
path: c.req.path,
|
|
102
|
-
method: c.req.method,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// Handle WebSocket upgrade
|
|
106
|
-
if (c.req.header("upgrade") === "websocket") {
|
|
107
|
-
const upgradeWebSocket = runConfig.getUpgradeWebSocket?.();
|
|
108
|
-
if (!upgradeWebSocket) {
|
|
109
|
-
throw new WebSocketsNotEnabled();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// For WebSocket, use the driver's proxyWebSocket method
|
|
113
|
-
// Extract any additional headers that might be needed
|
|
114
|
-
const encoding =
|
|
115
|
-
c.req.header("X-RivetKit-Encoding") ||
|
|
116
|
-
c.req.header("x-rivet-encoding") ||
|
|
117
|
-
"json";
|
|
118
|
-
const connParams =
|
|
119
|
-
c.req.header("X-RivetKit-Conn-Params") ||
|
|
120
|
-
c.req.header("x-rivet-conn-params");
|
|
121
|
-
const authData =
|
|
122
|
-
c.req.header("X-RivetKit-Auth-Data") ||
|
|
123
|
-
c.req.header("x-rivet-auth-data");
|
|
124
|
-
|
|
125
|
-
// Include query string if present
|
|
126
|
-
const pathWithQuery = c.req.url.includes("?")
|
|
127
|
-
? c.req.path + c.req.url.substring(c.req.url.indexOf("?"))
|
|
128
|
-
: c.req.path;
|
|
129
|
-
|
|
130
|
-
return await managerDriver.proxyWebSocket(
|
|
131
|
-
c,
|
|
132
|
-
pathWithQuery,
|
|
133
|
-
actorId,
|
|
134
|
-
encoding as any, // Will be validated by driver
|
|
135
|
-
connParams ? JSON.parse(connParams) : undefined,
|
|
136
|
-
authData ? JSON.parse(authData) : undefined,
|
|
137
|
-
);
|
|
138
|
-
}
|
|
94
|
+
if (serverlessActorDriverBuilder) {
|
|
95
|
+
addServerlessRoutes(serverlessActorDriverBuilder, router, cors);
|
|
96
|
+
} else {
|
|
97
|
+
addManagerRoutes(registryConfig, runConfig, managerDriver, router, cors);
|
|
98
|
+
}
|
|
139
99
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
proxyHeaders.delete("x-rivet-target");
|
|
144
|
-
proxyHeaders.delete("x-rivet-actor");
|
|
100
|
+
// Error handling
|
|
101
|
+
router.notFound(handleRouteNotFound);
|
|
102
|
+
router.onError(handleRouteError);
|
|
145
103
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const proxyUrl = new URL(`http://actor${url.pathname}${url.search}`);
|
|
104
|
+
return { router: router as Hono, openapi: router, cors };
|
|
105
|
+
}
|
|
149
106
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
107
|
+
function addServerlessRoutes(
|
|
108
|
+
serverlessActorDriverBuilder: () => ActorDriver,
|
|
109
|
+
router: OpenAPIHono,
|
|
110
|
+
cors: MiddlewareHandler,
|
|
111
|
+
) {
|
|
112
|
+
// GET /
|
|
113
|
+
router.get("/", cors, (c) => {
|
|
114
|
+
return c.text(
|
|
115
|
+
"This is a RivetKit server.\n\nLearn more at https://rivetkit.org",
|
|
116
|
+
);
|
|
117
|
+
});
|
|
156
118
|
|
|
157
|
-
|
|
158
|
-
|
|
119
|
+
// Serverless start endpoint
|
|
120
|
+
router.get("/start", cors, async (c) => {
|
|
121
|
+
const actorDriver = serverlessActorDriverBuilder();
|
|
122
|
+
invariant(
|
|
123
|
+
actorDriver.serverlessHandleStart,
|
|
124
|
+
"missing serverlessHandleStart on ActorDriver",
|
|
125
|
+
);
|
|
126
|
+
return await actorDriver.serverlessHandleStart(c);
|
|
127
|
+
});
|
|
159
128
|
|
|
160
|
-
|
|
129
|
+
router.get("/health", cors, (c) => {
|
|
130
|
+
return c.text("ok");
|
|
161
131
|
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function addManagerRoutes(
|
|
135
|
+
registryConfig: RegistryConfig,
|
|
136
|
+
runConfig: RunConfig,
|
|
137
|
+
managerDriver: ManagerDriver,
|
|
138
|
+
router: OpenAPIHono,
|
|
139
|
+
cors: MiddlewareHandler,
|
|
140
|
+
) {
|
|
141
|
+
// Actor gateway
|
|
142
|
+
router.use("*", cors, actorGateway.bind(undefined, runConfig, managerDriver));
|
|
162
143
|
|
|
163
144
|
// GET /
|
|
164
145
|
router.get("/", cors, (c) => {
|
|
@@ -167,72 +148,99 @@ export function createManagerRouter(
|
|
|
167
148
|
);
|
|
168
149
|
});
|
|
169
150
|
|
|
170
|
-
// GET /actors
|
|
151
|
+
// GET /actors
|
|
171
152
|
{
|
|
172
153
|
const route = createRoute({
|
|
173
154
|
middleware: [cors],
|
|
174
155
|
method: "get",
|
|
175
|
-
path: "/actors
|
|
156
|
+
path: "/actors",
|
|
176
157
|
request: {
|
|
177
158
|
query: z.object({
|
|
178
159
|
name: z.string(),
|
|
179
|
-
|
|
160
|
+
actor_ids: z.string().optional(),
|
|
161
|
+
key: z.string().optional(),
|
|
180
162
|
}),
|
|
181
163
|
},
|
|
182
|
-
responses: buildOpenApiResponses(
|
|
183
|
-
ActorsGetByIdResponseSchema,
|
|
184
|
-
validateBody,
|
|
185
|
-
),
|
|
164
|
+
responses: buildOpenApiResponses(ActorsListResponseSchema),
|
|
186
165
|
});
|
|
187
166
|
|
|
188
167
|
router.openapi(route, async (c) => {
|
|
189
|
-
const { name, key } = c.req.valid("query");
|
|
168
|
+
const { name, actor_ids, key } = c.req.valid("query");
|
|
169
|
+
|
|
170
|
+
const actorIdsParsed = actor_ids
|
|
171
|
+
? actor_ids
|
|
172
|
+
.split(",")
|
|
173
|
+
.map((id) => id.trim())
|
|
174
|
+
.filter((id) => id.length > 0)
|
|
175
|
+
: undefined;
|
|
176
|
+
|
|
177
|
+
const actors: ActorOutput[] = [];
|
|
178
|
+
|
|
179
|
+
if (actorIdsParsed) {
|
|
180
|
+
if (actorIdsParsed.length > 32) {
|
|
181
|
+
return c.json(
|
|
182
|
+
{
|
|
183
|
+
error: `Too many actor IDs. Maximum is 32, got ${actorIdsParsed.length}.`,
|
|
184
|
+
},
|
|
185
|
+
400,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
190
188
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
189
|
+
if (actorIdsParsed.length === 0) {
|
|
190
|
+
return c.json<ActorsListResponse>({
|
|
191
|
+
actors: [],
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (const actorId of actorIdsParsed) {
|
|
196
|
+
if (name) {
|
|
197
|
+
const actorOutput = await managerDriver.getForId({
|
|
198
|
+
c,
|
|
199
|
+
name,
|
|
200
|
+
actorId,
|
|
201
|
+
});
|
|
202
|
+
if (actorOutput) {
|
|
203
|
+
actors.push(actorOutput);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
} else if (key) {
|
|
208
|
+
const actorOutput = await managerDriver.getWithKey({
|
|
209
|
+
c,
|
|
210
|
+
name,
|
|
211
|
+
key: [key], // Convert string to ActorKey array
|
|
212
|
+
});
|
|
213
|
+
if (actorOutput) {
|
|
214
|
+
actors.push(actorOutput);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
197
217
|
|
|
198
|
-
return c.json({
|
|
199
|
-
|
|
218
|
+
return c.json<ActorsListResponse>({
|
|
219
|
+
actors: actors.map(createApiActor),
|
|
200
220
|
});
|
|
201
221
|
});
|
|
202
222
|
}
|
|
203
223
|
|
|
204
|
-
// PUT /actors
|
|
224
|
+
// PUT /actors
|
|
205
225
|
{
|
|
206
226
|
const route = createRoute({
|
|
207
|
-
|
|
227
|
+
middleware: [cors],
|
|
208
228
|
method: "put",
|
|
209
|
-
path: "/actors
|
|
229
|
+
path: "/actors",
|
|
210
230
|
request: {
|
|
211
231
|
body: {
|
|
212
|
-
content:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
: {},
|
|
232
|
+
content: {
|
|
233
|
+
"application/json": {
|
|
234
|
+
schema: ActorsGetOrCreateRequestSchema,
|
|
235
|
+
},
|
|
236
|
+
},
|
|
219
237
|
},
|
|
220
238
|
},
|
|
221
|
-
responses: buildOpenApiResponses(
|
|
222
|
-
ActorsGetOrCreateByIdResponseSchema,
|
|
223
|
-
validateBody,
|
|
224
|
-
),
|
|
239
|
+
responses: buildOpenApiResponses(ActorsGetOrCreateResponseSchema),
|
|
225
240
|
});
|
|
226
241
|
|
|
227
242
|
router.openapi(route, async (c) => {
|
|
228
|
-
const body =
|
|
229
|
-
? await c.req.json<ActorsGetOrCreateByIdRequest>()
|
|
230
|
-
: await c.req.json();
|
|
231
|
-
|
|
232
|
-
// Parse and validate the request body if validation is enabled
|
|
233
|
-
if (validateBody) {
|
|
234
|
-
ActorsGetOrCreateByIdRequestSchema.parse(body);
|
|
235
|
-
}
|
|
243
|
+
const body = c.req.valid("json");
|
|
236
244
|
|
|
237
245
|
// Check if actor already exists
|
|
238
246
|
const existingActor = await managerDriver.getWithKey({
|
|
@@ -242,8 +250,8 @@ export function createManagerRouter(
|
|
|
242
250
|
});
|
|
243
251
|
|
|
244
252
|
if (existingActor) {
|
|
245
|
-
return c.json({
|
|
246
|
-
|
|
253
|
+
return c.json<ActorsGetOrCreateResponse>({
|
|
254
|
+
actor: createApiActor(existingActor),
|
|
247
255
|
created: false,
|
|
248
256
|
});
|
|
249
257
|
}
|
|
@@ -259,60 +267,13 @@ export function createManagerRouter(
|
|
|
259
267
|
region: undefined, // Not provided in the request schema
|
|
260
268
|
});
|
|
261
269
|
|
|
262
|
-
return c.json({
|
|
263
|
-
|
|
270
|
+
return c.json<ActorsGetOrCreateResponse>({
|
|
271
|
+
actor: createApiActor(newActor),
|
|
264
272
|
created: true,
|
|
265
273
|
});
|
|
266
274
|
});
|
|
267
275
|
}
|
|
268
276
|
|
|
269
|
-
// GET /actors/{actor_id}
|
|
270
|
-
{
|
|
271
|
-
const route = createRoute({
|
|
272
|
-
middleware: [cors],
|
|
273
|
-
method: "get",
|
|
274
|
-
path: "/actors/{actor_id}",
|
|
275
|
-
request: {
|
|
276
|
-
params: z.object({
|
|
277
|
-
actor_id: RivetIdSchema,
|
|
278
|
-
}),
|
|
279
|
-
},
|
|
280
|
-
responses: buildOpenApiResponses(ActorsGetResponseSchema, validateBody),
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
router.openapi(route, async (c) => {
|
|
284
|
-
const { actor_id } = c.req.valid("param");
|
|
285
|
-
|
|
286
|
-
// Get actor by ID from the driver
|
|
287
|
-
const actorOutput = await managerDriver.getForId({
|
|
288
|
-
c,
|
|
289
|
-
name: "", // TODO: The API doesn't provide the name, this may need to be resolved
|
|
290
|
-
actorId: actor_id,
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
if (!actorOutput) {
|
|
294
|
-
throw new ActorNotFound(actor_id);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Transform ActorOutput to match ActorSchema
|
|
298
|
-
// Note: Some fields are not available from the driver and need defaults
|
|
299
|
-
const actor = {
|
|
300
|
-
actor_id: actorOutput.actorId,
|
|
301
|
-
name: actorOutput.name,
|
|
302
|
-
key: actorOutput.key,
|
|
303
|
-
namespace_id: "default", // Assert default namespace
|
|
304
|
-
runner_name_selector: "rivetkit", // Assert rivetkit runner
|
|
305
|
-
create_ts: Date.now(), // Not available from driver
|
|
306
|
-
connectable_ts: null,
|
|
307
|
-
destroy_ts: null,
|
|
308
|
-
sleep_ts: null,
|
|
309
|
-
start_ts: null,
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
return c.json({ actor });
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
|
|
316
277
|
// POST /actors
|
|
317
278
|
{
|
|
318
279
|
const route = createRoute({
|
|
@@ -321,30 +282,18 @@ export function createManagerRouter(
|
|
|
321
282
|
path: "/actors",
|
|
322
283
|
request: {
|
|
323
284
|
body: {
|
|
324
|
-
content:
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
: {},
|
|
285
|
+
content: {
|
|
286
|
+
"application/json": {
|
|
287
|
+
schema: ActorsCreateRequestSchema,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
331
290
|
},
|
|
332
291
|
},
|
|
333
|
-
responses: buildOpenApiResponses(
|
|
334
|
-
ActorsCreateResponseSchema,
|
|
335
|
-
validateBody,
|
|
336
|
-
),
|
|
292
|
+
responses: buildOpenApiResponses(ActorsCreateResponseSchema),
|
|
337
293
|
});
|
|
338
294
|
|
|
339
295
|
router.openapi(route, async (c) => {
|
|
340
|
-
const body =
|
|
341
|
-
? await c.req.json<ActorsCreateRequest>()
|
|
342
|
-
: await c.req.json();
|
|
343
|
-
|
|
344
|
-
// Parse and validate the request body if validation is enabled
|
|
345
|
-
if (validateBody) {
|
|
346
|
-
ActorsCreateRequestSchema.parse(body);
|
|
347
|
-
}
|
|
296
|
+
const body = c.req.valid("json");
|
|
348
297
|
|
|
349
298
|
// Create actor using the driver
|
|
350
299
|
const actorOutput = await managerDriver.createActor({
|
|
@@ -358,20 +307,9 @@ export function createManagerRouter(
|
|
|
358
307
|
});
|
|
359
308
|
|
|
360
309
|
// Transform ActorOutput to match ActorSchema
|
|
361
|
-
const actor =
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
key: actorOutput.key,
|
|
365
|
-
namespace_id: "default", // Assert default namespace
|
|
366
|
-
runner_name_selector: "rivetkit", // Assert rivetkit runner
|
|
367
|
-
create_ts: Date.now(),
|
|
368
|
-
connectable_ts: null,
|
|
369
|
-
destroy_ts: null,
|
|
370
|
-
sleep_ts: null,
|
|
371
|
-
start_ts: null,
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
return c.json({ actor });
|
|
310
|
+
const actor = createApiActor(actorOutput);
|
|
311
|
+
|
|
312
|
+
return c.json<ActorsCreateResponse>({ actor });
|
|
375
313
|
});
|
|
376
314
|
}
|
|
377
315
|
|
|
@@ -427,7 +365,8 @@ export function createManagerRouter(
|
|
|
427
365
|
response = { err };
|
|
428
366
|
}
|
|
429
367
|
|
|
430
|
-
|
|
368
|
+
// TODO: Remove any
|
|
369
|
+
return c.body(cbor.encode(response) as any);
|
|
431
370
|
});
|
|
432
371
|
|
|
433
372
|
router.get(".test/inline-driver/connect-websocket/*", async (c) => {
|
|
@@ -435,25 +374,52 @@ export function createManagerRouter(
|
|
|
435
374
|
invariant(upgradeWebSocket, "websockets not supported on this platform");
|
|
436
375
|
|
|
437
376
|
return upgradeWebSocket(async (c: any) => {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
377
|
+
// Extract information from sec-websocket-protocol header
|
|
378
|
+
const protocolHeader = c.req.header("sec-websocket-protocol") || "";
|
|
379
|
+
const protocols = protocolHeader.split(/,\s*/);
|
|
380
|
+
|
|
381
|
+
// Parse protocols to extract connection info
|
|
382
|
+
let actorId = "";
|
|
383
|
+
let encoding: Encoding = "bare";
|
|
384
|
+
let transport: Transport = "websocket";
|
|
385
|
+
let path = "";
|
|
386
|
+
let params: unknown;
|
|
387
|
+
let connId: string | undefined;
|
|
388
|
+
let connToken: string | undefined;
|
|
389
|
+
|
|
390
|
+
for (const protocol of protocols) {
|
|
391
|
+
if (protocol.startsWith(WS_PROTOCOL_ACTOR)) {
|
|
392
|
+
actorId = protocol.substring(WS_PROTOCOL_ACTOR.length);
|
|
393
|
+
} else if (protocol.startsWith(WS_PROTOCOL_ENCODING)) {
|
|
394
|
+
encoding = protocol.substring(
|
|
395
|
+
WS_PROTOCOL_ENCODING.length,
|
|
396
|
+
) as Encoding;
|
|
397
|
+
} else if (protocol.startsWith(WS_PROTOCOL_TRANSPORT)) {
|
|
398
|
+
transport = protocol.substring(
|
|
399
|
+
WS_PROTOCOL_TRANSPORT.length,
|
|
400
|
+
) as Transport;
|
|
401
|
+
} else if (protocol.startsWith(WS_PROTOCOL_PATH)) {
|
|
402
|
+
path = decodeURIComponent(
|
|
403
|
+
protocol.substring(WS_PROTOCOL_PATH.length),
|
|
404
|
+
);
|
|
405
|
+
} else if (protocol.startsWith(WS_PROTOCOL_CONN_PARAMS)) {
|
|
406
|
+
const paramsRaw = decodeURIComponent(
|
|
407
|
+
protocol.substring(WS_PROTOCOL_CONN_PARAMS.length),
|
|
408
|
+
);
|
|
409
|
+
params = JSON.parse(paramsRaw);
|
|
410
|
+
} else if (protocol.startsWith(WS_PROTOCOL_CONN_ID)) {
|
|
411
|
+
connId = protocol.substring(WS_PROTOCOL_CONN_ID.length);
|
|
412
|
+
} else if (protocol.startsWith(WS_PROTOCOL_CONN_TOKEN)) {
|
|
413
|
+
connToken = protocol.substring(WS_PROTOCOL_CONN_TOKEN.length);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
451
416
|
|
|
452
417
|
logger().debug({
|
|
453
418
|
msg: "received test inline driver websocket",
|
|
454
419
|
actorId,
|
|
455
420
|
params,
|
|
456
|
-
encodingKind,
|
|
421
|
+
encodingKind: encoding,
|
|
422
|
+
transport,
|
|
457
423
|
path: path,
|
|
458
424
|
});
|
|
459
425
|
|
|
@@ -461,11 +427,13 @@ export function createManagerRouter(
|
|
|
461
427
|
const clientWsPromise = managerDriver.openWebSocket(
|
|
462
428
|
path,
|
|
463
429
|
actorId,
|
|
464
|
-
|
|
430
|
+
encoding,
|
|
465
431
|
params,
|
|
432
|
+
connId,
|
|
433
|
+
connToken,
|
|
466
434
|
);
|
|
467
435
|
|
|
468
|
-
return await createTestWebSocketProxy(clientWsPromise
|
|
436
|
+
return await createTestWebSocketProxy(clientWsPromise);
|
|
469
437
|
})(c, noopNext());
|
|
470
438
|
});
|
|
471
439
|
|
|
@@ -500,6 +468,7 @@ export function createManagerRouter(
|
|
|
500
468
|
method: c.req.method,
|
|
501
469
|
headers: c.req.raw.headers,
|
|
502
470
|
body: c.req.raw.body,
|
|
471
|
+
duplex: "half",
|
|
503
472
|
}),
|
|
504
473
|
);
|
|
505
474
|
|
|
@@ -525,14 +494,60 @@ export function createManagerRouter(
|
|
|
525
494
|
);
|
|
526
495
|
}
|
|
527
496
|
});
|
|
497
|
+
|
|
498
|
+
// Test endpoint to force disconnect a connection non-cleanly
|
|
499
|
+
router.post("/.test/force-disconnect", async (c) => {
|
|
500
|
+
const actorId = c.req.query("actor");
|
|
501
|
+
const connId = c.req.query("conn");
|
|
502
|
+
|
|
503
|
+
if (!actorId || !connId) {
|
|
504
|
+
return c.text("Missing actor or conn query parameters", 400);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
logger().debug({
|
|
508
|
+
msg: "forcing unclean disconnect",
|
|
509
|
+
actorId,
|
|
510
|
+
connId,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
try {
|
|
514
|
+
// Send a special request to the actor to force disconnect the connection
|
|
515
|
+
const response = await managerDriver.sendRequest(
|
|
516
|
+
actorId,
|
|
517
|
+
new Request(`http://actor/.test/force-disconnect?conn=${connId}`, {
|
|
518
|
+
method: "POST",
|
|
519
|
+
}),
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
if (!response.ok) {
|
|
523
|
+
const text = await response.text();
|
|
524
|
+
return c.text(
|
|
525
|
+
`Failed to force disconnect: ${text}`,
|
|
526
|
+
response.status as any,
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return c.json({ success: true });
|
|
531
|
+
} catch (error) {
|
|
532
|
+
logger().error({
|
|
533
|
+
msg: "error forcing disconnect",
|
|
534
|
+
error: stringifyError(error),
|
|
535
|
+
});
|
|
536
|
+
return c.text(`Error: ${error}`, 500);
|
|
537
|
+
}
|
|
538
|
+
});
|
|
528
539
|
}
|
|
529
540
|
|
|
541
|
+
router.get("/health", cors, (c) => {
|
|
542
|
+
return c.text("ok");
|
|
543
|
+
});
|
|
544
|
+
|
|
530
545
|
managerDriver.modifyManagerRouter?.(
|
|
531
546
|
registryConfig,
|
|
532
547
|
router as unknown as Hono,
|
|
533
548
|
);
|
|
534
549
|
|
|
535
|
-
if (runConfig
|
|
550
|
+
if (isInspectorEnabled(runConfig, "manager")) {
|
|
536
551
|
if (!managerDriver.inspector) {
|
|
537
552
|
throw new Unsupported("inspector");
|
|
538
553
|
}
|
|
@@ -548,233 +563,19 @@ export function createManagerRouter(
|
|
|
548
563
|
.route("/", createManagerInspectorRouter()),
|
|
549
564
|
);
|
|
550
565
|
}
|
|
551
|
-
|
|
552
|
-
// Error handling
|
|
553
|
-
router.notFound(handleRouteNotFound);
|
|
554
|
-
router.onError(handleRouteError);
|
|
555
|
-
|
|
556
|
-
return { router: router as Hono, openapi: router };
|
|
557
566
|
}
|
|
558
|
-
/**
|
|
559
|
-
* Creates a WebSocket proxy for test endpoints that forwards messages between server and client WebSockets
|
|
560
|
-
*/
|
|
561
|
-
async function createTestWebSocketProxy(
|
|
562
|
-
clientWsPromise: Promise<UniversalWebSocket>,
|
|
563
|
-
connectionType: string,
|
|
564
|
-
): Promise<UpgradeWebSocketArgs> {
|
|
565
|
-
// Store a reference to the resolved WebSocket
|
|
566
|
-
let clientWs: UniversalWebSocket | null = null;
|
|
567
|
-
try {
|
|
568
|
-
// Resolve the client WebSocket promise
|
|
569
|
-
logger().debug({ msg: "awaiting client websocket promise" });
|
|
570
|
-
const ws = await clientWsPromise;
|
|
571
|
-
clientWs = ws;
|
|
572
|
-
logger().debug({
|
|
573
|
-
msg: "client websocket promise resolved",
|
|
574
|
-
constructor: ws?.constructor.name,
|
|
575
|
-
});
|
|
576
567
|
|
|
577
|
-
|
|
578
|
-
await new Promise<void>((resolve, reject) => {
|
|
579
|
-
const onOpen = () => {
|
|
580
|
-
logger().debug({ msg: "test websocket connection opened" });
|
|
581
|
-
resolve();
|
|
582
|
-
};
|
|
583
|
-
const onError = (error: any) => {
|
|
584
|
-
logger().error({ msg: "test websocket connection failed", error });
|
|
585
|
-
reject(
|
|
586
|
-
new Error(`Failed to open WebSocket: ${error.message || error}`),
|
|
587
|
-
);
|
|
588
|
-
};
|
|
589
|
-
ws.addEventListener("open", onOpen);
|
|
590
|
-
ws.addEventListener("error", onError);
|
|
591
|
-
});
|
|
592
|
-
} catch (error) {
|
|
593
|
-
logger().error({
|
|
594
|
-
msg: `failed to establish client ${connectionType} websocket connection`,
|
|
595
|
-
error,
|
|
596
|
-
});
|
|
597
|
-
return {
|
|
598
|
-
onOpen: (_evt, serverWs) => {
|
|
599
|
-
serverWs.close(1011, "Failed to establish connection");
|
|
600
|
-
},
|
|
601
|
-
onMessage: () => {},
|
|
602
|
-
onError: () => {},
|
|
603
|
-
onClose: () => {},
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
// Create WebSocket proxy handlers to relay messages between client and server
|
|
568
|
+
function createApiActor(actor: ActorOutput): ApiActor {
|
|
608
569
|
return {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
readyState: clientWs.readyState,
|
|
620
|
-
});
|
|
621
|
-
|
|
622
|
-
// Add message handler to forward messages from client to server
|
|
623
|
-
clientWs.addEventListener("message", (clientEvt: MessageEvent) => {
|
|
624
|
-
logger().debug({
|
|
625
|
-
msg: `test ${connectionType} websocket connection message from client`,
|
|
626
|
-
dataType: typeof clientEvt.data,
|
|
627
|
-
isBlob: clientEvt.data instanceof Blob,
|
|
628
|
-
isArrayBuffer: clientEvt.data instanceof ArrayBuffer,
|
|
629
|
-
dataConstructor: clientEvt.data?.constructor?.name,
|
|
630
|
-
dataStr:
|
|
631
|
-
typeof clientEvt.data === "string"
|
|
632
|
-
? clientEvt.data.substring(0, 100)
|
|
633
|
-
: undefined,
|
|
634
|
-
});
|
|
635
|
-
|
|
636
|
-
if (serverWs.readyState === 1) {
|
|
637
|
-
// OPEN
|
|
638
|
-
// Handle Blob data
|
|
639
|
-
if (clientEvt.data instanceof Blob) {
|
|
640
|
-
clientEvt.data
|
|
641
|
-
.arrayBuffer()
|
|
642
|
-
.then((buffer) => {
|
|
643
|
-
logger().debug({
|
|
644
|
-
msg: "converted client blob to arraybuffer, sending to server",
|
|
645
|
-
bufferSize: buffer.byteLength,
|
|
646
|
-
});
|
|
647
|
-
serverWs.send(buffer as any);
|
|
648
|
-
})
|
|
649
|
-
.catch((error) => {
|
|
650
|
-
logger().error({
|
|
651
|
-
msg: "failed to convert blob to arraybuffer",
|
|
652
|
-
error,
|
|
653
|
-
});
|
|
654
|
-
});
|
|
655
|
-
} else {
|
|
656
|
-
logger().debug({
|
|
657
|
-
msg: "sending client data directly to server",
|
|
658
|
-
dataType: typeof clientEvt.data,
|
|
659
|
-
dataLength:
|
|
660
|
-
typeof clientEvt.data === "string"
|
|
661
|
-
? clientEvt.data.length
|
|
662
|
-
: undefined,
|
|
663
|
-
});
|
|
664
|
-
serverWs.send(clientEvt.data as any);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
// Add close handler to close server when client closes
|
|
670
|
-
clientWs.addEventListener("close", (clientEvt: any) => {
|
|
671
|
-
logger().debug({
|
|
672
|
-
msg: `test ${connectionType} websocket connection closed`,
|
|
673
|
-
});
|
|
674
|
-
|
|
675
|
-
if (serverWs.readyState !== 3) {
|
|
676
|
-
// Not CLOSED
|
|
677
|
-
serverWs.close(clientEvt.code, clientEvt.reason);
|
|
678
|
-
}
|
|
679
|
-
});
|
|
680
|
-
|
|
681
|
-
// Add error handler
|
|
682
|
-
clientWs.addEventListener("error", () => {
|
|
683
|
-
logger().debug({
|
|
684
|
-
msg: `test ${connectionType} websocket connection error`,
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
if (serverWs.readyState !== 3) {
|
|
688
|
-
// Not CLOSED
|
|
689
|
-
serverWs.close(1011, "Error in client websocket");
|
|
690
|
-
}
|
|
691
|
-
});
|
|
692
|
-
},
|
|
693
|
-
onMessage: (evt: { data: any }) => {
|
|
694
|
-
logger().debug({
|
|
695
|
-
msg: "received message from server",
|
|
696
|
-
dataType: typeof evt.data,
|
|
697
|
-
isBlob: evt.data instanceof Blob,
|
|
698
|
-
isArrayBuffer: evt.data instanceof ArrayBuffer,
|
|
699
|
-
dataConstructor: evt.data?.constructor?.name,
|
|
700
|
-
dataStr:
|
|
701
|
-
typeof evt.data === "string" ? evt.data.substring(0, 100) : undefined,
|
|
702
|
-
});
|
|
703
|
-
|
|
704
|
-
// Forward messages from server websocket to client websocket
|
|
705
|
-
if (clientWs.readyState === 1) {
|
|
706
|
-
// OPEN
|
|
707
|
-
// Handle Blob data
|
|
708
|
-
if (evt.data instanceof Blob) {
|
|
709
|
-
evt.data
|
|
710
|
-
.arrayBuffer()
|
|
711
|
-
.then((buffer) => {
|
|
712
|
-
logger().debug({
|
|
713
|
-
msg: "converted blob to arraybuffer, sending",
|
|
714
|
-
bufferSize: buffer.byteLength,
|
|
715
|
-
});
|
|
716
|
-
clientWs.send(buffer);
|
|
717
|
-
})
|
|
718
|
-
.catch((error) => {
|
|
719
|
-
logger().error({
|
|
720
|
-
msg: "failed to convert blob to arraybuffer",
|
|
721
|
-
error,
|
|
722
|
-
});
|
|
723
|
-
});
|
|
724
|
-
} else {
|
|
725
|
-
logger().debug({
|
|
726
|
-
msg: "sending data directly",
|
|
727
|
-
dataType: typeof evt.data,
|
|
728
|
-
dataLength:
|
|
729
|
-
typeof evt.data === "string" ? evt.data.length : undefined,
|
|
730
|
-
});
|
|
731
|
-
clientWs.send(evt.data);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
},
|
|
735
|
-
onClose: (
|
|
736
|
-
event: {
|
|
737
|
-
wasClean: boolean;
|
|
738
|
-
code: number;
|
|
739
|
-
reason: string;
|
|
740
|
-
},
|
|
741
|
-
serverWs: WSContext,
|
|
742
|
-
) => {
|
|
743
|
-
logger().debug({
|
|
744
|
-
msg: `server ${connectionType} websocket closed`,
|
|
745
|
-
wasClean: event.wasClean,
|
|
746
|
-
code: event.code,
|
|
747
|
-
reason: event.reason,
|
|
748
|
-
});
|
|
749
|
-
|
|
750
|
-
// HACK: Close socket in order to fix bug with Cloudflare leaving WS in closing state
|
|
751
|
-
// https://github.com/cloudflare/workerd/issues/2569
|
|
752
|
-
serverWs.close(1000, "hack_force_close");
|
|
753
|
-
|
|
754
|
-
// Close the client websocket when the server websocket closes
|
|
755
|
-
if (
|
|
756
|
-
clientWs &&
|
|
757
|
-
clientWs.readyState !== clientWs.CLOSED &&
|
|
758
|
-
clientWs.readyState !== clientWs.CLOSING
|
|
759
|
-
) {
|
|
760
|
-
// Don't pass code/message since this may affect how close events are triggered
|
|
761
|
-
clientWs.close(1000, event.reason);
|
|
762
|
-
}
|
|
763
|
-
},
|
|
764
|
-
onError: (error: unknown) => {
|
|
765
|
-
logger().error({
|
|
766
|
-
msg: `error in server ${connectionType} websocket`,
|
|
767
|
-
error,
|
|
768
|
-
});
|
|
769
|
-
|
|
770
|
-
// Close the client websocket on error
|
|
771
|
-
if (
|
|
772
|
-
clientWs &&
|
|
773
|
-
clientWs.readyState !== clientWs.CLOSED &&
|
|
774
|
-
clientWs.readyState !== clientWs.CLOSING
|
|
775
|
-
) {
|
|
776
|
-
clientWs.close(1011, "Error in server websocket");
|
|
777
|
-
}
|
|
778
|
-
},
|
|
570
|
+
actor_id: actor.actorId,
|
|
571
|
+
name: actor.name,
|
|
572
|
+
key: serializeActorKey(actor.key),
|
|
573
|
+
namespace_id: "default", // Assert default namespace
|
|
574
|
+
runner_name_selector: "rivetkit", // Assert rivetkit runner
|
|
575
|
+
create_ts: Date.now(),
|
|
576
|
+
connectable_ts: null,
|
|
577
|
+
destroy_ts: null,
|
|
578
|
+
sleep_ts: null,
|
|
579
|
+
start_ts: null,
|
|
779
580
|
};
|
|
780
581
|
}
|