rivetkit 2.3.0-rc.10 → 2.3.0-rc.12
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 +448 -62
- package/dist/browser/client.js +131 -89
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +40 -20
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/tsup/actor/errors.cjs +2 -2
- package/dist/tsup/actor/errors.js +1 -1
- package/dist/tsup/agent-os/index.cjs +2103 -2090
- package/dist/tsup/agent-os/index.cjs.map +1 -1
- package/dist/tsup/agent-os/index.d.cts +446 -69
- package/dist/tsup/agent-os/index.d.ts +446 -69
- package/dist/tsup/agent-os/index.js +2102 -2089
- package/dist/tsup/agent-os/index.js.map +1 -1
- package/dist/tsup/{chunk-TE4VCDNY.cjs → chunk-2U6RLFKX.cjs} +219 -234
- package/dist/tsup/chunk-2U6RLFKX.cjs.map +1 -0
- package/dist/tsup/{chunk-4K3MV2MW.cjs → chunk-2ZTBRZRS.cjs} +10 -10
- package/dist/tsup/chunk-2ZTBRZRS.cjs.map +1 -0
- package/dist/tsup/{chunk-KU6VKVEK.js → chunk-3EVVOYFD.js} +19 -7
- package/dist/tsup/chunk-3EVVOYFD.js.map +1 -0
- package/dist/tsup/{chunk-3LGP4JSO.cjs → chunk-6KTMKPNU.cjs} +8 -8
- package/dist/tsup/{chunk-3LGP4JSO.cjs.map → chunk-6KTMKPNU.cjs.map} +1 -1
- package/dist/tsup/{chunk-WU2O2KIE.js → chunk-7UZF56RS.js} +63 -78
- package/dist/tsup/chunk-7UZF56RS.js.map +1 -0
- package/dist/tsup/{chunk-KIWH5H3K.js → chunk-BRP62GZC.js} +3 -3
- package/dist/tsup/chunk-BRP62GZC.js.map +1 -0
- package/dist/tsup/{chunk-G5RULGYQ.cjs → chunk-C7AAIILH.cjs} +24 -9
- package/dist/tsup/chunk-C7AAIILH.cjs.map +1 -0
- package/dist/tsup/{chunk-XV52XUWU.js → chunk-EWVOWEMD.js} +4 -4
- package/dist/tsup/chunk-EWVOWEMD.js.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-PCBNKI2J.js → chunk-JZ7TWV65.js} +1 -1
- package/dist/tsup/chunk-JZ7TWV65.js.map +1 -0
- package/dist/tsup/{chunk-QAZLM4WT.cjs → chunk-KORQB2IR.cjs} +3 -3
- package/dist/tsup/{chunk-QAZLM4WT.cjs.map → chunk-KORQB2IR.cjs.map} +1 -1
- package/dist/tsup/{chunk-CMYS77J6.js → chunk-OLIJHKLL.js} +3 -3
- package/dist/tsup/{chunk-BM3EOY7M.js → chunk-OOB32JVG.js} +134 -20
- package/dist/tsup/chunk-OOB32JVG.js.map +1 -0
- package/dist/tsup/{chunk-G34LIR7S.js → chunk-QKSGGKGQ.js} +22 -7
- package/dist/tsup/chunk-QKSGGKGQ.js.map +1 -0
- package/dist/tsup/{chunk-PWFGP2US.cjs → chunk-SS56HFM2.cjs} +138 -24
- package/dist/tsup/chunk-SS56HFM2.cjs.map +1 -0
- package/dist/tsup/{chunk-Z4C3W2CQ.cjs → chunk-UETC5RF7.cjs} +3 -3
- package/dist/tsup/{chunk-Z4C3W2CQ.cjs.map → chunk-UETC5RF7.cjs.map} +1 -1
- 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-6BI2MS3S.js → chunk-VLXRFJ7P.js} +2 -2
- package/dist/tsup/{chunk-J5P6S2LC.cjs → chunk-VNMIAPPF.cjs} +26 -14
- package/dist/tsup/chunk-VNMIAPPF.cjs.map +1 -0
- package/dist/tsup/{chunk-WQ4HNA4W.cjs → chunk-WHYBAEWG.cjs} +4 -2
- package/dist/tsup/chunk-WHYBAEWG.cjs.map +1 -0
- package/dist/tsup/{chunk-T6YVRM4K.js → chunk-WIMUFZVJ.js} +3 -1
- package/dist/tsup/chunk-WIMUFZVJ.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 +4 -4
- package/dist/tsup/client/mod.d.ts +4 -4
- 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-Ca8dN4cS.d.cts → config-BtAh7oBu.d.cts} +409 -22
- package/dist/tsup/{config-CxjGYf4K.d.cts → config-D49x8NpL.d.cts} +1 -2
- package/dist/tsup/{config-CxjGYf4K.d.ts → config-D49x8NpL.d.ts} +1 -2
- package/dist/tsup/{config-0Ta55UV0.d.ts → config-DKgPGC0f.d.ts} +409 -22
- package/dist/tsup/{context-B_IWbWne.d.ts → context-C-6dGebY.d.ts} +8 -8
- package/dist/tsup/{context-CUrQ9MHc.d.cts → context-Cfjl5pgz.d.cts} +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/mod.cjs +606 -325
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +4 -4
- package/dist/tsup/mod.d.ts +4 -4
- package/dist/tsup/mod.js +510 -229
- 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 +3 -3
- package/dist/tsup/test/mod.d.ts +3 -3
- package/dist/tsup/test/mod.js +18 -15
- package/dist/tsup/test/mod.js.map +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 +307 -282
- package/dist/tsup/workflow/mod.cjs.map +1 -1
- package/dist/tsup/workflow/mod.d.cts +5 -5
- package/dist/tsup/workflow/mod.d.ts +5 -5
- package/dist/tsup/workflow/mod.js +501 -476
- package/dist/tsup/workflow/mod.js.map +1 -1
- package/package.json +22 -11
- package/src/actor/config.ts +68 -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 +9 -3
- package/src/actor/instance/mod.ts +22 -30
- package/src/actor/keys.ts +1 -1
- package/src/actor/mod.ts +20 -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/actor/session.ts +2 -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 +8 -36
- package/src/client/actor-handle.ts +69 -51
- 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 -3
- package/src/client/raw-utils.ts +8 -6
- package/src/client/resolve-gateway-target.ts +1 -1
- package/src/client/utils.ts +2 -7
- 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 +250 -16
- package/src/common/eventsource.ts +1 -1
- package/src/common/inline-websocket-adapter.ts +14 -13
- package/src/common/log.ts +1 -0
- package/src/common/router.ts +13 -17
- package/src/common/utils.ts +1 -150
- package/src/common/websocket-interface.ts +1 -1
- package/src/db/mod.ts +1 -1
- package/src/drivers/engine/actor-driver.ts +58 -56
- 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 +1 -1
- package/src/engine-client/actor-websocket-client.ts +6 -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 +6 -3
- package/src/engine-client/ws-proxy.ts +4 -4
- package/src/inspector/client.browser.ts +5 -11
- package/src/inspector/mod.ts +1 -3
- package/src/registry/config/envoy.ts +1 -2
- package/src/registry/config/index.ts +3 -9
- package/src/registry/index.ts +150 -72
- package/src/registry/napi-runtime.ts +13 -2
- package/src/registry/native-validation.ts +10 -12
- package/src/registry/native.ts +231 -173
- package/src/registry/process-metrics.ts +250 -0
- package/src/registry/runtime.ts +4 -0
- package/src/registry/wasm-runtime.ts +18 -2
- package/src/registry/write-through-proxy.ts +40 -0
- package/src/serde.ts +2 -2
- 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/router.ts +1 -1
- package/src/utils/serve.ts +4 -5
- package/src/utils.ts +1 -2
- package/src/workflow/context.ts +61 -33
- package/src/workflow/driver.ts +4 -6
- package/src/workflow/inspector.ts +4 -3
- 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-4K3MV2MW.cjs.map +0 -1
- package/dist/tsup/chunk-BM3EOY7M.js.map +0 -1
- package/dist/tsup/chunk-G34LIR7S.js.map +0 -1
- package/dist/tsup/chunk-G5RULGYQ.cjs.map +0 -1
- package/dist/tsup/chunk-J5P6S2LC.cjs.map +0 -1
- package/dist/tsup/chunk-KIWH5H3K.js.map +0 -1
- package/dist/tsup/chunk-KU6VKVEK.js.map +0 -1
- package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
- package/dist/tsup/chunk-PWFGP2US.cjs.map +0 -1
- package/dist/tsup/chunk-T6YVRM4K.js.map +0 -1
- package/dist/tsup/chunk-TE4VCDNY.cjs.map +0 -1
- package/dist/tsup/chunk-WQ4HNA4W.cjs.map +0 -1
- package/dist/tsup/chunk-WU2O2KIE.js.map +0 -1
- package/dist/tsup/chunk-XV52XUWU.js.map +0 -1
- /package/dist/tsup/{chunk-CMYS77J6.js.map → chunk-OLIJHKLL.js.map} +0 -0
- /package/dist/tsup/{chunk-6BI2MS3S.js.map → chunk-VLXRFJ7P.js.map} +0 -0
|
@@ -2,23 +2,24 @@ import {
|
|
|
2
2
|
type ClientConfig,
|
|
3
3
|
DEFAULT_MAX_QUERY_INPUT_SIZE,
|
|
4
4
|
} from "@/client/config";
|
|
5
|
+
import type { ActorGatewayQuery, CrashPolicy } from "@/client/query";
|
|
5
6
|
import {
|
|
7
|
+
WS_PROTOCOL_ACTOR,
|
|
6
8
|
WS_PROTOCOL_CONN_PARAMS,
|
|
7
9
|
WS_PROTOCOL_ENCODING,
|
|
8
10
|
WS_PROTOCOL_STANDARD as WS_PROTOCOL_RIVETKIT,
|
|
9
|
-
WS_PROTOCOL_TARGET,
|
|
10
|
-
WS_PROTOCOL_ACTOR,
|
|
11
11
|
WS_PROTOCOL_SKIP_READY_WAIT,
|
|
12
|
+
WS_PROTOCOL_TARGET,
|
|
12
13
|
WS_PROTOCOL_TEST_ACK_HOOK,
|
|
13
14
|
WS_PROTOCOL_TOKEN,
|
|
14
15
|
} from "@/common/actor-router-consts";
|
|
16
|
+
import type { JsonCompatValue } from "@/common/encoding";
|
|
15
17
|
import { importWebSocket } from "@/common/websocket";
|
|
16
18
|
import { setRemoteHibernatableWebSocketAckTestHooks } from "@/common/websocket-test-hooks";
|
|
17
|
-
import type { ActorGatewayQuery, CrashPolicy } from "@/client/query";
|
|
18
19
|
import type { Encoding, UniversalWebSocket } from "@/mod";
|
|
19
20
|
import { encodeCborCompat, uint8ArrayToBase64 } from "@/serde";
|
|
20
21
|
import { combineUrlPath } from "@/utils";
|
|
21
|
-
import {
|
|
22
|
+
import { type GatewayRequestOptions, shouldSkipReadyWait } from "./driver";
|
|
22
23
|
import { logger } from "./log";
|
|
23
24
|
|
|
24
25
|
class BufferedRemoteWebSocket implements UniversalWebSocket {
|
|
@@ -302,7 +303,7 @@ function pushInputQueryParam(
|
|
|
302
303
|
return;
|
|
303
304
|
}
|
|
304
305
|
|
|
305
|
-
const encodedInput = encodeCborCompat(input);
|
|
306
|
+
const encodedInput = encodeCborCompat(input as JsonCompatValue);
|
|
306
307
|
if (encodedInput.byteLength > maxInputSize) {
|
|
307
308
|
throw new Error(
|
|
308
309
|
`Actor query input exceeds maxInputSize (${encodedInput.byteLength} > ${maxInputSize} bytes). Increase client maxInputSize to allow larger query payloads.`,
|
|
@@ -107,12 +107,59 @@ export async function getDatacenters(
|
|
|
107
107
|
return apiCall<never, DatacentersResponse>(config, "GET", `/datacenters`);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// MARK: Get runner configs
|
|
111
|
+
export interface RunnerConfig {
|
|
112
|
+
normal?: {
|
|
113
|
+
drain_on_version_upgrade?: boolean;
|
|
114
|
+
actor_eviction_period?: number;
|
|
115
|
+
actor_eviction_rate?: number;
|
|
116
|
+
};
|
|
117
|
+
serverless?: {
|
|
118
|
+
url: string;
|
|
119
|
+
headers: Record<string, string>;
|
|
120
|
+
drain_grace_period?: number;
|
|
121
|
+
max_runners: number;
|
|
122
|
+
min_runners: number;
|
|
123
|
+
request_lifespan: number;
|
|
124
|
+
runners_margin: number;
|
|
125
|
+
slots_per_runner: number;
|
|
126
|
+
metadata_poll_interval?: number;
|
|
127
|
+
drain_on_version_upgrade?: boolean;
|
|
128
|
+
actor_eviction_period?: number;
|
|
129
|
+
actor_eviction_rate?: number;
|
|
130
|
+
};
|
|
131
|
+
protocol_version?: number;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface RunnerConfigDatacenters {
|
|
135
|
+
datacenters: Record<string, RunnerConfig>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface RunnerConfigsResponse {
|
|
139
|
+
runner_configs: Record<string, RunnerConfigDatacenters>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export async function getRunnerConfig(
|
|
143
|
+
config: ClientConfig,
|
|
144
|
+
name: string,
|
|
145
|
+
): Promise<RunnerConfigsResponse> {
|
|
146
|
+
return apiCall<never, RunnerConfigsResponse>(
|
|
147
|
+
config,
|
|
148
|
+
"GET",
|
|
149
|
+
`/runner-configs?runner_name=${name}`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
110
153
|
// MARK: Update runner config
|
|
111
154
|
export interface RegistryConfigRequest {
|
|
112
155
|
datacenters: Record<
|
|
113
156
|
string,
|
|
114
157
|
{
|
|
115
|
-
normal?:
|
|
158
|
+
normal?: {
|
|
159
|
+
drain_on_version_upgrade?: boolean;
|
|
160
|
+
actor_eviction_period?: number;
|
|
161
|
+
actor_eviction_rate?: number;
|
|
162
|
+
};
|
|
116
163
|
serverless?: {
|
|
117
164
|
url: string;
|
|
118
165
|
headers: Record<string, string>;
|
|
@@ -123,9 +170,11 @@ export interface RegistryConfigRequest {
|
|
|
123
170
|
runners_margin: number;
|
|
124
171
|
slots_per_runner: number;
|
|
125
172
|
metadata_poll_interval?: number;
|
|
173
|
+
drain_on_version_upgrade?: boolean;
|
|
174
|
+
actor_eviction_period?: number;
|
|
175
|
+
actor_eviction_rate?: number;
|
|
126
176
|
};
|
|
127
177
|
metadata?: Record<string, unknown>;
|
|
128
|
-
drain_on_version_upgrade?: boolean;
|
|
129
178
|
}
|
|
130
179
|
>;
|
|
131
180
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
|
+
import { RivetError } from "@/actor/errors";
|
|
2
3
|
import type { ClientConfig } from "@/client/config";
|
|
3
4
|
import { sendHttpRequest } from "@/client/utils";
|
|
4
|
-
import {
|
|
5
|
+
import type { RegistryConfig } from "@/registry/config";
|
|
5
6
|
import { combineUrlPath } from "@/utils";
|
|
6
7
|
import { logger } from "./log";
|
|
7
|
-
import { RegistryConfig } from "@/registry/config";
|
|
8
8
|
|
|
9
9
|
export { RivetError as EngineApiError };
|
|
10
10
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Hono, Context as HonoContext } from "hono";
|
|
2
2
|
import type { ActorKey, Encoding, UniversalWebSocket } from "@/actor/mod";
|
|
3
|
+
import type { ActorQuery, CrashPolicy } from "@/client/query";
|
|
3
4
|
import type { RegistryConfig } from "@/registry/config";
|
|
4
5
|
import type { GetUpgradeWebSocket } from "@/utils";
|
|
5
|
-
import type { ActorQuery, CrashPolicy } from "@/client/query";
|
|
6
6
|
|
|
7
7
|
export type GatewayTarget = { directId: string } | ActorQuery;
|
|
8
8
|
|
package/src/engine-client/mod.ts
CHANGED
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
PATH_WEBSOCKET_BASE,
|
|
8
8
|
PATH_WEBSOCKET_PREFIX,
|
|
9
9
|
} from "@/common/actor-router-consts";
|
|
10
|
+
import type { JsonCompatValue } from "@/common/encoding";
|
|
10
11
|
import { noopNext } from "@/common/utils";
|
|
11
12
|
import type { Actor as ApiActor } from "@/engine-api/actors";
|
|
12
|
-
import { shouldSkipReadyWait } from "@/engine-client/driver";
|
|
13
13
|
import type {
|
|
14
14
|
ActorOutput,
|
|
15
15
|
CreateInput,
|
|
@@ -22,6 +22,7 @@ import type {
|
|
|
22
22
|
ListActorsInput,
|
|
23
23
|
RuntimeDisplayInformation,
|
|
24
24
|
} from "@/engine-client/driver";
|
|
25
|
+
import { shouldSkipReadyWait } from "@/engine-client/driver";
|
|
25
26
|
import type { Encoding, UniversalWebSocket } from "@/mod";
|
|
26
27
|
import { encodeCborCompat, uint8ArrayToBase64 } from "@/serde";
|
|
27
28
|
import { combineUrlPath, type GetUpgradeWebSocket } from "@/utils";
|
|
@@ -181,7 +182,9 @@ export class RemoteEngineControlClient implements EngineControlClient {
|
|
|
181
182
|
key: serializeActorKey(key),
|
|
182
183
|
runner_name_selector: this.#config.poolName,
|
|
183
184
|
input: actorInput
|
|
184
|
-
? uint8ArrayToBase64(
|
|
185
|
+
? uint8ArrayToBase64(
|
|
186
|
+
encodeCborCompat(actorInput as JsonCompatValue),
|
|
187
|
+
)
|
|
185
188
|
: undefined,
|
|
186
189
|
crash_policy: crashPolicy ?? "sleep",
|
|
187
190
|
});
|
|
@@ -215,7 +218,7 @@ export class RemoteEngineControlClient implements EngineControlClient {
|
|
|
215
218
|
runner_name_selector: this.#config.poolName,
|
|
216
219
|
key: serializeActorKey(key),
|
|
217
220
|
input: input
|
|
218
|
-
? uint8ArrayToBase64(encodeCborCompat(input))
|
|
221
|
+
? uint8ArrayToBase64(encodeCborCompat(input as JsonCompatValue))
|
|
219
222
|
: undefined,
|
|
220
223
|
crash_policy: crashPolicy ?? "sleep",
|
|
221
224
|
});
|
|
@@ -9,7 +9,7 @@ import { logger } from "./log";
|
|
|
9
9
|
* Returns Hono `upgradeWebSocket` args that will proxy requests from the client to a destination address.
|
|
10
10
|
*/
|
|
11
11
|
export async function createWebSocketProxy(
|
|
12
|
-
|
|
12
|
+
_c: HonoContext,
|
|
13
13
|
targetUrl: string,
|
|
14
14
|
protocols: string[],
|
|
15
15
|
): Promise<UpgradeWebSocketArgs> {
|
|
@@ -23,7 +23,7 @@ export async function createWebSocketProxy(
|
|
|
23
23
|
const state: WsState = {};
|
|
24
24
|
|
|
25
25
|
return {
|
|
26
|
-
onOpen: async (
|
|
26
|
+
onOpen: async (_event: any, clientWs: WSContext) => {
|
|
27
27
|
logger().debug({ msg: "client websocket connected", targetUrl });
|
|
28
28
|
|
|
29
29
|
if (clientWs.readyState !== 1) {
|
|
@@ -137,7 +137,7 @@ export async function createWebSocketProxy(
|
|
|
137
137
|
}
|
|
138
138
|
},
|
|
139
139
|
|
|
140
|
-
onClose: (event: any,
|
|
140
|
+
onClose: (event: any, _clientWs: WSContext) => {
|
|
141
141
|
logger().debug({
|
|
142
142
|
msg: "client websocket closed",
|
|
143
143
|
targetUrl,
|
|
@@ -159,7 +159,7 @@ export async function createWebSocketProxy(
|
|
|
159
159
|
}
|
|
160
160
|
},
|
|
161
161
|
|
|
162
|
-
onError: (event: any,
|
|
162
|
+
onError: (event: any, _clientWs: WSContext) => {
|
|
163
163
|
logger().error({ msg: "client websocket error", targetUrl, event });
|
|
164
164
|
|
|
165
165
|
if (state.targetWs) {
|
|
@@ -198,7 +198,9 @@ const v3ToServerToV4 = (v3Data: v3.ToServer): v4.ToServer =>
|
|
|
198
198
|
|
|
199
199
|
const v4ToServerToV3 = (v4Data: v4.ToServer): v3.ToServer => {
|
|
200
200
|
if (v4Data.body.tag === "WorkflowReplayRequest") {
|
|
201
|
-
throw new Error(
|
|
201
|
+
throw new Error(
|
|
202
|
+
"Cannot convert v4-only workflow replay requests to v3",
|
|
203
|
+
);
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
return v4Data as unknown as v3.ToServer;
|
|
@@ -238,11 +240,7 @@ export const TO_SERVER_VERSIONED = createVersionedDataHandler<v4.ToServer>({
|
|
|
238
240
|
v2ToServerToV3,
|
|
239
241
|
v3ToServerToV4,
|
|
240
242
|
],
|
|
241
|
-
serializeConverters: () => [
|
|
242
|
-
v4ToServerToV3,
|
|
243
|
-
v3ToServerToV2,
|
|
244
|
-
v2ToServerToV1,
|
|
245
|
-
],
|
|
243
|
+
serializeConverters: () => [v4ToServerToV3, v3ToServerToV2, v2ToServerToV1],
|
|
246
244
|
});
|
|
247
245
|
|
|
248
246
|
export const TO_CLIENT_VERSIONED = createVersionedDataHandler<v4.ToClient>({
|
|
@@ -279,9 +277,5 @@ export const TO_CLIENT_VERSIONED = createVersionedDataHandler<v4.ToClient>({
|
|
|
279
277
|
v2ToClientToV3,
|
|
280
278
|
v3ToClientToV4,
|
|
281
279
|
],
|
|
282
|
-
serializeConverters: () => [
|
|
283
|
-
v4ToClientToV3,
|
|
284
|
-
v3ToClientToV2,
|
|
285
|
-
v2ToClientToV1,
|
|
286
|
-
],
|
|
280
|
+
serializeConverters: () => [v4ToClientToV3, v3ToClientToV2, v2ToClientToV1],
|
|
287
281
|
});
|
package/src/inspector/mod.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "@/common/bare/generated/inspector/v4";
|
|
2
|
+
export type { WorkflowHistory as TransportWorkflowHistory } from "@/common/bare/transport/v1";
|
|
2
3
|
export {
|
|
3
4
|
decodeWorkflowHistoryTransport,
|
|
4
5
|
encodeWorkflowHistoryTransport,
|
|
@@ -7,6 +8,3 @@ export {
|
|
|
7
8
|
createWorkflowInspectorAdapter,
|
|
8
9
|
type WorkflowInspectorAdapter,
|
|
9
10
|
} from "@/workflow/inspector";
|
|
10
|
-
export type {
|
|
11
|
-
WorkflowHistory as TransportWorkflowHistory,
|
|
12
|
-
} from "@/common/bare/transport/v1";
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
import { getLogger } from "@/common/log";
|
|
3
3
|
import {
|
|
4
|
-
isDev,
|
|
5
4
|
getNodeEnv,
|
|
5
|
+
getRivetEnvoyVersion,
|
|
6
6
|
getRivetPool,
|
|
7
7
|
getRivetTotalSlots,
|
|
8
|
-
getRivetEnvoyVersion,
|
|
9
8
|
} from "@/utils/env-vars";
|
|
10
9
|
|
|
11
10
|
let warnedMissingVersion = false;
|
|
@@ -33,9 +33,7 @@ import {
|
|
|
33
33
|
|
|
34
34
|
export const ActorsSchema = z.record(
|
|
35
35
|
z.string(),
|
|
36
|
-
z.custom<
|
|
37
|
-
BaseActorDefinition<any, any, any, any, any, any, any, any, any>
|
|
38
|
-
>(),
|
|
36
|
+
z.custom<AnyActorDefinition>(),
|
|
39
37
|
);
|
|
40
38
|
export type RegistryActors = z.infer<typeof ActorsSchema>;
|
|
41
39
|
|
|
@@ -267,13 +265,9 @@ export const RegistryConfigSchema = z
|
|
|
267
265
|
* after calling `CoreRegistry::shutdown()`. Defaults to the
|
|
268
266
|
* engine-provided actor stop threshold once the envoy connects.
|
|
269
267
|
*
|
|
270
|
-
* Must be
|
|
268
|
+
* Must be long enough for rivetkit-core to drain the envoy.
|
|
271
269
|
*/
|
|
272
|
-
gracePeriodMs: z
|
|
273
|
-
.number()
|
|
274
|
-
.int()
|
|
275
|
-
.min(1_000)
|
|
276
|
-
.optional(),
|
|
270
|
+
gracePeriodMs: z.number().int().min(1_000).optional(),
|
|
277
271
|
/**
|
|
278
272
|
* If true, rivetkit will not install SIGINT/SIGTERM handlers.
|
|
279
273
|
* Use when the host application owns signal policy and will
|
package/src/registry/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
1
2
|
import { ENGINE_ENDPOINT } from "@/common/engine";
|
|
2
3
|
import { configureServerlessPool } from "@/serverless/configure";
|
|
3
|
-
import { VERSION } from "@/utils";
|
|
4
|
+
import { detectRuntime, VERSION } from "@/utils";
|
|
5
|
+
import { crossPlatformServe, loadRuntimeServeStatic } from "@/utils/serve";
|
|
4
6
|
import {
|
|
5
7
|
type RegistryActors,
|
|
6
8
|
type RegistryConfig,
|
|
@@ -44,8 +46,18 @@ export interface RegistryRoutes {
|
|
|
44
46
|
prometheusMetrics(request?: Request): Promise<Response>;
|
|
45
47
|
}
|
|
46
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;
|
|
56
|
+
}
|
|
57
|
+
|
|
47
58
|
export class Registry<A extends RegistryActors> {
|
|
48
59
|
#config: RegistryConfigInput<A>;
|
|
60
|
+
#buildConfiguredRegistry: typeof buildConfiguredRegistry;
|
|
49
61
|
public readonly routes: RegistryRoutes;
|
|
50
62
|
|
|
51
63
|
get config(): RegistryConfigInput<A> {
|
|
@@ -65,8 +77,10 @@ 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;
|
|
70
84
|
this.routes = {
|
|
71
85
|
health: () => this.#healthRoute(),
|
|
72
86
|
metadata: () => this.#metadataRoute(),
|
|
@@ -75,16 +89,18 @@ export class Registry<A extends RegistryActors> {
|
|
|
75
89
|
};
|
|
76
90
|
}
|
|
77
91
|
|
|
78
|
-
#ensureServerlessPoolConfigured(
|
|
92
|
+
#ensureServerlessPoolConfigured(
|
|
93
|
+
config: RegistryConfig,
|
|
94
|
+
): Promise<void> | undefined {
|
|
79
95
|
if (!config.configurePool) return undefined;
|
|
80
96
|
|
|
81
97
|
if (!this.#configureServerlessPoolPromise) {
|
|
82
|
-
this.#configureServerlessPoolPromise = configureServerlessPool(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
);
|
|
98
|
+
this.#configureServerlessPoolPromise = configureServerlessPool(
|
|
99
|
+
config,
|
|
100
|
+
).catch((error) => {
|
|
101
|
+
this.#configureServerlessPoolPromise = undefined;
|
|
102
|
+
throw error;
|
|
103
|
+
});
|
|
88
104
|
this.#configureServerlessPoolPromise.catch(() => {});
|
|
89
105
|
}
|
|
90
106
|
|
|
@@ -106,7 +122,8 @@ export class Registry<A extends RegistryActors> {
|
|
|
106
122
|
this.#printWelcome(config, "serverless");
|
|
107
123
|
|
|
108
124
|
if (!this.#runtimeServerlessPromise) {
|
|
109
|
-
this.#runtimeServerlessPromise =
|
|
125
|
+
this.#runtimeServerlessPromise =
|
|
126
|
+
this.#buildConfiguredRegistry(config);
|
|
110
127
|
}
|
|
111
128
|
|
|
112
129
|
const { runtime, registry, serveConfig } =
|
|
@@ -120,12 +137,13 @@ export class Registry<A extends RegistryActors> {
|
|
|
120
137
|
serveConfig.serverlessBasePath ?? "/api/rivet",
|
|
121
138
|
);
|
|
122
139
|
const isEngineMetadataRequest =
|
|
123
|
-
request.headers.get("user-agent")?.startsWith("RivetEngine/") ??
|
|
140
|
+
request.headers.get("user-agent")?.startsWith("RivetEngine/") ??
|
|
141
|
+
false;
|
|
124
142
|
|
|
125
143
|
if (isStartRequest) {
|
|
126
144
|
try {
|
|
127
145
|
await this.#ensureServerlessPoolConfigured(config);
|
|
128
|
-
} catch (
|
|
146
|
+
} catch (_error) {
|
|
129
147
|
return new Response(
|
|
130
148
|
JSON.stringify({
|
|
131
149
|
group: "guard",
|
|
@@ -267,7 +285,7 @@ export class Registry<A extends RegistryActors> {
|
|
|
267
285
|
if (isMetadataRequest && !isEngineMetadataRequest) {
|
|
268
286
|
try {
|
|
269
287
|
await this.#ensureServerlessPoolConfigured(config);
|
|
270
|
-
} catch (
|
|
288
|
+
} catch (_error) {
|
|
271
289
|
return new Response(
|
|
272
290
|
JSON.stringify({
|
|
273
291
|
group: "guard",
|
|
@@ -303,6 +321,36 @@ export class Registry<A extends RegistryActors> {
|
|
|
303
321
|
};
|
|
304
322
|
}
|
|
305
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Starts an HTTP server that dispatches every request through the
|
|
326
|
+
* serverless handler. Uses `crossPlatformServe` to pick the right
|
|
327
|
+
* runtime (Node, Bun, Deno).
|
|
328
|
+
*
|
|
329
|
+
* @param opts.port Port to listen on. Defaults to 3000.
|
|
330
|
+
* @param opts.publicDir If set, serves static files from this directory
|
|
331
|
+
* before falling through to the registry handler.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```ts
|
|
335
|
+
* await registry.listen();
|
|
336
|
+
* await registry.listen({ port: 8080, publicDir: "./public" });
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
public async listen(
|
|
340
|
+
opts: { port?: number; publicDir?: string } = {},
|
|
341
|
+
): Promise<void> {
|
|
342
|
+
const port = opts.port ?? 3000;
|
|
343
|
+
const config = this.parseConfig();
|
|
344
|
+
const runtime = detectRuntime();
|
|
345
|
+
const app = new Hono();
|
|
346
|
+
if (opts.publicDir) {
|
|
347
|
+
const serveStatic = await loadRuntimeServeStatic(runtime);
|
|
348
|
+
app.use("*", serveStatic({ root: opts.publicDir }));
|
|
349
|
+
}
|
|
350
|
+
app.all("*", (c) => this.handler(c.req.raw));
|
|
351
|
+
await crossPlatformServe(config, port, app, runtime);
|
|
352
|
+
}
|
|
353
|
+
|
|
306
354
|
/**
|
|
307
355
|
* Returns a health response suitable for mounting in a user-owned router.
|
|
308
356
|
*/
|
|
@@ -392,8 +440,11 @@ export class Registry<A extends RegistryActors> {
|
|
|
392
440
|
const candidates = [
|
|
393
441
|
this.#runtimeServerlessPromise,
|
|
394
442
|
this.#runtimeServeConfiguredPromise,
|
|
395
|
-
].filter(
|
|
396
|
-
|
|
443
|
+
].filter(
|
|
444
|
+
(
|
|
445
|
+
candidate,
|
|
446
|
+
): candidate is ReturnType<typeof buildConfiguredRegistry> =>
|
|
447
|
+
candidate !== undefined,
|
|
397
448
|
);
|
|
398
449
|
|
|
399
450
|
if (candidates.length === 0) return undefined;
|
|
@@ -405,35 +456,33 @@ export class Registry<A extends RegistryActors> {
|
|
|
405
456
|
*/
|
|
406
457
|
#startEnvoy(config: RegistryConfig, printWelcome: boolean) {
|
|
407
458
|
if (!this.#runtimeServePromise) {
|
|
408
|
-
const configuredRegistryPromise =
|
|
459
|
+
const configuredRegistryPromise =
|
|
460
|
+
this.#buildConfiguredRegistry(config);
|
|
409
461
|
this.#runtimeServeConfiguredPromise = configuredRegistryPromise;
|
|
410
462
|
this.#runtimeServePromise = configuredRegistryPromise
|
|
411
463
|
.then(async ({ runtime, registry, serveConfig }) => {
|
|
412
464
|
await runtime.serveRegistry(registry, serveConfig);
|
|
413
465
|
})
|
|
414
|
-
.catch((
|
|
466
|
+
.catch((error) => {
|
|
415
467
|
// Always-attached catch so the stored promise never leaves a
|
|
416
468
|
// rejection unhandled. Downstream awaits (e.g. #runShutdown's
|
|
417
469
|
// Promise.race) attach their own catches and still observe
|
|
418
470
|
// resolution via the race.
|
|
419
|
-
logger().warn({
|
|
471
|
+
logger().warn({ error }, "runtime registry serve errored");
|
|
420
472
|
});
|
|
421
473
|
// Install signal handlers once an envoy lifecycle has begun. Only
|
|
422
474
|
// Mode A ever reaches here. Mode B (handler(request)) intentionally
|
|
423
475
|
// does not install handlers because it runs on Workers/Vercel/Deno
|
|
424
476
|
// Deploy where `process.on` is absent or forbidden; those platforms
|
|
425
477
|
// own their own signal policy.
|
|
426
|
-
this.#installSignalHandlers(config
|
|
478
|
+
this.#installSignalHandlers(config);
|
|
427
479
|
}
|
|
428
480
|
if (printWelcome) {
|
|
429
481
|
this.#printWelcome(config, "serverful");
|
|
430
482
|
}
|
|
431
483
|
}
|
|
432
484
|
|
|
433
|
-
#installSignalHandlers(
|
|
434
|
-
config: RegistryConfig,
|
|
435
|
-
configuredRegistryPromise: ReturnType<typeof buildConfiguredRegistry>,
|
|
436
|
-
): void {
|
|
485
|
+
#installSignalHandlers(config: RegistryConfig): void {
|
|
437
486
|
if (this.#shutdownInstalled) return;
|
|
438
487
|
if (config.shutdown?.disableSignalHandlers) return;
|
|
439
488
|
// Guard against non-Node runtimes (Workers/Edge) where `process` may
|
|
@@ -448,12 +497,7 @@ export class Registry<A extends RegistryActors> {
|
|
|
448
497
|
this.#shutdownInstalled = true;
|
|
449
498
|
|
|
450
499
|
const install = (signal: ShutdownSignal) => {
|
|
451
|
-
const handler = () =>
|
|
452
|
-
this.#onShutdownSignal(
|
|
453
|
-
signal,
|
|
454
|
-
config,
|
|
455
|
-
configuredRegistryPromise,
|
|
456
|
-
);
|
|
500
|
+
const handler = () => this.#onShutdownSignal(signal, config);
|
|
457
501
|
this.#signalHandlers[signal] = handler;
|
|
458
502
|
process.on(signal, handler);
|
|
459
503
|
};
|
|
@@ -461,37 +505,67 @@ export class Registry<A extends RegistryActors> {
|
|
|
461
505
|
install("SIGTERM");
|
|
462
506
|
}
|
|
463
507
|
|
|
464
|
-
#onShutdownSignal(
|
|
465
|
-
signal: ShutdownSignal,
|
|
466
|
-
config: RegistryConfig,
|
|
467
|
-
configuredRegistryPromise: ReturnType<typeof buildConfiguredRegistry>,
|
|
468
|
-
): void {
|
|
508
|
+
#onShutdownSignal(signal: ShutdownSignal, config: RegistryConfig): void {
|
|
469
509
|
if (this.#shutdownInFlight !== null) {
|
|
470
|
-
// Second delivery of the same (or another) shutdown signal
|
|
471
|
-
//
|
|
472
|
-
//
|
|
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
|
|
473
514
|
// swallowed by the container signal path.
|
|
474
515
|
this.#removeSignalHandlers();
|
|
475
516
|
finishShutdownSignal(signal);
|
|
476
517
|
return;
|
|
477
518
|
}
|
|
478
|
-
this.#shutdownInFlight = this.#
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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) => {
|
|
483
557
|
logger().warn({ err }, "shutdown error");
|
|
484
558
|
});
|
|
559
|
+
return this.#shutdownInFlight;
|
|
485
560
|
}
|
|
486
561
|
|
|
487
|
-
async #
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
): Promise<void> {
|
|
562
|
+
async #drain(config: RegistryConfig): Promise<void> {
|
|
563
|
+
const modeAPromise = this.#runtimeServeConfiguredPromise;
|
|
564
|
+
const modeBPromise = this.#runtimeServerlessPromise;
|
|
565
|
+
|
|
492
566
|
const gracePeriodMs =
|
|
493
567
|
config.shutdown?.gracePeriodMs ??
|
|
494
|
-
(await this.#actorStopThresholdMs(
|
|
568
|
+
(await this.#actorStopThresholdMs(modeAPromise ?? modeBPromise)) ??
|
|
495
569
|
30 * 60 * 1000;
|
|
496
570
|
// Race the entire drain sequence (both modes + serve promise) against
|
|
497
571
|
// a single grace ceiling. By default, this uses the engine-provided
|
|
@@ -499,33 +573,33 @@ export class Registry<A extends RegistryActors> {
|
|
|
499
573
|
const drain = async () => {
|
|
500
574
|
// Shut down every live `CoreRegistry` we know about. Mode A
|
|
501
575
|
// (`start()`) and Mode B (`handler()`) each build a separate
|
|
502
|
-
// runtime registry, so one
|
|
503
|
-
//
|
|
504
|
-
const registries: Promise<void>[] = [
|
|
505
|
-
|
|
506
|
-
try {
|
|
507
|
-
const { runtime, registry } =
|
|
508
|
-
await configuredRegistryPromise;
|
|
509
|
-
await runtime.shutdownRegistry(registry);
|
|
510
|
-
} catch (err) {
|
|
511
|
-
logger().warn(
|
|
512
|
-
{ err },
|
|
513
|
-
"runtime registry shutdown errored (mode A)",
|
|
514
|
-
);
|
|
515
|
-
}
|
|
516
|
-
})(),
|
|
517
|
-
];
|
|
518
|
-
const runtimeServerlessPromise = this.#runtimeServerlessPromise;
|
|
519
|
-
if (runtimeServerlessPromise !== undefined) {
|
|
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) {
|
|
520
580
|
registries.push(
|
|
521
581
|
(async () => {
|
|
522
582
|
try {
|
|
523
|
-
const { runtime, registry } =
|
|
524
|
-
await runtimeServerlessPromise;
|
|
583
|
+
const { runtime, registry } = await modeAPromise;
|
|
525
584
|
await runtime.shutdownRegistry(registry);
|
|
526
585
|
} catch (err) {
|
|
527
586
|
logger().warn(
|
|
528
587
|
{ err },
|
|
588
|
+
"runtime registry shutdown errored (mode A)",
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
})(),
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
if (modeBPromise !== undefined) {
|
|
595
|
+
registries.push(
|
|
596
|
+
(async () => {
|
|
597
|
+
try {
|
|
598
|
+
const { runtime, registry } = await modeBPromise;
|
|
599
|
+
await runtime.shutdownRegistry(registry);
|
|
600
|
+
} catch (err) {
|
|
601
|
+
logger().warn(
|
|
602
|
+
{ error: err },
|
|
529
603
|
"runtime registry shutdown errored (mode B)",
|
|
530
604
|
);
|
|
531
605
|
}
|
|
@@ -548,13 +622,14 @@ export class Registry<A extends RegistryActors> {
|
|
|
548
622
|
setTimeout(resolve, gracePeriodMs).unref?.(),
|
|
549
623
|
),
|
|
550
624
|
]);
|
|
551
|
-
this.#removeSignalHandlers();
|
|
552
|
-
finishShutdownSignal(signal);
|
|
553
625
|
}
|
|
554
626
|
|
|
555
627
|
async #actorStopThresholdMs(
|
|
556
|
-
configuredRegistryPromise:
|
|
628
|
+
configuredRegistryPromise:
|
|
629
|
+
| ReturnType<typeof buildConfiguredRegistry>
|
|
630
|
+
| undefined,
|
|
557
631
|
): Promise<number | undefined> {
|
|
632
|
+
if (configuredRegistryPromise === undefined) return undefined;
|
|
558
633
|
try {
|
|
559
634
|
const { runtime, registry } = await configuredRegistryPromise;
|
|
560
635
|
const thresholdMs =
|
|
@@ -646,7 +721,10 @@ function isServerlessStartRequest(request: Request, basePath: string): boolean {
|
|
|
646
721
|
return parsed.pathname === `${normalizedBase}/start`;
|
|
647
722
|
}
|
|
648
723
|
|
|
649
|
-
function isServerlessMetadataRequest(
|
|
724
|
+
function isServerlessMetadataRequest(
|
|
725
|
+
request: Request,
|
|
726
|
+
basePath: string,
|
|
727
|
+
): boolean {
|
|
650
728
|
if (request.method !== "GET") return false;
|
|
651
729
|
const parsed = new URL(request.url);
|
|
652
730
|
const normalizedBase =
|