rivetkit 2.3.0-rc.8 → 2.3.0
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/browser/client.d.ts +481 -74
- package/dist/browser/client.js +174 -148
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +47 -18
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/tsup/actor/errors.cjs +2 -2
- package/dist/tsup/actor/errors.d.cts +1 -1
- package/dist/tsup/actor/errors.d.ts +1 -1
- package/dist/tsup/actor/errors.js +1 -1
- package/dist/tsup/agent-os/index.cjs +2160 -2086
- package/dist/tsup/agent-os/index.cjs.map +1 -1
- package/dist/tsup/agent-os/index.d.cts +479 -73
- package/dist/tsup/agent-os/index.d.ts +479 -73
- package/dist/tsup/agent-os/index.js +2160 -2086
- package/dist/tsup/agent-os/index.js.map +1 -1
- package/dist/tsup/{chunk-KY3CERZR.js → chunk-2OTRTA3J.js} +7 -21
- package/dist/tsup/chunk-2OTRTA3J.js.map +1 -0
- package/dist/tsup/{chunk-HGW6PBWR.cjs → chunk-3677IIOV.cjs} +11 -25
- package/dist/tsup/chunk-3677IIOV.cjs.map +1 -0
- package/dist/tsup/{chunk-OT7FF6GB.cjs → chunk-47HHIEXH.cjs} +24 -9
- package/dist/tsup/chunk-47HHIEXH.cjs.map +1 -0
- package/dist/tsup/{chunk-EMFKMVJR.js → chunk-4JDSFJS5.js} +69 -58
- package/dist/tsup/chunk-4JDSFJS5.js.map +1 -0
- package/dist/tsup/{chunk-7HLFSAJP.cjs → chunk-7QKCIVAY.cjs} +225 -214
- package/dist/tsup/chunk-7QKCIVAY.cjs.map +1 -0
- package/dist/tsup/{chunk-AWTPTUQ7.cjs → chunk-B6VUNZUD.cjs} +10 -10
- package/dist/tsup/{chunk-AWTPTUQ7.cjs.map → chunk-B6VUNZUD.cjs.map} +1 -1
- package/dist/tsup/{chunk-D3T3ZBSY.js → chunk-BEI24WTI.js} +2 -2
- package/dist/tsup/{chunk-TMLOKTRB.js → chunk-BRP62GZC.js} +1 -1
- package/dist/tsup/chunk-BRP62GZC.js.map +1 -0
- package/dist/tsup/{chunk-D5G75T7J.js → chunk-DPIMKYNB.js} +61 -2
- package/dist/tsup/chunk-DPIMKYNB.js.map +1 -0
- package/dist/tsup/{chunk-BATTOVHF.cjs → chunk-DXXJPH55.cjs} +40 -13
- package/dist/tsup/chunk-DXXJPH55.cjs.map +1 -0
- package/dist/tsup/{chunk-3YY5S6TV.js → chunk-HXUEHHJF.js} +2 -2
- package/dist/tsup/chunk-HXUEHHJF.js.map +1 -0
- package/dist/tsup/{chunk-4BPKKZJO.cjs → chunk-I4LN3FNT.cjs} +10 -10
- package/dist/tsup/chunk-I4LN3FNT.cjs.map +1 -0
- package/dist/tsup/{chunk-PCBNKI2J.js → chunk-JZ7TWV65.js} +1 -1
- package/dist/tsup/chunk-JZ7TWV65.js.map +1 -0
- package/dist/tsup/{chunk-63WNTDRC.cjs → chunk-KORQB2IR.cjs} +1 -1
- package/dist/tsup/{chunk-63WNTDRC.cjs.map → chunk-KORQB2IR.cjs.map} +1 -1
- package/dist/tsup/{chunk-6TQSSJ4F.cjs → chunk-LVTBW2RE.cjs} +3 -3
- package/dist/tsup/{chunk-6TQSSJ4F.cjs.map → chunk-LVTBW2RE.cjs.map} +1 -1
- package/dist/tsup/{chunk-4JU3IPG2.js → chunk-MEHBWPLJ.js} +6 -6
- package/dist/tsup/chunk-MEHBWPLJ.js.map +1 -0
- package/dist/tsup/{chunk-SRNOPUC6.cjs → chunk-NIY3RSPX.cjs} +62 -3
- package/dist/tsup/chunk-NIY3RSPX.cjs.map +1 -0
- package/dist/tsup/{chunk-UZXQEGVJ.js → chunk-P2GNQ4RN.js} +4 -4
- package/dist/tsup/{chunk-UZXQEGVJ.js.map → chunk-P2GNQ4RN.js.map} +1 -1
- package/dist/tsup/{chunk-VUGENVIK.js → chunk-UMZVD6DQ.js} +22 -7
- package/dist/tsup/chunk-UMZVD6DQ.js.map +1 -0
- package/dist/tsup/{chunk-LD5YASJU.cjs → chunk-VE2X4KMG.cjs} +2 -2
- package/dist/tsup/{chunk-LD5YASJU.cjs.map → chunk-VE2X4KMG.cjs.map} +1 -1
- package/dist/tsup/{chunk-GBG63SUG.js → chunk-VTTFNQQI.js} +32 -5
- package/dist/tsup/chunk-VTTFNQQI.js.map +1 -0
- package/dist/tsup/{chunk-2NDZ7JCR.cjs → chunk-ZA7FLHKH.cjs} +1 -1
- package/dist/tsup/chunk-ZA7FLHKH.cjs.map +1 -0
- package/dist/tsup/client/mod.cjs +9 -9
- package/dist/tsup/client/mod.d.cts +5 -5
- package/dist/tsup/client/mod.d.ts +5 -5
- 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/{config-Ak1lv4gF.d.ts → config-BxWAw3iH.d.ts} +512 -27
- package/dist/tsup/{config-DU_xj4qZ.d.cts → config-CZQQ-mso.d.cts} +512 -27
- package/dist/tsup/{config-CxjGYf4K.d.ts → config-D49x8NpL.d.cts} +1 -2
- package/dist/tsup/{config-CxjGYf4K.d.cts → config-D49x8NpL.d.ts} +1 -2
- package/dist/tsup/{context-DAAp4Lpg.d.ts → context-Bw7xq8w3.d.cts} +8 -8
- package/dist/tsup/{context-Dt_L55q8.d.cts → context-D8QA76sV.d.ts} +8 -8
- package/dist/tsup/db/drizzle.cjs +3 -3
- package/dist/tsup/db/drizzle.d.cts +1 -1
- package/dist/tsup/db/drizzle.d.ts +1 -1
- package/dist/tsup/db/drizzle.js +1 -1
- package/dist/tsup/db/mod.cjs +2 -2
- package/dist/tsup/db/mod.d.cts +2 -2
- package/dist/tsup/db/mod.d.ts +2 -2
- package/dist/tsup/db/mod.js +1 -1
- package/dist/tsup/dynamic/mod.cjs +24 -0
- package/dist/tsup/dynamic/mod.cjs.map +1 -0
- package/dist/tsup/dynamic/mod.d.cts +37 -0
- package/dist/tsup/dynamic/mod.d.ts +37 -0
- package/dist/tsup/dynamic/mod.js +24 -0
- package/dist/tsup/dynamic/mod.js.map +1 -0
- package/dist/tsup/inspector/mod.cjs +6 -6
- package/dist/tsup/inspector/mod.js +5 -5
- package/dist/tsup/inspector-tab/mod.cjs +173 -0
- package/dist/tsup/inspector-tab/mod.cjs.map +1 -0
- package/dist/tsup/inspector-tab/mod.d.cts +250 -0
- package/dist/tsup/inspector-tab/mod.d.ts +250 -0
- package/dist/tsup/inspector-tab/mod.js +173 -0
- package/dist/tsup/inspector-tab/mod.js.map +1 -0
- package/dist/tsup/mod.cjs +615 -348
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +5 -5
- package/dist/tsup/mod.d.ts +5 -5
- package/dist/tsup/mod.js +511 -244
- package/dist/tsup/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +21 -18
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +4 -4
- package/dist/tsup/test/mod.d.ts +4 -4
- package/dist/tsup/test/mod.js +18 -15
- package/dist/tsup/test/mod.js.map +1 -1
- package/dist/tsup/{utils-DVekpm4I.d.cts → utils-DQosb24I.d.cts} +1 -1
- package/dist/tsup/{utils-DVekpm4I.d.ts → utils-DQosb24I.d.ts} +1 -1
- package/dist/tsup/utils.cjs +3 -3
- package/dist/tsup/utils.d.cts +1 -1
- package/dist/tsup/utils.d.ts +1 -1
- package/dist/tsup/utils.js +2 -2
- package/dist/tsup/workflow/mod.cjs +279 -279
- package/dist/tsup/workflow/mod.cjs.map +1 -1
- package/dist/tsup/workflow/mod.d.cts +6 -6
- package/dist/tsup/workflow/mod.d.ts +6 -6
- package/dist/tsup/workflow/mod.js +380 -380
- package/dist/tsup/workflow/mod.js.map +1 -1
- package/package.json +29 -9
- package/src/actor/config.ts +156 -51
- package/src/actor/contexts/index.ts +7 -2
- package/src/actor/definition.ts +17 -19
- package/src/actor/driver.ts +3 -3
- package/src/actor/errors.ts +8 -2
- package/src/actor/instance/mod.ts +26 -34
- package/src/actor/keys.ts +1 -1
- package/src/actor/mod.ts +22 -20
- package/src/actor/schema.ts +2 -2
- package/src/agent-os/actor/index.ts +38 -18
- package/src/agent-os/actor/preview.ts +1 -2
- package/src/agent-os/config.ts +1 -1
- package/src/agent-os/fs/database-vfs.ts +1 -1
- package/src/agent-os/index.ts +16 -15
- package/src/client/actor-common.ts +87 -54
- package/src/client/actor-conn.ts +11 -11
- package/src/client/actor-handle.ts +69 -52
- package/src/client/actor-query.ts +5 -5
- package/src/client/errors.ts +1 -1
- package/src/client/lifecycle-errors.ts +2 -4
- package/src/client/query.ts +1 -1
- package/src/client/queue.ts +8 -4
- package/src/client/raw-utils.ts +8 -6
- package/src/client/resolve-gateway-target.ts +1 -1
- package/src/client/utils.ts +2 -6
- package/src/common/actor-websocket.ts +3 -1
- package/src/common/bare/actor-persist/v1.ts +205 -163
- package/src/common/bare/actor-persist/v2.ts +265 -213
- package/src/common/bare/actor-persist/v3.ts +176 -172
- package/src/common/bare/actor-persist/v4.ts +254 -253
- package/src/common/bare/transport/v1.ts +659 -543
- package/src/common/client-protocol-versioned.ts +66 -64
- package/src/common/database/config.ts +2 -8
- package/src/common/database/native-database.ts +1 -1
- package/src/common/database/shared.ts +1 -0
- package/src/common/encoding.ts +13 -17
- package/src/common/engine.ts +28 -1
- package/src/common/eventsource.ts +1 -1
- package/src/common/inline-websocket-adapter.ts +3 -2
- package/src/common/router.ts +13 -17
- package/src/common/utils.ts +1 -2
- package/src/common/websocket-interface.ts +1 -1
- package/src/db/mod.ts +1 -1
- package/src/devtools-loader/index.ts +4 -7
- package/src/devtools-loader/serve-devtools.ts +26 -0
- package/src/drivers/engine/actor-driver.ts +48 -46
- package/src/dynamic/instance.ts +32 -0
- package/src/dynamic/internal.ts +50 -0
- package/src/dynamic/isolate-runtime.ts +66 -0
- package/src/dynamic/mod.ts +32 -0
- package/src/engine-client/actor-http-client.ts +3 -3
- package/src/engine-client/actor-websocket-client.ts +5 -5
- package/src/engine-client/api-endpoints.ts +51 -2
- package/src/engine-client/api-utils.ts +2 -2
- package/src/engine-client/driver.ts +1 -1
- package/src/engine-client/mod.ts +5 -3
- package/src/engine-client/ws-proxy.ts +9 -4
- package/src/inspector/client.browser.ts +5 -11
- package/src/inspector/mod.ts +1 -3
- package/src/inspector-tab/mod.ts +315 -0
- package/src/registry/config/envoy.ts +1 -2
- package/src/registry/config/index.ts +40 -16
- package/src/registry/index.ts +226 -83
- package/src/registry/napi-runtime.ts +46 -12
- package/src/registry/native-validation.ts +10 -12
- package/src/registry/native.ts +307 -164
- package/src/registry/process-metrics.ts +90 -23
- package/src/registry/runtime.ts +53 -6
- package/src/registry/wasm-runtime.ts +30 -3
- package/src/serde.ts +1 -1
- package/src/serverless/configure.ts +18 -7
- package/src/test/mod.ts +11 -8
- package/src/utils/endpoint-parser.ts +1 -1
- package/src/utils/env-vars.ts +6 -0
- package/src/utils/router.ts +1 -1
- package/src/utils/serve.ts +4 -5
- package/src/utils.ts +1 -2
- package/src/workflow/context.ts +30 -29
- package/src/workflow/driver.ts +4 -6
- package/src/workflow/inspector.ts +2 -2
- package/src/workflow/mod.ts +15 -17
- package/dist/tsup/chunk-2NDZ7JCR.cjs.map +0 -1
- package/dist/tsup/chunk-3YY5S6TV.js.map +0 -1
- package/dist/tsup/chunk-4BPKKZJO.cjs.map +0 -1
- package/dist/tsup/chunk-4JU3IPG2.js.map +0 -1
- package/dist/tsup/chunk-7HLFSAJP.cjs.map +0 -1
- package/dist/tsup/chunk-BATTOVHF.cjs.map +0 -1
- package/dist/tsup/chunk-D5G75T7J.js.map +0 -1
- package/dist/tsup/chunk-EMFKMVJR.js.map +0 -1
- package/dist/tsup/chunk-GBG63SUG.js.map +0 -1
- package/dist/tsup/chunk-HGW6PBWR.cjs.map +0 -1
- package/dist/tsup/chunk-KY3CERZR.js.map +0 -1
- package/dist/tsup/chunk-OT7FF6GB.cjs.map +0 -1
- package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
- package/dist/tsup/chunk-SRNOPUC6.cjs.map +0 -1
- package/dist/tsup/chunk-TMLOKTRB.js.map +0 -1
- package/dist/tsup/chunk-VUGENVIK.js.map +0 -1
- package/dist/tsup/process-metrics-NW754INA.js +0 -118
- package/dist/tsup/process-metrics-NW754INA.js.map +0 -1
- package/dist/tsup/process-metrics-TYAGKCEJ.cjs +0 -118
- package/dist/tsup/process-metrics-TYAGKCEJ.cjs.map +0 -1
- /package/dist/tsup/{chunk-D3T3ZBSY.js.map → chunk-BEI24WTI.js.map} +0 -0
package/src/registry/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import {
|
|
2
|
+
import { isLocalEngineEndpoint } from "@/common/engine";
|
|
3
3
|
import { configureServerlessPool } from "@/serverless/configure";
|
|
4
4
|
import { detectRuntime, VERSION } from "@/utils";
|
|
5
5
|
import { crossPlatformServe, loadRuntimeServeStatic } from "@/utils/serve";
|
|
@@ -40,13 +40,25 @@ export interface ServerlessHandler {
|
|
|
40
40
|
fetch: FetchHandler;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export interface
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
export interface RegistryRoutes {
|
|
44
|
+
health(): Promise<Response>;
|
|
45
|
+
metadata(): Promise<Response>;
|
|
46
|
+
prometheusMetrics(request?: Request): Promise<Response>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Injectable dependencies for {@link Registry}. Production code uses the
|
|
51
|
+
* defaults. Tests override `buildConfiguredRegistry` to drive lifecycle
|
|
52
|
+
* orchestration against a fake `CoreRuntime` without an engine.
|
|
53
|
+
*/
|
|
54
|
+
export interface RegistryDeps {
|
|
55
|
+
buildConfiguredRegistry: typeof buildConfiguredRegistry;
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
export class Registry<A extends RegistryActors> {
|
|
49
59
|
#config: RegistryConfigInput<A>;
|
|
60
|
+
#buildConfiguredRegistry: typeof buildConfiguredRegistry;
|
|
61
|
+
public readonly routes: RegistryRoutes;
|
|
50
62
|
|
|
51
63
|
get config(): RegistryConfigInput<A> {
|
|
52
64
|
return this.#config;
|
|
@@ -65,20 +77,30 @@ export class Registry<A extends RegistryActors> {
|
|
|
65
77
|
#shutdownInFlight: Promise<void> | null = null;
|
|
66
78
|
#signalHandlers: Partial<Record<ShutdownSignal, () => void>> = {};
|
|
67
79
|
|
|
68
|
-
constructor(config: RegistryConfigInput<A>) {
|
|
80
|
+
constructor(config: RegistryConfigInput<A>, deps?: Partial<RegistryDeps>) {
|
|
69
81
|
this.#config = config;
|
|
82
|
+
this.#buildConfiguredRegistry =
|
|
83
|
+
deps?.buildConfiguredRegistry ?? buildConfiguredRegistry;
|
|
84
|
+
this.routes = {
|
|
85
|
+
health: () => this.#healthRoute(),
|
|
86
|
+
metadata: () => this.#metadataRoute(),
|
|
87
|
+
prometheusMetrics: (request?: Request) =>
|
|
88
|
+
this.#prometheusMetricsRoute(request),
|
|
89
|
+
};
|
|
70
90
|
}
|
|
71
91
|
|
|
72
|
-
#ensureServerlessPoolConfigured(
|
|
92
|
+
#ensureServerlessPoolConfigured(
|
|
93
|
+
config: RegistryConfig,
|
|
94
|
+
): Promise<void> | undefined {
|
|
73
95
|
if (!config.configurePool) return undefined;
|
|
74
96
|
|
|
75
97
|
if (!this.#configureServerlessPoolPromise) {
|
|
76
|
-
this.#configureServerlessPoolPromise = configureServerlessPool(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
);
|
|
98
|
+
this.#configureServerlessPoolPromise = configureServerlessPool(
|
|
99
|
+
config,
|
|
100
|
+
).catch((error) => {
|
|
101
|
+
this.#configureServerlessPoolPromise = undefined;
|
|
102
|
+
throw error;
|
|
103
|
+
});
|
|
82
104
|
this.#configureServerlessPoolPromise.catch(() => {});
|
|
83
105
|
}
|
|
84
106
|
|
|
@@ -100,7 +122,8 @@ export class Registry<A extends RegistryActors> {
|
|
|
100
122
|
this.#printWelcome(config, "serverless");
|
|
101
123
|
|
|
102
124
|
if (!this.#runtimeServerlessPromise) {
|
|
103
|
-
this.#runtimeServerlessPromise =
|
|
125
|
+
this.#runtimeServerlessPromise =
|
|
126
|
+
this.#buildConfiguredRegistry(config);
|
|
104
127
|
}
|
|
105
128
|
|
|
106
129
|
const { runtime, registry, serveConfig } =
|
|
@@ -114,12 +137,13 @@ export class Registry<A extends RegistryActors> {
|
|
|
114
137
|
serveConfig.serverlessBasePath ?? "/api/rivet",
|
|
115
138
|
);
|
|
116
139
|
const isEngineMetadataRequest =
|
|
117
|
-
request.headers.get("user-agent")?.startsWith("RivetEngine/") ??
|
|
140
|
+
request.headers.get("user-agent")?.startsWith("RivetEngine/") ??
|
|
141
|
+
false;
|
|
118
142
|
|
|
119
143
|
if (isStartRequest) {
|
|
120
144
|
try {
|
|
121
145
|
await this.#ensureServerlessPoolConfigured(config);
|
|
122
|
-
} catch (
|
|
146
|
+
} catch (_error) {
|
|
123
147
|
return new Response(
|
|
124
148
|
JSON.stringify({
|
|
125
149
|
group: "guard",
|
|
@@ -261,7 +285,7 @@ export class Registry<A extends RegistryActors> {
|
|
|
261
285
|
if (isMetadataRequest && !isEngineMetadataRequest) {
|
|
262
286
|
try {
|
|
263
287
|
await this.#ensureServerlessPoolConfigured(config);
|
|
264
|
-
} catch (
|
|
288
|
+
} catch (_error) {
|
|
265
289
|
return new Response(
|
|
266
290
|
JSON.stringify({
|
|
267
291
|
group: "guard",
|
|
@@ -327,21 +351,104 @@ export class Registry<A extends RegistryActors> {
|
|
|
327
351
|
await crossPlatformServe(config, port, app, runtime);
|
|
328
352
|
}
|
|
329
353
|
|
|
330
|
-
|
|
354
|
+
/**
|
|
355
|
+
* Returns a health response suitable for mounting in a user-owned router.
|
|
356
|
+
*/
|
|
357
|
+
async #healthRoute(): Promise<Response> {
|
|
358
|
+
const configured = await this.#activeConfiguredRegistry();
|
|
359
|
+
if (!configured) {
|
|
360
|
+
return jsonRouteResponse(503, {
|
|
361
|
+
status: "not_started",
|
|
362
|
+
runtime: "rivetkit",
|
|
363
|
+
version: VERSION,
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const { runtime, registry } = configured;
|
|
368
|
+
if (!runtime.registryHealth) {
|
|
369
|
+
return jsonRouteResponse(501, {
|
|
370
|
+
status: "unsupported",
|
|
371
|
+
runtime: "rivetkit",
|
|
372
|
+
version: VERSION,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const response = await runtime.registryHealth(registry);
|
|
377
|
+
return new Response(new Uint8Array(response.body), {
|
|
378
|
+
status: response.status,
|
|
379
|
+
headers: response.headers,
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Returns serverless metadata suitable for mounting in a user-owned router.
|
|
385
|
+
*/
|
|
386
|
+
async #metadataRoute(): Promise<Response> {
|
|
387
|
+
const configured = await this.#activeConfiguredRegistry();
|
|
388
|
+
if (!configured) {
|
|
389
|
+
return new Response("registry not started\n", {
|
|
390
|
+
status: 503,
|
|
391
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const { runtime, registry } = configured;
|
|
396
|
+
if (!runtime.registryMetadata) {
|
|
397
|
+
return new Response("metadata is not supported by this runtime\n", {
|
|
398
|
+
status: 501,
|
|
399
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const response = await runtime.registryMetadata(registry);
|
|
404
|
+
return new Response(new Uint8Array(response.body), {
|
|
405
|
+
status: response.status,
|
|
406
|
+
headers: response.headers,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Returns a Prometheus metrics response suitable for mounting in a user-owned router.
|
|
412
|
+
*/
|
|
413
|
+
async #prometheusMetricsRoute(_request?: Request): Promise<Response> {
|
|
414
|
+
const configured = await this.#activeConfiguredRegistry();
|
|
415
|
+
if (!configured) {
|
|
416
|
+
return new Response("registry not started\n", {
|
|
417
|
+
status: 503,
|
|
418
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const { runtime, registry } = configured;
|
|
423
|
+
if (!runtime.registryMetrics) {
|
|
424
|
+
return new Response("metrics are not supported by this runtime\n", {
|
|
425
|
+
status: 501,
|
|
426
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const response = await runtime.registryMetrics(registry);
|
|
431
|
+
return new Response(new Uint8Array(response.body), {
|
|
432
|
+
status: response.status,
|
|
433
|
+
headers: response.headers,
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
async #activeConfiguredRegistry(): Promise<
|
|
438
|
+
Awaited<ReturnType<typeof buildConfiguredRegistry>> | undefined
|
|
439
|
+
> {
|
|
331
440
|
const candidates = [
|
|
332
441
|
this.#runtimeServerlessPromise,
|
|
333
442
|
this.#runtimeServeConfiguredPromise,
|
|
334
|
-
].filter(
|
|
335
|
-
|
|
443
|
+
].filter(
|
|
444
|
+
(
|
|
445
|
+
candidate,
|
|
446
|
+
): candidate is ReturnType<typeof buildConfiguredRegistry> =>
|
|
447
|
+
candidate !== undefined,
|
|
336
448
|
);
|
|
337
449
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const diagnostics = await runtime.registryDiagnostics?.(registry);
|
|
341
|
-
if (diagnostics) return diagnostics;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
return { mode: "not_started", envoyActiveActorCount: null };
|
|
450
|
+
if (candidates.length === 0) return undefined;
|
|
451
|
+
return await candidates[0]!;
|
|
345
452
|
}
|
|
346
453
|
|
|
347
454
|
/**
|
|
@@ -349,7 +456,8 @@ export class Registry<A extends RegistryActors> {
|
|
|
349
456
|
*/
|
|
350
457
|
#startEnvoy(config: RegistryConfig, printWelcome: boolean) {
|
|
351
458
|
if (!this.#runtimeServePromise) {
|
|
352
|
-
const configuredRegistryPromise =
|
|
459
|
+
const configuredRegistryPromise =
|
|
460
|
+
this.#buildConfiguredRegistry(config);
|
|
353
461
|
this.#runtimeServeConfiguredPromise = configuredRegistryPromise;
|
|
354
462
|
this.#runtimeServePromise = configuredRegistryPromise
|
|
355
463
|
.then(async ({ runtime, registry, serveConfig }) => {
|
|
@@ -367,17 +475,14 @@ export class Registry<A extends RegistryActors> {
|
|
|
367
475
|
// does not install handlers because it runs on Workers/Vercel/Deno
|
|
368
476
|
// Deploy where `process.on` is absent or forbidden; those platforms
|
|
369
477
|
// own their own signal policy.
|
|
370
|
-
this.#installSignalHandlers(config
|
|
478
|
+
this.#installSignalHandlers(config);
|
|
371
479
|
}
|
|
372
480
|
if (printWelcome) {
|
|
373
481
|
this.#printWelcome(config, "serverful");
|
|
374
482
|
}
|
|
375
483
|
}
|
|
376
484
|
|
|
377
|
-
#installSignalHandlers(
|
|
378
|
-
config: RegistryConfig,
|
|
379
|
-
configuredRegistryPromise: ReturnType<typeof buildConfiguredRegistry>,
|
|
380
|
-
): void {
|
|
485
|
+
#installSignalHandlers(config: RegistryConfig): void {
|
|
381
486
|
if (this.#shutdownInstalled) return;
|
|
382
487
|
if (config.shutdown?.disableSignalHandlers) return;
|
|
383
488
|
// Guard against non-Node runtimes (Workers/Edge) where `process` may
|
|
@@ -392,12 +497,7 @@ export class Registry<A extends RegistryActors> {
|
|
|
392
497
|
this.#shutdownInstalled = true;
|
|
393
498
|
|
|
394
499
|
const install = (signal: ShutdownSignal) => {
|
|
395
|
-
const handler = () =>
|
|
396
|
-
this.#onShutdownSignal(
|
|
397
|
-
signal,
|
|
398
|
-
config,
|
|
399
|
-
configuredRegistryPromise,
|
|
400
|
-
);
|
|
500
|
+
const handler = () => this.#onShutdownSignal(signal, config);
|
|
401
501
|
this.#signalHandlers[signal] = handler;
|
|
402
502
|
process.on(signal, handler);
|
|
403
503
|
};
|
|
@@ -405,37 +505,67 @@ export class Registry<A extends RegistryActors> {
|
|
|
405
505
|
install("SIGTERM");
|
|
406
506
|
}
|
|
407
507
|
|
|
408
|
-
#onShutdownSignal(
|
|
409
|
-
signal: ShutdownSignal,
|
|
410
|
-
config: RegistryConfig,
|
|
411
|
-
configuredRegistryPromise: ReturnType<typeof buildConfiguredRegistry>,
|
|
412
|
-
): void {
|
|
508
|
+
#onShutdownSignal(signal: ShutdownSignal, config: RegistryConfig): void {
|
|
413
509
|
if (this.#shutdownInFlight !== null) {
|
|
414
|
-
// Second delivery of the same (or another) shutdown signal
|
|
415
|
-
//
|
|
416
|
-
//
|
|
510
|
+
// Second delivery of the same (or another) shutdown signal, or a
|
|
511
|
+
// drain already started by an explicit `shutdown()` call. Remove
|
|
512
|
+
// our handler only, preserving any user-installed listeners. PID 1
|
|
513
|
+
// must exit directly because re-raised default signals can be
|
|
417
514
|
// swallowed by the container signal path.
|
|
418
515
|
this.#removeSignalHandlers();
|
|
419
516
|
finishShutdownSignal(signal);
|
|
420
517
|
return;
|
|
421
518
|
}
|
|
422
|
-
this.#shutdownInFlight = this.#
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
519
|
+
this.#shutdownInFlight = this.#drain(config)
|
|
520
|
+
.catch((err) => {
|
|
521
|
+
logger().warn({ err }, "shutdown error");
|
|
522
|
+
})
|
|
523
|
+
.then(() => {
|
|
524
|
+
this.#removeSignalHandlers();
|
|
525
|
+
finishShutdownSignal(signal);
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Gracefully drains all live registries.
|
|
531
|
+
*
|
|
532
|
+
* Programmatic counterpart to the SIGINT/SIGTERM handlers: tears down
|
|
533
|
+
* every live `CoreRegistry` (both `start()` and `handler()` modes) and
|
|
534
|
+
* waits for the serve promise to resolve, all bounded by the shutdown
|
|
535
|
+
* grace period. Unlike a signal-driven shutdown, this does not re-raise a
|
|
536
|
+
* signal or exit the process. The caller owns process lifetime.
|
|
537
|
+
*
|
|
538
|
+
* Idempotent: concurrent or repeated calls share a single drain. Safe to
|
|
539
|
+
* call even if nothing has been started.
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```ts
|
|
543
|
+
* const registry = setup({ use: { counter } });
|
|
544
|
+
* registry.start();
|
|
545
|
+
* // ...later, on your own shutdown trigger:
|
|
546
|
+
* await registry.shutdown();
|
|
547
|
+
* ```
|
|
548
|
+
*/
|
|
549
|
+
public async shutdown(): Promise<void> {
|
|
550
|
+
if (this.#shutdownInFlight !== null) return this.#shutdownInFlight;
|
|
551
|
+
const config = this.parseConfig();
|
|
552
|
+
// Uninstall our signal handlers so a later SIGINT/SIGTERM does not
|
|
553
|
+
// re-trigger a drain on already-torn-down registries. Subsequent
|
|
554
|
+
// signals fall back to Node's default termination behavior.
|
|
555
|
+
this.#removeSignalHandlers();
|
|
556
|
+
this.#shutdownInFlight = this.#drain(config).catch((err) => {
|
|
557
|
+
logger().warn({ err }, "shutdown error");
|
|
428
558
|
});
|
|
559
|
+
return this.#shutdownInFlight;
|
|
429
560
|
}
|
|
430
561
|
|
|
431
|
-
async #
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
): Promise<void> {
|
|
562
|
+
async #drain(config: RegistryConfig): Promise<void> {
|
|
563
|
+
const modeAPromise = this.#runtimeServeConfiguredPromise;
|
|
564
|
+
const modeBPromise = this.#runtimeServerlessPromise;
|
|
565
|
+
|
|
436
566
|
const gracePeriodMs =
|
|
437
567
|
config.shutdown?.gracePeriodMs ??
|
|
438
|
-
(await this.#actorStopThresholdMs(
|
|
568
|
+
(await this.#actorStopThresholdMs(modeAPromise ?? modeBPromise)) ??
|
|
439
569
|
30 * 60 * 1000;
|
|
440
570
|
// Race the entire drain sequence (both modes + serve promise) against
|
|
441
571
|
// a single grace ceiling. By default, this uses the engine-provided
|
|
@@ -443,29 +573,29 @@ export class Registry<A extends RegistryActors> {
|
|
|
443
573
|
const drain = async () => {
|
|
444
574
|
// Shut down every live `CoreRegistry` we know about. Mode A
|
|
445
575
|
// (`start()`) and Mode B (`handler()`) each build a separate
|
|
446
|
-
// runtime registry, so one
|
|
447
|
-
//
|
|
448
|
-
const registries: Promise<void>[] = [
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
576
|
+
// runtime registry, so one drain fans out to both to honor the
|
|
577
|
+
// spec invariant "single shutdown tears down both modes".
|
|
578
|
+
const registries: Promise<void>[] = [];
|
|
579
|
+
if (modeAPromise !== undefined) {
|
|
580
|
+
registries.push(
|
|
581
|
+
(async () => {
|
|
582
|
+
try {
|
|
583
|
+
const { runtime, registry } = await modeAPromise;
|
|
584
|
+
await runtime.shutdownRegistry(registry);
|
|
585
|
+
} catch (err) {
|
|
586
|
+
logger().warn(
|
|
587
|
+
{ err },
|
|
588
|
+
"runtime registry shutdown errored (mode A)",
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
})(),
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
if (modeBPromise !== undefined) {
|
|
464
595
|
registries.push(
|
|
465
596
|
(async () => {
|
|
466
597
|
try {
|
|
467
|
-
const { runtime, registry } =
|
|
468
|
-
await runtimeServerlessPromise;
|
|
598
|
+
const { runtime, registry } = await modeBPromise;
|
|
469
599
|
await runtime.shutdownRegistry(registry);
|
|
470
600
|
} catch (err) {
|
|
471
601
|
logger().warn(
|
|
@@ -492,13 +622,14 @@ export class Registry<A extends RegistryActors> {
|
|
|
492
622
|
setTimeout(resolve, gracePeriodMs).unref?.(),
|
|
493
623
|
),
|
|
494
624
|
]);
|
|
495
|
-
this.#removeSignalHandlers();
|
|
496
|
-
finishShutdownSignal(signal);
|
|
497
625
|
}
|
|
498
626
|
|
|
499
627
|
async #actorStopThresholdMs(
|
|
500
|
-
configuredRegistryPromise:
|
|
628
|
+
configuredRegistryPromise:
|
|
629
|
+
| ReturnType<typeof buildConfiguredRegistry>
|
|
630
|
+
| undefined,
|
|
501
631
|
): Promise<number | undefined> {
|
|
632
|
+
if (configuredRegistryPromise === undefined) return undefined;
|
|
502
633
|
try {
|
|
503
634
|
const { runtime, registry } = await configuredRegistryPromise;
|
|
504
635
|
const thresholdMs =
|
|
@@ -569,7 +700,9 @@ export class Registry<A extends RegistryActors> {
|
|
|
569
700
|
|
|
570
701
|
if (config.endpoint) {
|
|
571
702
|
const endpointType =
|
|
572
|
-
config.
|
|
703
|
+
config.startEngine || isLocalEngineEndpoint(config.endpoint)
|
|
704
|
+
? "local native"
|
|
705
|
+
: "remote";
|
|
573
706
|
logLine("Endpoint", `${config.endpoint} (${endpointType})`);
|
|
574
707
|
}
|
|
575
708
|
|
|
@@ -590,7 +723,10 @@ function isServerlessStartRequest(request: Request, basePath: string): boolean {
|
|
|
590
723
|
return parsed.pathname === `${normalizedBase}/start`;
|
|
591
724
|
}
|
|
592
725
|
|
|
593
|
-
function isServerlessMetadataRequest(
|
|
726
|
+
function isServerlessMetadataRequest(
|
|
727
|
+
request: Request,
|
|
728
|
+
basePath: string,
|
|
729
|
+
): boolean {
|
|
594
730
|
if (request.method !== "GET") return false;
|
|
595
731
|
const parsed = new URL(request.url);
|
|
596
732
|
const normalizedBase =
|
|
@@ -598,6 +734,13 @@ function isServerlessMetadataRequest(request: Request, basePath: string): boolea
|
|
|
598
734
|
return parsed.pathname === `${normalizedBase}/metadata`;
|
|
599
735
|
}
|
|
600
736
|
|
|
737
|
+
function jsonRouteResponse(status: number, body: unknown): Response {
|
|
738
|
+
return new Response(JSON.stringify(body), {
|
|
739
|
+
status,
|
|
740
|
+
headers: { "content-type": "application/json" },
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
601
744
|
export function setup<A extends RegistryActors>(
|
|
602
745
|
input: RegistryConfigInput<A>,
|
|
603
746
|
): Registry<A> {
|
|
@@ -23,8 +23,8 @@ import type {
|
|
|
23
23
|
RuntimeQueueNextBatchOptions,
|
|
24
24
|
RuntimeQueueTryNextBatchOptions,
|
|
25
25
|
RuntimeQueueWaitOptions,
|
|
26
|
+
RuntimeRegistryRouteResponse,
|
|
26
27
|
RuntimeRequestSaveOpts,
|
|
27
|
-
RuntimeRegistryDiagnostics,
|
|
28
28
|
RuntimeServeConfig,
|
|
29
29
|
RuntimeServerlessRequest,
|
|
30
30
|
RuntimeServerlessResponseHead,
|
|
@@ -202,16 +202,6 @@ export class NapiCoreRuntime implements CoreRuntime {
|
|
|
202
202
|
await asNativeRegistry(registry).shutdown();
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
async registryDiagnostics(
|
|
206
|
-
registry: RegistryHandle,
|
|
207
|
-
): Promise<RuntimeRegistryDiagnostics> {
|
|
208
|
-
const diagnostics = await asNativeRegistry(registry).diagnostics();
|
|
209
|
-
return {
|
|
210
|
-
mode: diagnostics.mode,
|
|
211
|
-
envoyActiveActorCount: diagnostics.envoyActiveActorCount,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
205
|
async registryActorStopThresholdMs(
|
|
216
206
|
registry: RegistryHandle,
|
|
217
207
|
): Promise<number | undefined> {
|
|
@@ -221,6 +211,39 @@ export class NapiCoreRuntime implements CoreRuntime {
|
|
|
221
211
|
);
|
|
222
212
|
}
|
|
223
213
|
|
|
214
|
+
async registryHealth(
|
|
215
|
+
registry: RegistryHandle,
|
|
216
|
+
): Promise<RuntimeRegistryRouteResponse> {
|
|
217
|
+
const response = await asNativeRegistry(registry).health();
|
|
218
|
+
return {
|
|
219
|
+
status: response.status,
|
|
220
|
+
headers: response.headers,
|
|
221
|
+
body: response.body,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async registryMetadata(
|
|
226
|
+
registry: RegistryHandle,
|
|
227
|
+
): Promise<RuntimeRegistryRouteResponse> {
|
|
228
|
+
const response = asNativeRegistry(registry).metadata();
|
|
229
|
+
return {
|
|
230
|
+
status: response.status,
|
|
231
|
+
headers: response.headers,
|
|
232
|
+
body: response.body,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async registryMetrics(
|
|
237
|
+
registry: RegistryHandle,
|
|
238
|
+
): Promise<RuntimeRegistryRouteResponse> {
|
|
239
|
+
const response = asNativeRegistry(registry).metrics();
|
|
240
|
+
return {
|
|
241
|
+
status: response.status,
|
|
242
|
+
headers: response.headers,
|
|
243
|
+
body: response.body,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
224
247
|
async handleServerlessRequest(
|
|
225
248
|
registry: RegistryHandle,
|
|
226
249
|
req: RuntimeServerlessRequest,
|
|
@@ -429,6 +452,12 @@ export class NapiCoreRuntime implements CoreRuntime {
|
|
|
429
452
|
return await asNativeActorContext(ctx).waitForTrackedShutdownWork();
|
|
430
453
|
}
|
|
431
454
|
|
|
455
|
+
async actorWaitForTrackedShutdownWorkUnbounded(
|
|
456
|
+
ctx: ActorContextHandle,
|
|
457
|
+
): Promise<void> {
|
|
458
|
+
await asNativeActorContext(ctx).waitForTrackedShutdownWorkUnbounded();
|
|
459
|
+
}
|
|
460
|
+
|
|
432
461
|
actorKeepAwake(ctx: ActorContextHandle, promise: Promise<unknown>): void {
|
|
433
462
|
asNativeActorContext(ctx).keepAwake(promise);
|
|
434
463
|
}
|
|
@@ -654,10 +683,15 @@ export class NapiCoreRuntime implements CoreRuntime {
|
|
|
654
683
|
ctx: ActorContextHandle,
|
|
655
684
|
names: string[],
|
|
656
685
|
options?: RuntimeQueueWaitOptions | undefined | null,
|
|
686
|
+
signal?: CancellationTokenHandle | undefined | null,
|
|
657
687
|
): Promise<void> {
|
|
658
688
|
await asNativeActorContext(ctx)
|
|
659
689
|
.queue()
|
|
660
|
-
.waitForNamesAvailable(
|
|
690
|
+
.waitForNamesAvailable(
|
|
691
|
+
names,
|
|
692
|
+
options,
|
|
693
|
+
signal ? asNativeCancellationToken(signal) : signal,
|
|
694
|
+
);
|
|
661
695
|
}
|
|
662
696
|
|
|
663
697
|
async actorQueueEnqueueAndWait(
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { RivetError } from "@/actor/errors";
|
|
2
2
|
import {
|
|
3
|
+
type EventSchemaConfig,
|
|
3
4
|
isEventSchemaDefinition,
|
|
4
5
|
isQueueSchemaDefinition,
|
|
5
6
|
isStandardSchema,
|
|
6
|
-
validateSchemaSync,
|
|
7
|
-
type EventSchemaConfig,
|
|
8
7
|
type PrimitiveSchema,
|
|
9
8
|
type QueueSchemaConfig,
|
|
9
|
+
validateSchemaSync,
|
|
10
10
|
} from "@/actor/schema";
|
|
11
11
|
|
|
12
12
|
const CONN_PARAMS_KEY = "__conn_params__";
|
|
@@ -126,19 +126,17 @@ export function validateQueueComplete(
|
|
|
126
126
|
response,
|
|
127
127
|
);
|
|
128
128
|
if (!result.success) {
|
|
129
|
-
throw validationError(
|
|
129
|
+
throw validationError(
|
|
130
|
+
`queue \`${name}\` completion response`,
|
|
131
|
+
result.issues,
|
|
132
|
+
);
|
|
130
133
|
}
|
|
131
134
|
return result.data;
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
function validationError(target: string, issues: unknown[]): RivetError {
|
|
135
|
-
return new RivetError(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
public: true,
|
|
141
|
-
metadata: { issues },
|
|
142
|
-
},
|
|
143
|
-
);
|
|
138
|
+
return new RivetError("actor", "validation_error", `Invalid ${target}`, {
|
|
139
|
+
public: true,
|
|
140
|
+
metadata: { issues },
|
|
141
|
+
});
|
|
144
142
|
}
|