rivetkit 2.0.9 → 2.0.11
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/tsup/{chunk-F2YZNUPU.js → chunk-3JUN3IEH.js} +3 -3
- package/dist/tsup/{chunk-DL7TPF63.cjs → chunk-5ABUOI3V.cjs} +7 -7
- package/dist/tsup/{chunk-DL7TPF63.cjs.map → chunk-5ABUOI3V.cjs.map} +1 -1
- package/dist/tsup/{chunk-SDXTJDDR.cjs → chunk-5JZPEJVJ.cjs} +58 -14
- package/dist/tsup/chunk-5JZPEJVJ.cjs.map +1 -0
- package/dist/tsup/{chunk-SOC4HWCG.cjs → chunk-6PORXHSQ.cjs} +92 -39
- package/dist/tsup/chunk-6PORXHSQ.cjs.map +1 -0
- package/dist/tsup/{chunk-QGRYH6TU.cjs → chunk-765F7ILI.cjs} +7 -6
- package/dist/tsup/chunk-765F7ILI.cjs.map +1 -0
- package/dist/tsup/{chunk-DLPIL3VC.js → chunk-7DCESQ4O.js} +2 -2
- package/dist/tsup/{chunk-R7OP5N25.js → chunk-AZI2T6UF.js} +53 -9
- package/dist/tsup/chunk-AZI2T6UF.js.map +1 -0
- package/dist/tsup/{chunk-A44TWAS5.cjs → chunk-GGIW54I2.cjs} +6 -6
- package/dist/tsup/{chunk-A44TWAS5.cjs.map → chunk-GGIW54I2.cjs.map} +1 -1
- package/dist/tsup/{chunk-7OMMIAWP.cjs → chunk-HDCLOVOE.cjs} +17 -12
- package/dist/tsup/chunk-HDCLOVOE.cjs.map +1 -0
- package/dist/tsup/{chunk-2MJYYF2Q.cjs → chunk-I6AVFIVY.cjs} +12 -12
- package/dist/tsup/{chunk-2MJYYF2Q.cjs.map → chunk-I6AVFIVY.cjs.map} +1 -1
- package/dist/tsup/{chunk-WBSPHV5V.js → chunk-JTWD6ZT2.js} +2 -2
- package/dist/tsup/{chunk-4YV6RDZL.cjs → chunk-LXFOO25H.cjs} +722 -359
- package/dist/tsup/chunk-LXFOO25H.cjs.map +1 -0
- package/dist/tsup/{chunk-YR2VY4XS.js → chunk-MIP4PYTD.js} +5 -4
- package/dist/tsup/chunk-MIP4PYTD.js.map +1 -0
- package/dist/tsup/{chunk-KHZ2QSQ4.js → chunk-MT5ES4XD.js} +32 -10
- package/dist/tsup/chunk-MT5ES4XD.js.map +1 -0
- package/dist/tsup/{chunk-U2IXX6DY.cjs → chunk-NLYAKGML.cjs} +5 -6
- package/dist/tsup/chunk-NLYAKGML.cjs.map +1 -0
- package/dist/tsup/{chunk-FZP2IBIX.js → chunk-NOXYAPM2.js} +603 -240
- package/dist/tsup/chunk-NOXYAPM2.js.map +1 -0
- package/dist/tsup/{chunk-E63WU5PL.js → chunk-NQFIZSTR.js} +5 -6
- package/dist/tsup/chunk-NQFIZSTR.js.map +1 -0
- package/dist/tsup/{chunk-4PSLOAXR.cjs → chunk-O7BIBANW.cjs} +226 -204
- package/dist/tsup/chunk-O7BIBANW.cjs.map +1 -0
- package/dist/tsup/{chunk-VVCL5DXN.js → chunk-OHSP4BUE.js} +97 -44
- package/dist/tsup/{chunk-VVCL5DXN.js.map → chunk-OHSP4BUE.js.map} +1 -1
- package/dist/tsup/{chunk-APHV6WXU.js → chunk-SBUJ3KIM.js} +2 -2
- package/dist/tsup/{chunk-DZZQG7VH.cjs → chunk-WYTLLIJM.cjs} +3 -3
- package/dist/tsup/{chunk-DZZQG7VH.cjs.map → chunk-WYTLLIJM.cjs.map} +1 -1
- package/dist/tsup/{chunk-WRSWUDFA.js → chunk-XO7VX4MN.js} +14 -9
- package/dist/tsup/chunk-XO7VX4MN.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-CEh3WKbA.d.cts → conn-CT_8ZBT_.d.cts} +204 -199
- package/dist/tsup/{conn-Bt8rkUzm.d.ts → conn-d5F0M95s.d.ts} +204 -199
- 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 +6 -6
- package/dist/tsup/driver-test-suite/mod.cjs +117 -103
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +3 -2
- package/dist/tsup/driver-test-suite/mod.d.ts +3 -2
- package/dist/tsup/driver-test-suite/mod.js +62 -48
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +6 -6
- package/dist/tsup/inspector/mod.d.cts +6 -6
- package/dist/tsup/inspector/mod.d.ts +6 -6
- package/dist/tsup/inspector/mod.js +5 -5
- package/dist/tsup/mod.cjs +10 -10
- package/dist/tsup/mod.d.cts +8 -39
- package/dist/tsup/mod.d.ts +8 -39
- 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 +2 -2
- package/dist/tsup/utils.d.cts +2 -1
- package/dist/tsup/utils.d.ts +2 -1
- package/dist/tsup/utils.js +1 -1
- package/package.json +4 -5
- package/src/actor/driver.ts +2 -2
- package/src/actor/protocol/serde.ts +75 -3
- package/src/actor/router-endpoints.ts +6 -6
- package/src/actor/router.ts +2 -2
- package/src/client/actor-conn.ts +24 -3
- package/src/client/config.ts +19 -26
- package/src/driver-helpers/mod.ts +4 -1
- package/src/driver-test-suite/mod.ts +66 -44
- package/src/driver-test-suite/utils.ts +4 -1
- package/src/drivers/default.ts +11 -9
- package/src/drivers/engine/actor-driver.ts +42 -39
- package/src/drivers/engine/config.ts +9 -22
- package/src/drivers/engine/mod.ts +9 -8
- package/src/drivers/file-system/global-state.ts +4 -4
- package/src/engine-process/log.ts +5 -0
- package/src/engine-process/mod.ts +316 -0
- package/src/inspector/utils.ts +6 -4
- package/src/manager/driver.ts +2 -2
- package/src/manager/gateway.ts +29 -11
- package/src/manager/router-schema.ts +20 -0
- package/src/manager/router.ts +116 -29
- package/src/registry/mod.ts +168 -113
- package/src/registry/run-config.ts +116 -47
- package/src/registry/serve.ts +3 -1
- package/src/serde.ts +3 -3
- package/src/test/config.ts +2 -2
- package/src/test/mod.ts +6 -3
- package/src/utils.ts +2 -0
- package/dist/tsup/chunk-4PSLOAXR.cjs.map +0 -1
- package/dist/tsup/chunk-4YV6RDZL.cjs.map +0 -1
- package/dist/tsup/chunk-7OMMIAWP.cjs.map +0 -1
- package/dist/tsup/chunk-E63WU5PL.js.map +0 -1
- package/dist/tsup/chunk-FZP2IBIX.js.map +0 -1
- package/dist/tsup/chunk-KHZ2QSQ4.js.map +0 -1
- package/dist/tsup/chunk-QGRYH6TU.cjs.map +0 -1
- package/dist/tsup/chunk-R7OP5N25.js.map +0 -1
- package/dist/tsup/chunk-SDXTJDDR.cjs.map +0 -1
- package/dist/tsup/chunk-SOC4HWCG.cjs.map +0 -1
- package/dist/tsup/chunk-U2IXX6DY.cjs.map +0 -1
- package/dist/tsup/chunk-WRSWUDFA.js.map +0 -1
- package/dist/tsup/chunk-YR2VY4XS.js.map +0 -1
- /package/dist/tsup/{chunk-F2YZNUPU.js.map → chunk-3JUN3IEH.js.map} +0 -0
- /package/dist/tsup/{chunk-DLPIL3VC.js.map → chunk-7DCESQ4O.js.map} +0 -0
- /package/dist/tsup/{chunk-WBSPHV5V.js.map → chunk-JTWD6ZT2.js.map} +0 -0
- /package/dist/tsup/{chunk-APHV6WXU.js.map → chunk-SBUJ3KIM.js.map} +0 -0
package/src/manager/router.ts
CHANGED
|
@@ -11,9 +11,9 @@ import { createMiddleware } from "hono/factory";
|
|
|
11
11
|
import { streamSSE } from "hono/streaming";
|
|
12
12
|
import invariant from "invariant";
|
|
13
13
|
import { z } from "zod";
|
|
14
|
-
import { ActorNotFound, Unsupported } from "@/actor/errors";
|
|
14
|
+
import { ActorNotFound, InvalidRequest, Unsupported } from "@/actor/errors";
|
|
15
15
|
import { serializeActorKey } from "@/actor/keys";
|
|
16
|
-
import type { Encoding, Transport } from "@/client/mod";
|
|
16
|
+
import type { Client, Encoding, Transport } from "@/client/mod";
|
|
17
17
|
import {
|
|
18
18
|
WS_PROTOCOL_ACTOR,
|
|
19
19
|
WS_PROTOCOL_CONN_ID,
|
|
@@ -28,7 +28,12 @@ import {
|
|
|
28
28
|
handleRouteNotFound,
|
|
29
29
|
loggerMiddleware,
|
|
30
30
|
} from "@/common/router";
|
|
31
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
assertUnreachable,
|
|
33
|
+
deconstructError,
|
|
34
|
+
noopNext,
|
|
35
|
+
stringifyError,
|
|
36
|
+
} from "@/common/utils";
|
|
32
37
|
import { type ActorDriver, HEADER_ACTOR_ID } from "@/driver-helpers/mod";
|
|
33
38
|
import type {
|
|
34
39
|
TestInlineDriverCallRequest,
|
|
@@ -50,11 +55,14 @@ import {
|
|
|
50
55
|
type Actor as ApiActor,
|
|
51
56
|
} from "@/manager-api/actors";
|
|
52
57
|
import { RivetIdSchema } from "@/manager-api/common";
|
|
58
|
+
import type { AnyClient } from "@/mod";
|
|
53
59
|
import type { RegistryConfig } from "@/registry/config";
|
|
54
|
-
import type {
|
|
60
|
+
import type { DriverConfig, RunnerConfig } from "@/registry/run-config";
|
|
61
|
+
import { VERSION } from "@/utils";
|
|
55
62
|
import type { ActorOutput, ManagerDriver } from "./driver";
|
|
56
63
|
import { actorGateway, createTestWebSocketProxy } from "./gateway";
|
|
57
64
|
import { logger } from "./log";
|
|
65
|
+
import { ServerlessStartHeadersSchema } from "./router-schema";
|
|
58
66
|
|
|
59
67
|
function buildOpenApiResponses<T>(schema: T) {
|
|
60
68
|
return {
|
|
@@ -77,9 +85,10 @@ function buildOpenApiResponses<T>(schema: T) {
|
|
|
77
85
|
|
|
78
86
|
export function createManagerRouter(
|
|
79
87
|
registryConfig: RegistryConfig,
|
|
80
|
-
runConfig:
|
|
88
|
+
runConfig: RunnerConfig,
|
|
81
89
|
managerDriver: ManagerDriver,
|
|
82
|
-
|
|
90
|
+
driverConfig: DriverConfig,
|
|
91
|
+
client: AnyClient,
|
|
83
92
|
): { router: Hono; openapi: OpenAPIHono } {
|
|
84
93
|
const router = new OpenAPIHono({ strict: false }).basePath(
|
|
85
94
|
runConfig.basePath,
|
|
@@ -87,10 +96,38 @@ export function createManagerRouter(
|
|
|
87
96
|
|
|
88
97
|
router.use("*", loggerMiddleware(logger()));
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
// HACK: Add Sec-WebSocket-Protocol header to fix KIT-339
|
|
100
|
+
//
|
|
101
|
+
// Some Deno WebSocket providers do not auto-set the protocol, which
|
|
102
|
+
// will cause some WebSocket clients to fail
|
|
103
|
+
router.use(
|
|
104
|
+
"*",
|
|
105
|
+
createMiddleware(async (c, next) => {
|
|
106
|
+
const upgrade = c.req.header("upgrade");
|
|
107
|
+
const isWebSocket = upgrade?.toLowerCase() === "websocket";
|
|
108
|
+
const isGet = c.req.method === "GET";
|
|
109
|
+
|
|
110
|
+
if (isGet && isWebSocket) {
|
|
111
|
+
c.header("Sec-WebSocket-Protocol", "rivet");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
await next();
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
if (runConfig.runnerKind === "serverless") {
|
|
119
|
+
addServerlessRoutes(
|
|
120
|
+
driverConfig,
|
|
121
|
+
registryConfig,
|
|
122
|
+
runConfig,
|
|
123
|
+
managerDriver,
|
|
124
|
+
client,
|
|
125
|
+
router,
|
|
126
|
+
);
|
|
127
|
+
} else if (runConfig.runnerKind === "normal") {
|
|
93
128
|
addManagerRoutes(registryConfig, runConfig, managerDriver, router);
|
|
129
|
+
} else {
|
|
130
|
+
assertUnreachable(runConfig.runnerKind);
|
|
94
131
|
}
|
|
95
132
|
|
|
96
133
|
// Error handling
|
|
@@ -101,11 +138,11 @@ export function createManagerRouter(
|
|
|
101
138
|
}
|
|
102
139
|
|
|
103
140
|
function addServerlessRoutes(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
141
|
+
driverConfig: DriverConfig,
|
|
142
|
+
registryConfig: RegistryConfig,
|
|
143
|
+
runConfig: RunnerConfig,
|
|
144
|
+
managerDriver: ManagerDriver,
|
|
145
|
+
client: AnyClient,
|
|
109
146
|
router: OpenAPIHono,
|
|
110
147
|
) {
|
|
111
148
|
// Apply CORS
|
|
@@ -120,28 +157,68 @@ function addServerlessRoutes(
|
|
|
120
157
|
|
|
121
158
|
// Serverless start endpoint
|
|
122
159
|
router.get("/start", async (c) => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
c.req.header("x-
|
|
126
|
-
|
|
127
|
-
|
|
160
|
+
// Parse headers
|
|
161
|
+
const parseResult = ServerlessStartHeadersSchema.safeParse({
|
|
162
|
+
endpoint: c.req.header("x-rivet-endpoint"),
|
|
163
|
+
token: c.req.header("x-rivet-token") ?? undefined,
|
|
164
|
+
totalSlots: c.req.header("x-rivet-total-slots"),
|
|
165
|
+
runnerName: c.req.header("x-rivet-runner-name"),
|
|
166
|
+
namespace: c.req.header("x-rivet-namespace-id"),
|
|
167
|
+
});
|
|
168
|
+
if (!parseResult.success) {
|
|
169
|
+
throw new InvalidRequest(
|
|
170
|
+
parseResult.error.issues[0]?.message ??
|
|
171
|
+
"invalid serverless start headers",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const { endpoint, token, totalSlots, runnerName, namespace } =
|
|
175
|
+
parseResult.data;
|
|
176
|
+
|
|
177
|
+
logger().debug({
|
|
178
|
+
msg: "received serverless runner start request",
|
|
179
|
+
endpoint,
|
|
180
|
+
totalSlots,
|
|
181
|
+
runnerName,
|
|
182
|
+
namespace,
|
|
183
|
+
});
|
|
128
184
|
|
|
129
|
-
|
|
185
|
+
// Override config
|
|
186
|
+
//
|
|
187
|
+
// We can't do a structuredClone here since this holds functions
|
|
188
|
+
const newRunConfig = Object.assign({}, runConfig);
|
|
189
|
+
newRunConfig.endpoint = endpoint;
|
|
190
|
+
newRunConfig.token = token;
|
|
191
|
+
newRunConfig.totalSlots = totalSlots;
|
|
192
|
+
newRunConfig.runnerName = runnerName;
|
|
193
|
+
newRunConfig.namespace = namespace;
|
|
194
|
+
|
|
195
|
+
// Create new actor driver with updated config
|
|
196
|
+
const actorDriver = driverConfig.actor(
|
|
197
|
+
registryConfig,
|
|
198
|
+
newRunConfig,
|
|
199
|
+
managerDriver,
|
|
200
|
+
client,
|
|
201
|
+
);
|
|
130
202
|
invariant(
|
|
131
203
|
actorDriver.serverlessHandleStart,
|
|
132
204
|
"missing serverlessHandleStart on ActorDriver",
|
|
133
205
|
);
|
|
206
|
+
|
|
134
207
|
return await actorDriver.serverlessHandleStart(c);
|
|
135
208
|
});
|
|
136
209
|
|
|
137
210
|
router.get("/health", (c) => {
|
|
138
|
-
return c.
|
|
211
|
+
return c.json({
|
|
212
|
+
status: "ok",
|
|
213
|
+
runtime: "rivetkit",
|
|
214
|
+
version: VERSION,
|
|
215
|
+
});
|
|
139
216
|
});
|
|
140
217
|
}
|
|
141
218
|
|
|
142
219
|
function addManagerRoutes(
|
|
143
220
|
registryConfig: RegistryConfig,
|
|
144
|
-
runConfig:
|
|
221
|
+
runConfig: RunnerConfig,
|
|
145
222
|
managerDriver: ManagerDriver,
|
|
146
223
|
router: OpenAPIHono,
|
|
147
224
|
) {
|
|
@@ -244,7 +321,9 @@ function addManagerRoutes(
|
|
|
244
321
|
}
|
|
245
322
|
|
|
246
323
|
return c.json<ActorsListResponse>({
|
|
247
|
-
actors: actors.map(
|
|
324
|
+
actors: actors.map((actor) =>
|
|
325
|
+
createApiActor(actor, runConfig.runnerName),
|
|
326
|
+
),
|
|
248
327
|
});
|
|
249
328
|
});
|
|
250
329
|
}
|
|
@@ -278,7 +357,7 @@ function addManagerRoutes(
|
|
|
278
357
|
|
|
279
358
|
if (existingActor) {
|
|
280
359
|
return c.json<ActorsGetOrCreateResponse>({
|
|
281
|
-
actor: createApiActor(existingActor),
|
|
360
|
+
actor: createApiActor(existingActor, runConfig.runnerName),
|
|
282
361
|
created: false,
|
|
283
362
|
});
|
|
284
363
|
}
|
|
@@ -295,7 +374,7 @@ function addManagerRoutes(
|
|
|
295
374
|
});
|
|
296
375
|
|
|
297
376
|
return c.json<ActorsGetOrCreateResponse>({
|
|
298
|
-
actor: createApiActor(newActor),
|
|
377
|
+
actor: createApiActor(newActor, runConfig.runnerName),
|
|
299
378
|
created: true,
|
|
300
379
|
});
|
|
301
380
|
});
|
|
@@ -333,7 +412,7 @@ function addManagerRoutes(
|
|
|
333
412
|
});
|
|
334
413
|
|
|
335
414
|
// Transform ActorOutput to match ActorSchema
|
|
336
|
-
const actor = createApiActor(actorOutput);
|
|
415
|
+
const actor = createApiActor(actorOutput, runConfig.runnerName);
|
|
337
416
|
|
|
338
417
|
return c.json<ActorsCreateResponse>({ actor });
|
|
339
418
|
});
|
|
@@ -564,7 +643,12 @@ function addManagerRoutes(
|
|
|
564
643
|
}
|
|
565
644
|
|
|
566
645
|
router.get("/health", (c) => {
|
|
567
|
-
return c.
|
|
646
|
+
return c.json({
|
|
647
|
+
status: "ok",
|
|
648
|
+
rivetkit: {
|
|
649
|
+
version: VERSION,
|
|
650
|
+
},
|
|
651
|
+
});
|
|
568
652
|
});
|
|
569
653
|
|
|
570
654
|
managerDriver.modifyManagerRouter?.(
|
|
@@ -573,13 +657,16 @@ function addManagerRoutes(
|
|
|
573
657
|
);
|
|
574
658
|
}
|
|
575
659
|
|
|
576
|
-
function createApiActor(
|
|
660
|
+
function createApiActor(
|
|
661
|
+
actor: ActorOutput,
|
|
662
|
+
runnerName: string = "default",
|
|
663
|
+
): ApiActor {
|
|
577
664
|
return {
|
|
578
665
|
actor_id: actor.actorId,
|
|
579
666
|
name: actor.name,
|
|
580
667
|
key: serializeActorKey(actor.key),
|
|
581
668
|
namespace_id: "default", // Assert default namespace
|
|
582
|
-
runner_name_selector:
|
|
669
|
+
runner_name_selector: runnerName,
|
|
583
670
|
create_ts: Date.now(),
|
|
584
671
|
connectable_ts: null,
|
|
585
672
|
destroy_ts: null,
|
package/src/registry/mod.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import invariant from "invariant";
|
|
1
2
|
import { type Client, createClientWithDriver } from "@/client/client";
|
|
2
3
|
import { configureBaseLogger, configureDefaultLogger } from "@/common/log";
|
|
3
4
|
import type { ActorDriver } from "@/driver-helpers/mod";
|
|
4
5
|
import { chooseDefaultDriver } from "@/drivers/default";
|
|
6
|
+
import { ENGINE_ENDPOINT, ensureEngineProcess } from "@/engine-process/mod";
|
|
5
7
|
import {
|
|
6
8
|
configureInspectorAccessToken,
|
|
7
9
|
getInspectorUrl,
|
|
@@ -18,12 +20,16 @@ import {
|
|
|
18
20
|
import { logger } from "./log";
|
|
19
21
|
import {
|
|
20
22
|
type DriverConfig,
|
|
21
|
-
type
|
|
22
|
-
type
|
|
23
|
-
|
|
23
|
+
type RunnerConfig,
|
|
24
|
+
type RunnerConfigInput,
|
|
25
|
+
RunnerConfigSchema,
|
|
24
26
|
} from "./run-config";
|
|
25
27
|
import { crossPlatformServe } from "./serve";
|
|
26
28
|
|
|
29
|
+
export type ServerlessActorDriverBuilder = (
|
|
30
|
+
updateConfig: (config: RunnerConfig) => void,
|
|
31
|
+
) => ActorDriver;
|
|
32
|
+
|
|
27
33
|
interface ServerOutput<A extends Registry<any>> {
|
|
28
34
|
/** Client to communicate with the actors. */
|
|
29
35
|
client: Client<A>;
|
|
@@ -45,8 +51,49 @@ export class Registry<A extends RegistryActors> {
|
|
|
45
51
|
/**
|
|
46
52
|
* Runs the registry for a server.
|
|
47
53
|
*/
|
|
48
|
-
public start(inputConfig?:
|
|
49
|
-
const config =
|
|
54
|
+
public start(inputConfig?: RunnerConfigInput): ServerOutput<this> {
|
|
55
|
+
const config = RunnerConfigSchema.parse(inputConfig);
|
|
56
|
+
|
|
57
|
+
// Validate autoConfigureServerless is only used with serverless runner
|
|
58
|
+
if (config.autoConfigureServerless && config.runnerKind !== "serverless") {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"autoConfigureServerless can only be configured when runnerKind is 'serverless'",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Promise for any async operations we need to wait to complete
|
|
65
|
+
const readyPromises = [];
|
|
66
|
+
|
|
67
|
+
// Start engine
|
|
68
|
+
if (config.runEngine) {
|
|
69
|
+
logger().debug({
|
|
70
|
+
msg: "run engine requested",
|
|
71
|
+
version: config.runEngineVersion,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Set config to point to the engine
|
|
75
|
+
invariant(
|
|
76
|
+
config.endpoint === undefined,
|
|
77
|
+
"cannot specify 'endpoint' with 'runEngine'",
|
|
78
|
+
);
|
|
79
|
+
config.endpoint = ENGINE_ENDPOINT;
|
|
80
|
+
config.disableActorDriver = true;
|
|
81
|
+
|
|
82
|
+
// Start the engine
|
|
83
|
+
const engineProcessPromise = ensureEngineProcess({
|
|
84
|
+
version: config.runEngineVersion,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Chain ready promise
|
|
88
|
+
readyPromises.push(engineProcessPromise);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Configure for serverless
|
|
92
|
+
if (config.runnerKind === "serverless") {
|
|
93
|
+
config.defaultServerPort = 8080;
|
|
94
|
+
config.overrideServerAddress = config.endpoint;
|
|
95
|
+
config.disableActorDriver = true;
|
|
96
|
+
}
|
|
50
97
|
|
|
51
98
|
// Configure logger
|
|
52
99
|
if (config.logging?.baseLogger) {
|
|
@@ -61,14 +108,18 @@ export class Registry<A extends RegistryActors> {
|
|
|
61
108
|
// Choose the driver based on configuration
|
|
62
109
|
const driver = chooseDefaultDriver(config);
|
|
63
110
|
|
|
64
|
-
//
|
|
111
|
+
// Set defaults based on the driver
|
|
65
112
|
if (driver.name === "engine") {
|
|
66
113
|
config.inspector.enabled = { manager: false, actor: true };
|
|
67
|
-
|
|
114
|
+
|
|
115
|
+
// We need to leave the default server enabled for dev
|
|
116
|
+
if (config.runnerKind !== "serverless") {
|
|
117
|
+
config.disableDefaultServer = true;
|
|
118
|
+
}
|
|
68
119
|
}
|
|
69
120
|
if (driver.name === "cloudflare-workers") {
|
|
70
121
|
config.inspector.enabled = { manager: false, actor: true };
|
|
71
|
-
config.
|
|
122
|
+
config.disableDefaultServer = true;
|
|
72
123
|
config.disableActorDriver = true;
|
|
73
124
|
config.noWelcome = true;
|
|
74
125
|
}
|
|
@@ -102,7 +153,15 @@ export class Registry<A extends RegistryActors> {
|
|
|
102
153
|
const displayInfo = managerDriver.displayInformation();
|
|
103
154
|
console.log();
|
|
104
155
|
console.log(` RivetKit ${pkg.version} (${displayInfo.name})`);
|
|
105
|
-
|
|
156
|
+
if (!config.disableDefaultServer) {
|
|
157
|
+
console.log(` - Endpoint: ${config.endpoint}`);
|
|
158
|
+
} else if (config.overrideServerAddress) {
|
|
159
|
+
console.log(` - Endpoint: ${config.overrideServerAddress}`);
|
|
160
|
+
}
|
|
161
|
+
if (config.runEngine) {
|
|
162
|
+
const padding = " ".repeat(Math.max(0, 13 - "Engine".length));
|
|
163
|
+
console.log(` - Engine:${padding}v${config.runEngineVersion}`);
|
|
164
|
+
}
|
|
106
165
|
for (const [k, v] of Object.entries(displayInfo.properties)) {
|
|
107
166
|
const padding = " ".repeat(Math.max(0, 13 - k.length));
|
|
108
167
|
console.log(` - ${k}:${padding}${v}`);
|
|
@@ -116,27 +175,32 @@ export class Registry<A extends RegistryActors> {
|
|
|
116
175
|
// HACK: We need to find a better way to let the driver itself decide when to start the actor driver
|
|
117
176
|
// Create runner
|
|
118
177
|
//
|
|
119
|
-
// Even though we do not use the
|
|
178
|
+
// Even though we do not use the returned ActorDriver, this is required to start the code that will handle incoming actors
|
|
120
179
|
if (!config.disableActorDriver) {
|
|
121
|
-
|
|
122
|
-
this.#config,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
180
|
+
Promise.all(readyPromises).then(async () => {
|
|
181
|
+
driver.actor(this.#config, config, managerDriver, client);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Configure serverless runner if enabled when actor driver is disabled
|
|
186
|
+
if (config.runnerKind === "serverless" && config.autoConfigureServerless) {
|
|
187
|
+
Promise.all(readyPromises).then(async () => {
|
|
188
|
+
await configureServerlessRunner(config);
|
|
189
|
+
});
|
|
127
190
|
}
|
|
128
191
|
|
|
129
192
|
const { router: hono } = createManagerRouter(
|
|
130
193
|
this.#config,
|
|
131
194
|
config,
|
|
132
195
|
managerDriver,
|
|
133
|
-
|
|
196
|
+
driver,
|
|
197
|
+
client,
|
|
134
198
|
);
|
|
135
199
|
|
|
136
200
|
// Start server
|
|
137
|
-
if (!config.
|
|
201
|
+
if (!config.disableDefaultServer) {
|
|
138
202
|
(async () => {
|
|
139
|
-
const out = await crossPlatformServe(hono, undefined);
|
|
203
|
+
const out = await crossPlatformServe(config, hono, undefined);
|
|
140
204
|
upgradeWebSocket = out.upgradeWebSocket;
|
|
141
205
|
})();
|
|
142
206
|
}
|
|
@@ -146,116 +210,107 @@ export class Registry<A extends RegistryActors> {
|
|
|
146
210
|
fetch: hono.fetch.bind(hono),
|
|
147
211
|
};
|
|
148
212
|
}
|
|
213
|
+
}
|
|
149
214
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// Use provided base logger
|
|
156
|
-
configureBaseLogger(config.logging.baseLogger);
|
|
157
|
-
} else {
|
|
158
|
-
// Configure default logger with log level from config
|
|
159
|
-
// getPinoLevel will handle env variable priority
|
|
160
|
-
configureDefaultLogger(config.logging?.level);
|
|
215
|
+
async function configureServerlessRunner(config: RunnerConfig): Promise<void> {
|
|
216
|
+
try {
|
|
217
|
+
// Ensure we have required config values
|
|
218
|
+
if (!config.runnerName) {
|
|
219
|
+
throw new Error("runnerName is required for serverless configuration");
|
|
161
220
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const driver = chooseDefaultDriver(config);
|
|
165
|
-
|
|
166
|
-
// TODO: Find cleaner way of disabling by default
|
|
167
|
-
if (driver.name === "engine") {
|
|
168
|
-
config.inspector.enabled = false;
|
|
169
|
-
config.disableServer = true;
|
|
170
|
-
config.disableActorDriver = true;
|
|
221
|
+
if (!config.namespace) {
|
|
222
|
+
throw new Error("namespace is required for serverless configuration");
|
|
171
223
|
}
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
config.disableServer = true;
|
|
175
|
-
config.disableActorDriver = true;
|
|
176
|
-
config.noWelcome = true;
|
|
224
|
+
if (!config.endpoint) {
|
|
225
|
+
throw new Error("endpoint is required for serverless configuration");
|
|
177
226
|
}
|
|
178
227
|
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
228
|
+
// Prepare the configuration
|
|
229
|
+
const customConfig =
|
|
230
|
+
typeof config.autoConfigureServerless === "object"
|
|
231
|
+
? config.autoConfigureServerless
|
|
232
|
+
: {};
|
|
184
233
|
|
|
185
|
-
//
|
|
186
|
-
const
|
|
234
|
+
// Make the request to fetch all datacenters
|
|
235
|
+
const dcsUrl = `${config.endpoint}/datacenters`;
|
|
187
236
|
|
|
188
|
-
|
|
189
|
-
|
|
237
|
+
logger().debug({
|
|
238
|
+
msg: "fetching datacenters",
|
|
239
|
+
url: dcsUrl,
|
|
240
|
+
});
|
|
190
241
|
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
definitions: Object.keys(this.#config.use).length,
|
|
196
|
-
...driverLog,
|
|
242
|
+
const dcsResponse = await fetch(dcsUrl, {
|
|
243
|
+
headers: {
|
|
244
|
+
...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),
|
|
245
|
+
},
|
|
197
246
|
});
|
|
198
|
-
if (config.inspector?.enabled && managerDriver.inspector) {
|
|
199
|
-
logger().info({ msg: "inspector ready", url: getInspectorUrl(config) });
|
|
200
|
-
}
|
|
201
247
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
console.log(` - Endpoint: http://127.0.0.1:6420`);
|
|
208
|
-
for (const [k, v] of Object.entries(displayInfo.properties)) {
|
|
209
|
-
const padding = " ".repeat(Math.max(0, 13 - k.length));
|
|
210
|
-
console.log(` - ${k}:${padding}${v}`);
|
|
211
|
-
}
|
|
212
|
-
if (config.inspector?.enabled && managerDriver.inspector) {
|
|
213
|
-
console.log(` - Inspector: ${getInspectorUrl(config)}`);
|
|
214
|
-
}
|
|
215
|
-
console.log();
|
|
248
|
+
if (!dcsResponse.ok) {
|
|
249
|
+
const errorText = await dcsResponse.text();
|
|
250
|
+
throw new Error(
|
|
251
|
+
`failed to configure serverless runner: ${dcsResponse.status} ${dcsResponse.statusText} - ${errorText}`,
|
|
252
|
+
);
|
|
216
253
|
}
|
|
217
254
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
| undefined = (
|
|
221
|
-
token: string | undefined,
|
|
222
|
-
totalSlots: number | undefined,
|
|
223
|
-
) => {
|
|
224
|
-
// Override config
|
|
225
|
-
if (token) config.token = token;
|
|
226
|
-
if (totalSlots) config.totalSlots = totalSlots;
|
|
227
|
-
|
|
228
|
-
return driver.actor(this.#config, config, managerDriver, client);
|
|
255
|
+
const dcsRes = (await dcsResponse.json()) as {
|
|
256
|
+
datacenters: { name: string }[];
|
|
229
257
|
};
|
|
230
258
|
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
259
|
+
// Build the request body
|
|
260
|
+
const serverlessConfig = {
|
|
261
|
+
serverless: {
|
|
262
|
+
url:
|
|
263
|
+
customConfig.url ||
|
|
264
|
+
`http://localhost:${config.defaultServerPort}/start`,
|
|
265
|
+
headers: customConfig.headers || {},
|
|
266
|
+
max_runners: customConfig.maxRunners ?? 100,
|
|
267
|
+
min_runners: customConfig.minRunners ?? 0,
|
|
268
|
+
request_lifespan: customConfig.requestLifespan ?? 15 * 60,
|
|
269
|
+
runners_margin: customConfig.runnersMargin ?? 0,
|
|
270
|
+
slots_per_runner:
|
|
271
|
+
customConfig.slotsPerRunner ?? config.totalSlots ?? 1000,
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
const requestBody = Object.fromEntries(
|
|
275
|
+
dcsRes.datacenters.map((dc) => [dc.name, serverlessConfig]),
|
|
245
276
|
);
|
|
246
277
|
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
278
|
+
// Make the request to configure the serverless runner
|
|
279
|
+
const configUrl = `${config.endpoint}/runner-configs/${config.runnerName}?namespace=${config.namespace}`;
|
|
280
|
+
|
|
281
|
+
logger().debug({
|
|
282
|
+
msg: "configuring serverless runner",
|
|
283
|
+
url: configUrl,
|
|
284
|
+
config: serverlessConfig.serverless,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const response = await fetch(configUrl, {
|
|
288
|
+
method: "PUT",
|
|
289
|
+
headers: {
|
|
290
|
+
"Content-Type": "application/json",
|
|
291
|
+
...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),
|
|
292
|
+
},
|
|
293
|
+
body: JSON.stringify(requestBody),
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
if (!response.ok) {
|
|
297
|
+
const errorText = await response.text();
|
|
298
|
+
throw new Error(
|
|
299
|
+
`failed to configure serverless runner: ${response.status} ${response.statusText} - ${errorText}`,
|
|
300
|
+
);
|
|
253
301
|
}
|
|
254
302
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
303
|
+
logger().info({
|
|
304
|
+
msg: "serverless runner configured successfully",
|
|
305
|
+
runnerName: config.runnerName,
|
|
306
|
+
namespace: config.namespace,
|
|
307
|
+
});
|
|
308
|
+
} catch (error) {
|
|
309
|
+
logger().error({
|
|
310
|
+
msg: "failed to configure serverless runner",
|
|
311
|
+
error,
|
|
312
|
+
});
|
|
313
|
+
throw error;
|
|
259
314
|
}
|
|
260
315
|
}
|
|
261
316
|
|
|
@@ -269,8 +324,8 @@ export function setup<A extends RegistryActors>(
|
|
|
269
324
|
export type {
|
|
270
325
|
RegistryConfig,
|
|
271
326
|
RegistryActors,
|
|
272
|
-
RunConfig,
|
|
273
|
-
RunConfigInput,
|
|
327
|
+
RunnerConfig as RunConfig,
|
|
328
|
+
RunnerConfigInput as RunConfigInput,
|
|
274
329
|
DriverConfig,
|
|
275
330
|
};
|
|
276
331
|
export { RegistryConfigSchema };
|