rivetkit 2.3.0-rc.9 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/client.d.ts +511 -62
- package/dist/browser/client.js +230 -174
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +53 -23
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/tsup/actor/errors.cjs +4 -2
- package/dist/tsup/actor/errors.cjs.map +1 -1
- package/dist/tsup/actor/errors.d.cts +1 -1
- package/dist/tsup/actor/errors.d.ts +1 -1
- package/dist/tsup/actor/errors.js +3 -1
- package/dist/tsup/agent-os/index.cjs +2163 -2087
- package/dist/tsup/agent-os/index.cjs.map +1 -1
- package/dist/tsup/agent-os/index.d.cts +509 -69
- package/dist/tsup/agent-os/index.d.ts +509 -69
- package/dist/tsup/agent-os/index.js +2163 -2087
- package/dist/tsup/agent-os/index.js.map +1 -1
- package/dist/tsup/{chunk-WQ4HNA4W.cjs → chunk-3MHDOUD7.cjs} +73 -3
- package/dist/tsup/chunk-3MHDOUD7.cjs.map +1 -0
- package/dist/tsup/{chunk-QAZLM4WT.cjs → chunk-4FC7TVS6.cjs} +8 -4
- package/dist/tsup/chunk-4FC7TVS6.cjs.map +1 -0
- package/dist/tsup/{chunk-4CGA6QJO.cjs → chunk-4UUEB43Y.cjs} +24 -9
- package/dist/tsup/chunk-4UUEB43Y.cjs.map +1 -0
- package/dist/tsup/{chunk-GVTOE34S.cjs → chunk-5IWLUJ6W.cjs} +222 -235
- package/dist/tsup/chunk-5IWLUJ6W.cjs.map +1 -0
- package/dist/tsup/{chunk-MMMEZM5J.js → chunk-H6VVZMWN.js} +4 -4
- package/dist/tsup/chunk-H6VVZMWN.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-H7P7WR2Y.js → chunk-I35VSLEM.js} +6 -6
- package/dist/tsup/chunk-I35VSLEM.js.map +1 -0
- package/dist/tsup/{chunk-H37XQU3I.js → chunk-JBUZRPY5.js} +2 -2
- package/dist/tsup/{chunk-CPA4Y3RG.cjs → chunk-JLJJZYCJ.cjs} +10 -10
- package/dist/tsup/chunk-JLJJZYCJ.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-VRCIXJRN.js → chunk-L2X3YFER.js} +64 -10
- package/dist/tsup/chunk-L2X3YFER.js.map +1 -0
- package/dist/tsup/{chunk-Y5NSCZA2.cjs → chunk-MNHKOS6L.cjs} +72 -18
- package/dist/tsup/chunk-MNHKOS6L.cjs.map +1 -0
- package/dist/tsup/{chunk-KJTA3ATT.js → chunk-NERUIBOT.js} +22 -7
- package/dist/tsup/chunk-NERUIBOT.js.map +1 -0
- package/dist/tsup/{chunk-4WPEZBK4.cjs → chunk-OST76LRW.cjs} +10 -10
- package/dist/tsup/chunk-OST76LRW.cjs.map +1 -0
- package/dist/tsup/{chunk-MALSPBAF.cjs → chunk-OZBCXBVP.cjs} +3 -3
- package/dist/tsup/{chunk-MALSPBAF.cjs.map → chunk-OZBCXBVP.cjs.map} +1 -1
- package/dist/tsup/{chunk-F3Q5BFQ6.js → chunk-PT6OIW5E.js} +66 -79
- package/dist/tsup/chunk-PT6OIW5E.js.map +1 -0
- package/dist/tsup/{chunk-W7EYSYVI.js → chunk-R6KPN5EW.js} +134 -20
- package/dist/tsup/chunk-R6KPN5EW.js.map +1 -0
- package/dist/tsup/{chunk-VJFRBJVQ.cjs → chunk-V5KMAMX3.cjs} +138 -24
- package/dist/tsup/chunk-V5KMAMX3.cjs.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-T6YVRM4K.js → chunk-XIX5DOZN.js} +72 -2
- package/dist/tsup/chunk-XIX5DOZN.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/{chunk-KIWH5H3K.js → chunk-ZZ3WBRPD.js} +7 -3
- package/dist/tsup/chunk-ZZ3WBRPD.js.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-Ca8dN4cS.d.cts → config-CzvopP5m.d.cts} +544 -23
- 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-DZuT7tcp.d.ts} +544 -23
- package/dist/tsup/context-CyAdY-aA.d.ts +128 -0
- package/dist/tsup/context-sNB28g0N.d.cts +128 -0
- 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 +758 -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 +662 -252
- 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-CqDnC_PS.d.cts} +2 -1
- package/dist/tsup/{utils-DVekpm4I.d.ts → utils-CqDnC_PS.d.ts} +2 -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 +383 -322
- package/dist/tsup/workflow/mod.cjs.map +1 -1
- package/dist/tsup/workflow/mod.d.cts +8 -8
- package/dist/tsup/workflow/mod.d.ts +8 -8
- package/dist/tsup/workflow/mod.js +360 -299
- package/dist/tsup/workflow/mod.js.map +1 -1
- package/package.json +35 -14
- package/src/actor/config.ts +173 -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 +20 -3
- 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/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/engine.ts +28 -1
- 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/devtools-loader/index.ts +4 -7
- package/src/devtools-loader/serve-devtools.ts +26 -0
- 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 +3 -3
- 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 +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 +209 -73
- package/src/registry/napi-runtime.ts +29 -2
- package/src/registry/native-validation.ts +10 -12
- package/src/registry/native.ts +433 -198
- package/src/registry/process-metrics.ts +250 -0
- package/src/registry/runtime.ts +52 -1
- package/src/registry/wasm-runtime.ts +29 -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/env-vars.ts +37 -0
- package/src/utils/router.ts +1 -1
- package/src/utils.ts +1 -2
- package/src/workflow/context.ts +699 -240
- package/src/workflow/driver.ts +23 -12
- package/src/workflow/inspector.ts +4 -3
- package/src/workflow/mod.ts +37 -23
- package/dist/tsup/chunk-2NDZ7JCR.cjs.map +0 -1
- package/dist/tsup/chunk-3YY5S6TV.js.map +0 -1
- package/dist/tsup/chunk-4CGA6QJO.cjs.map +0 -1
- package/dist/tsup/chunk-4WPEZBK4.cjs.map +0 -1
- package/dist/tsup/chunk-CPA4Y3RG.cjs.map +0 -1
- package/dist/tsup/chunk-F3Q5BFQ6.js.map +0 -1
- package/dist/tsup/chunk-GVTOE34S.cjs.map +0 -1
- package/dist/tsup/chunk-H7P7WR2Y.js.map +0 -1
- package/dist/tsup/chunk-KIWH5H3K.js.map +0 -1
- package/dist/tsup/chunk-KJTA3ATT.js.map +0 -1
- package/dist/tsup/chunk-MMMEZM5J.js.map +0 -1
- package/dist/tsup/chunk-PCBNKI2J.js.map +0 -1
- package/dist/tsup/chunk-QAZLM4WT.cjs.map +0 -1
- package/dist/tsup/chunk-T6YVRM4K.js.map +0 -1
- package/dist/tsup/chunk-VJFRBJVQ.cjs.map +0 -1
- package/dist/tsup/chunk-VRCIXJRN.js.map +0 -1
- package/dist/tsup/chunk-W7EYSYVI.js.map +0 -1
- package/dist/tsup/chunk-WQ4HNA4W.cjs.map +0 -1
- package/dist/tsup/chunk-Y5NSCZA2.cjs.map +0 -1
- package/dist/tsup/context-B_IWbWne.d.ts +0 -92
- package/dist/tsup/context-CUrQ9MHc.d.cts +0 -92
- package/src/utils/serve.ts +0 -217
- /package/dist/tsup/{chunk-H37XQU3I.js.map → chunk-JBUZRPY5.js.map} +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js runtime health metrics.
|
|
3
|
+
*
|
|
4
|
+
* Collects JS-internal data (event loop lag, GC, heap, libuv handles,
|
|
5
|
+
* event loop utilization, CPU) using Node built-ins (`node:perf_hooks`,
|
|
6
|
+
* `process`, `node:v8`, `PerformanceObserver`) and pushes them across NAPI
|
|
7
|
+
* into Rust-side prometheus collectors registered with
|
|
8
|
+
* `rivet_metrics::REGISTRY` so they appear on the existing `/metrics`
|
|
9
|
+
* endpoint.
|
|
10
|
+
*
|
|
11
|
+
* All data collection happens here in TypeScript. The NAPI bridge is pure
|
|
12
|
+
* type marshalling and the Rust side only registers + stores the metrics.
|
|
13
|
+
*/
|
|
14
|
+
import {
|
|
15
|
+
monitorEventLoopDelay,
|
|
16
|
+
PerformanceObserver,
|
|
17
|
+
performance,
|
|
18
|
+
} from "node:perf_hooks";
|
|
19
|
+
import { getHeapStatistics } from "node:v8";
|
|
20
|
+
import * as napi from "@rivetkit/rivetkit-napi";
|
|
21
|
+
|
|
22
|
+
type OptionalProcessMetricsNapi = typeof napi & {
|
|
23
|
+
jsObserveGcDuration?: (kind: string, durationSeconds: number) => void;
|
|
24
|
+
jsSetEventloopHeartbeatTsMs?: (timestampMs: number) => void;
|
|
25
|
+
jsSetEventloopLagQuantile?: (
|
|
26
|
+
quantile: string,
|
|
27
|
+
valueSeconds: number,
|
|
28
|
+
) => void;
|
|
29
|
+
jsSetEventloopUtilization?: (utilization: number) => void;
|
|
30
|
+
jsAddProcessCpuSeconds?: (mode: string, valueSeconds: number) => void;
|
|
31
|
+
jsSetProcessResidentMemoryBytes?: (bytes: number) => void;
|
|
32
|
+
jsSetHeapBytes?: (kind: string, bytes: number) => void;
|
|
33
|
+
jsSetActiveHandles?: (count: number) => void;
|
|
34
|
+
jsSetActiveRequests?: (count: number) => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type GcPerformanceEntry = {
|
|
38
|
+
duration: number;
|
|
39
|
+
detail?: { kind?: number };
|
|
40
|
+
kind?: number;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const processMetricsNapi = napi as OptionalProcessMetricsNapi;
|
|
44
|
+
|
|
45
|
+
// Some napi process-metrics symbols may be missing on older native binaries
|
|
46
|
+
// (the auto-generated index.js destructures them as `undefined` if the
|
|
47
|
+
// underlying `.node` was built before they were added). Guard each call so
|
|
48
|
+
// the metrics collection runs as a no-op instead of throwing
|
|
49
|
+
// `TypeError: napi.jsXxx is not a function` on every interval tick.
|
|
50
|
+
function callIfFn<T extends unknown[]>(
|
|
51
|
+
fn: ((...args: T) => void) | undefined,
|
|
52
|
+
...args: T
|
|
53
|
+
): void {
|
|
54
|
+
if (typeof fn === "function") {
|
|
55
|
+
fn(...args);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const SCRAPE_INTERVAL_MS = 5_000;
|
|
60
|
+
const HEARTBEAT_INTERVAL_MS = 100;
|
|
61
|
+
const EVENTLOOP_DELAY_RESOLUTION_MS = 20;
|
|
62
|
+
const NS_PER_SECOND = 1e9;
|
|
63
|
+
const US_PER_SECOND = 1e6;
|
|
64
|
+
|
|
65
|
+
// V8 GC kind bitfield from Node's perf_hooks documentation. A `gc` performance
|
|
66
|
+
// entry's `kind` field is one of these values.
|
|
67
|
+
const GC_KIND_NAMES: Record<number, string> = {
|
|
68
|
+
1: "minor",
|
|
69
|
+
2: "major",
|
|
70
|
+
4: "incremental",
|
|
71
|
+
8: "weakcb",
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
interface ProcessMetricsState {
|
|
75
|
+
scrapeInterval: NodeJS.Timeout;
|
|
76
|
+
heartbeatInterval: NodeJS.Timeout;
|
|
77
|
+
gcObserver: PerformanceObserver;
|
|
78
|
+
eventLoopHistogram: ReturnType<typeof monitorEventLoopDelay>;
|
|
79
|
+
lastCpuUsage: NodeJS.CpuUsage;
|
|
80
|
+
lastEventLoopUtilization: ReturnType<
|
|
81
|
+
typeof performance.eventLoopUtilization
|
|
82
|
+
>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let state: ProcessMetricsState | undefined;
|
|
86
|
+
|
|
87
|
+
export function startProcessMetrics(): void {
|
|
88
|
+
if (state) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const eventLoopHistogram = monitorEventLoopDelay({
|
|
93
|
+
resolution: EVENTLOOP_DELAY_RESOLUTION_MS,
|
|
94
|
+
});
|
|
95
|
+
eventLoopHistogram.enable();
|
|
96
|
+
|
|
97
|
+
const gcObserver = new PerformanceObserver((list) => {
|
|
98
|
+
for (const entry of list.getEntries()) {
|
|
99
|
+
const gcEntry = entry as GcPerformanceEntry;
|
|
100
|
+
const kind = gcEntry.detail?.kind ?? gcEntry.kind;
|
|
101
|
+
if (typeof kind !== "number") continue;
|
|
102
|
+
const kindName = GC_KIND_NAMES[kind];
|
|
103
|
+
if (!kindName) continue;
|
|
104
|
+
// `entry.duration` is in milliseconds; convert to seconds.
|
|
105
|
+
callIfFn(
|
|
106
|
+
processMetricsNapi.jsObserveGcDuration,
|
|
107
|
+
kindName,
|
|
108
|
+
gcEntry.duration / 1000,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
gcObserver.observe({ entryTypes: ["gc"], buffered: false });
|
|
113
|
+
|
|
114
|
+
const lastCpuUsage = process.cpuUsage();
|
|
115
|
+
const lastEventLoopUtilization = performance.eventLoopUtilization();
|
|
116
|
+
|
|
117
|
+
const heartbeatInterval = setInterval(() => {
|
|
118
|
+
callIfFn(processMetricsNapi.jsSetEventloopHeartbeatTsMs, Date.now());
|
|
119
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
120
|
+
heartbeatInterval.unref();
|
|
121
|
+
|
|
122
|
+
const scrapeInterval = setInterval(() => {
|
|
123
|
+
try {
|
|
124
|
+
collectAndPush();
|
|
125
|
+
} catch {
|
|
126
|
+
// Collection errors must never bring down the process; metrics
|
|
127
|
+
// are best-effort.
|
|
128
|
+
}
|
|
129
|
+
}, SCRAPE_INTERVAL_MS);
|
|
130
|
+
scrapeInterval.unref();
|
|
131
|
+
|
|
132
|
+
state = {
|
|
133
|
+
scrapeInterval,
|
|
134
|
+
heartbeatInterval,
|
|
135
|
+
gcObserver,
|
|
136
|
+
eventLoopHistogram,
|
|
137
|
+
lastCpuUsage,
|
|
138
|
+
lastEventLoopUtilization,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Emit one snapshot immediately so freshly-scraped instances have data.
|
|
142
|
+
callIfFn(processMetricsNapi.jsSetEventloopHeartbeatTsMs, Date.now());
|
|
143
|
+
try {
|
|
144
|
+
collectAndPush();
|
|
145
|
+
} catch {
|
|
146
|
+
// As above; best-effort.
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function stopProcessMetrics(): void {
|
|
151
|
+
if (!state) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
clearInterval(state.scrapeInterval);
|
|
155
|
+
clearInterval(state.heartbeatInterval);
|
|
156
|
+
state.gcObserver.disconnect();
|
|
157
|
+
state.eventLoopHistogram.disable();
|
|
158
|
+
state = undefined;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function collectAndPush(): void {
|
|
162
|
+
if (!state) return;
|
|
163
|
+
|
|
164
|
+
// Event loop delay quantiles. `monitorEventLoopDelay()` reports values in
|
|
165
|
+
// nanoseconds; convert to seconds. Reset after reading so the next window
|
|
166
|
+
// reflects only the new interval.
|
|
167
|
+
const hist = state.eventLoopHistogram;
|
|
168
|
+
callIfFn(
|
|
169
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
170
|
+
"p50",
|
|
171
|
+
hist.percentile(50) / NS_PER_SECOND,
|
|
172
|
+
);
|
|
173
|
+
callIfFn(
|
|
174
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
175
|
+
"p90",
|
|
176
|
+
hist.percentile(90) / NS_PER_SECOND,
|
|
177
|
+
);
|
|
178
|
+
callIfFn(
|
|
179
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
180
|
+
"p99",
|
|
181
|
+
hist.percentile(99) / NS_PER_SECOND,
|
|
182
|
+
);
|
|
183
|
+
callIfFn(
|
|
184
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
185
|
+
"max",
|
|
186
|
+
hist.max / NS_PER_SECOND,
|
|
187
|
+
);
|
|
188
|
+
hist.reset();
|
|
189
|
+
|
|
190
|
+
// Event loop utilization delta over the scrape window.
|
|
191
|
+
const nextElu = performance.eventLoopUtilization();
|
|
192
|
+
const eluDelta = performance.eventLoopUtilization(
|
|
193
|
+
nextElu,
|
|
194
|
+
state.lastEventLoopUtilization,
|
|
195
|
+
);
|
|
196
|
+
state.lastEventLoopUtilization = nextElu;
|
|
197
|
+
callIfFn(
|
|
198
|
+
processMetricsNapi.jsSetEventloopUtilization,
|
|
199
|
+
eluDelta.utilization,
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// CPU usage delta. `process.cpuUsage()` returns microseconds.
|
|
203
|
+
const nextCpu = process.cpuUsage();
|
|
204
|
+
const userDeltaUs = nextCpu.user - state.lastCpuUsage.user;
|
|
205
|
+
const systemDeltaUs = nextCpu.system - state.lastCpuUsage.system;
|
|
206
|
+
state.lastCpuUsage = nextCpu;
|
|
207
|
+
if (userDeltaUs > 0) {
|
|
208
|
+
callIfFn(
|
|
209
|
+
processMetricsNapi.jsAddProcessCpuSeconds,
|
|
210
|
+
"user",
|
|
211
|
+
userDeltaUs / US_PER_SECOND,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
if (systemDeltaUs > 0) {
|
|
215
|
+
callIfFn(
|
|
216
|
+
processMetricsNapi.jsAddProcessCpuSeconds,
|
|
217
|
+
"system",
|
|
218
|
+
systemDeltaUs / US_PER_SECOND,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Memory + heap.
|
|
223
|
+
const mem = process.memoryUsage();
|
|
224
|
+
callIfFn(processMetricsNapi.jsSetProcessResidentMemoryBytes, mem.rss);
|
|
225
|
+
callIfFn(processMetricsNapi.jsSetHeapBytes, "used", mem.heapUsed);
|
|
226
|
+
callIfFn(processMetricsNapi.jsSetHeapBytes, "total", mem.heapTotal);
|
|
227
|
+
const heapLimit = getHeapStatistics().heap_size_limit;
|
|
228
|
+
callIfFn(processMetricsNapi.jsSetHeapBytes, "limit", heapLimit);
|
|
229
|
+
|
|
230
|
+
// libuv active handles + requests. These are unstable Node internals
|
|
231
|
+
// guarded behind underscore-prefixed names; if a future Node release
|
|
232
|
+
// removes them the try/catch above keeps the rest of the collection
|
|
233
|
+
// alive.
|
|
234
|
+
const proc = process as unknown as {
|
|
235
|
+
_getActiveHandles?: () => unknown[];
|
|
236
|
+
_getActiveRequests?: () => unknown[];
|
|
237
|
+
};
|
|
238
|
+
if (typeof proc._getActiveHandles === "function") {
|
|
239
|
+
callIfFn(
|
|
240
|
+
processMetricsNapi.jsSetActiveHandles,
|
|
241
|
+
proc._getActiveHandles().length,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
if (typeof proc._getActiveRequests === "function") {
|
|
245
|
+
callIfFn(
|
|
246
|
+
processMetricsNapi.jsSetActiveRequests,
|
|
247
|
+
proc._getActiveRequests().length,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
package/src/registry/runtime.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { stringifyError } from "@/common/utils";
|
|
1
2
|
import type { SqliteNativeMetrics } from "@/common/database/config";
|
|
2
3
|
import type { RegistryConfig } from "./config";
|
|
4
|
+
import { logger } from "./log";
|
|
3
5
|
|
|
4
6
|
declare const handleBrand: unique symbol;
|
|
5
7
|
|
|
@@ -225,6 +227,22 @@ export interface RuntimeActorConfig {
|
|
|
225
227
|
preloadMaxWorkflowBytes?: number;
|
|
226
228
|
preloadMaxConnectionsBytes?: number;
|
|
227
229
|
actions?: Array<{ name: string }>;
|
|
230
|
+
inspectorTabs?: Array<RuntimeInspectorTabEntry>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface RuntimeInspectorTabEntry {
|
|
234
|
+
id: string;
|
|
235
|
+
/** Required for custom entries; omitted for built-in hides. */
|
|
236
|
+
label?: string;
|
|
237
|
+
/**
|
|
238
|
+
* Required for custom entries — absolute path to the source directory.
|
|
239
|
+
* Resolved on the TS side before being handed to the runtime.
|
|
240
|
+
*/
|
|
241
|
+
source?: string;
|
|
242
|
+
/** Optional icon id for custom entries. */
|
|
243
|
+
icon?: string;
|
|
244
|
+
/** Set to true for built-in hide entries. */
|
|
245
|
+
hidden?: boolean;
|
|
228
246
|
}
|
|
229
247
|
|
|
230
248
|
export interface RuntimeServeConfig {
|
|
@@ -234,6 +252,8 @@ export interface RuntimeServeConfig {
|
|
|
234
252
|
namespace: string;
|
|
235
253
|
poolName: string;
|
|
236
254
|
engineBinaryPath?: string;
|
|
255
|
+
engineHost?: string;
|
|
256
|
+
enginePort?: number;
|
|
237
257
|
handleInspectorHttpInRuntime?: boolean;
|
|
238
258
|
inspectorTestToken?: string;
|
|
239
259
|
serverlessBasePath?: string;
|
|
@@ -245,6 +265,12 @@ export interface RuntimeServeConfig {
|
|
|
245
265
|
serverlessMaxStartPayloadBytes: number;
|
|
246
266
|
}
|
|
247
267
|
|
|
268
|
+
export interface RuntimeListenerConfig {
|
|
269
|
+
port: number;
|
|
270
|
+
host?: string;
|
|
271
|
+
publicDir?: string;
|
|
272
|
+
}
|
|
273
|
+
|
|
248
274
|
export interface RuntimeServerlessRequest {
|
|
249
275
|
method: string;
|
|
250
276
|
url: string;
|
|
@@ -320,6 +346,11 @@ export interface CoreRuntime {
|
|
|
320
346
|
cancelToken: CancellationTokenHandle,
|
|
321
347
|
config: RuntimeServeConfig,
|
|
322
348
|
): Promise<RuntimeServerlessResponseHead>;
|
|
349
|
+
serveListener(
|
|
350
|
+
registry: RegistryHandle,
|
|
351
|
+
listener: RuntimeListenerConfig,
|
|
352
|
+
config: RuntimeServeConfig,
|
|
353
|
+
): Promise<void>;
|
|
323
354
|
registryHealth?(
|
|
324
355
|
registry: RegistryHandle,
|
|
325
356
|
): Promise<RuntimeRegistryRouteResponse>;
|
|
@@ -399,6 +430,9 @@ export interface CoreRuntime {
|
|
|
399
430
|
): void;
|
|
400
431
|
actorWaitUntil(ctx: ActorContextHandle, promise: Promise<unknown>): void;
|
|
401
432
|
actorWaitForTrackedShutdownWork(ctx: ActorContextHandle): Promise<boolean>;
|
|
433
|
+
actorWaitForTrackedShutdownWorkUnbounded(
|
|
434
|
+
ctx: ActorContextHandle,
|
|
435
|
+
): Promise<void>;
|
|
402
436
|
actorKeepAwake(ctx: ActorContextHandle, promise: Promise<unknown>): void;
|
|
403
437
|
actorBeginKeepAwake(ctx: ActorContextHandle): number;
|
|
404
438
|
actorEndKeepAwake(ctx: ActorContextHandle, regionId: number): void;
|
|
@@ -491,6 +525,7 @@ export interface CoreRuntime {
|
|
|
491
525
|
ctx: ActorContextHandle,
|
|
492
526
|
names: string[],
|
|
493
527
|
options?: RuntimeQueueWaitOptions | undefined | null,
|
|
528
|
+
signal?: CancellationTokenHandle | undefined | null,
|
|
494
529
|
): Promise<void>;
|
|
495
530
|
actorQueueEnqueueAndWait(
|
|
496
531
|
ctx: ActorContextHandle,
|
|
@@ -577,9 +612,25 @@ export async function buildServeConfig(
|
|
|
577
612
|
serverlessMaxStartPayloadBytes: config.serverless.maxStartPayloadBytes,
|
|
578
613
|
};
|
|
579
614
|
|
|
580
|
-
|
|
615
|
+
// Always best-effort resolve the engine binary path and hand it to the core.
|
|
616
|
+
// The core alone decides whether to actually spawn a local engine, so JS must
|
|
617
|
+
// not duplicate that decision here. `loadEnginePath` throws when no binary is
|
|
618
|
+
// available (remote-only install, unsupported platform, optional deps
|
|
619
|
+
// skipped); in that case leave it unset and let the core report
|
|
620
|
+
// `engine.binary_unavailable` only if it actually needs one.
|
|
621
|
+
try {
|
|
581
622
|
serveConfig.engineBinaryPath = await loadEnginePath();
|
|
623
|
+
} catch (error) {
|
|
624
|
+
// The engine binary could not be resolved. The core still decides whether
|
|
625
|
+
// it needs to spawn a local engine; if it does, it will fail with
|
|
626
|
+
// engine.binary_unavailable (auto-download is off in the napi runtime).
|
|
627
|
+
logger().warn({
|
|
628
|
+
msg: "could not resolve a local engine binary; if a local engine must be spawned it will fail with engine.binary_unavailable — set RIVET_ENGINE_BINARY_PATH or install the @rivetkit/engine-cli platform package",
|
|
629
|
+
error: stringifyError(error),
|
|
630
|
+
});
|
|
582
631
|
}
|
|
632
|
+
serveConfig.engineHost = config.engineHost;
|
|
633
|
+
serveConfig.enginePort = config.enginePort;
|
|
583
634
|
if (config.test?.enabled) {
|
|
584
635
|
serveConfig.inspectorTestToken =
|
|
585
636
|
process.env._RIVET_TEST_INSPECTOR_TOKEN ?? "token";
|
|
@@ -26,14 +26,15 @@ import type {
|
|
|
26
26
|
RuntimeInspectorSnapshot,
|
|
27
27
|
RuntimeKvEntry,
|
|
28
28
|
RuntimeKvListOptions,
|
|
29
|
+
RuntimeListenerConfig,
|
|
29
30
|
RuntimeQueueEnqueueAndWaitOptions,
|
|
30
31
|
RuntimeQueueInspectMessage,
|
|
31
32
|
RuntimeQueueMessage,
|
|
32
33
|
RuntimeQueueNextBatchOptions,
|
|
33
34
|
RuntimeQueueTryNextBatchOptions,
|
|
34
35
|
RuntimeQueueWaitOptions,
|
|
35
|
-
RuntimeRequestSaveOpts,
|
|
36
36
|
RuntimeRegistryRouteResponse,
|
|
37
|
+
RuntimeRequestSaveOpts,
|
|
37
38
|
RuntimeServeConfig,
|
|
38
39
|
RuntimeServerlessRequest,
|
|
39
40
|
RuntimeServerlessResponseHead,
|
|
@@ -302,6 +303,16 @@ export class WasmCoreRuntime implements CoreRuntime {
|
|
|
302
303
|
);
|
|
303
304
|
}
|
|
304
305
|
|
|
306
|
+
async serveListener(
|
|
307
|
+
_registry: RegistryHandle,
|
|
308
|
+
_listener: RuntimeListenerConfig,
|
|
309
|
+
_config: RuntimeServeConfig,
|
|
310
|
+
): Promise<void> {
|
|
311
|
+
throw new Error(
|
|
312
|
+
"registry.listen() is not supported on the wasm runtime; use registry.serve() and mount the handler in your platform's HTTP server instead",
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
305
316
|
createActorFactory(
|
|
306
317
|
callbacks: object,
|
|
307
318
|
config?: RuntimeActorConfig | undefined | null,
|
|
@@ -519,6 +530,15 @@ export class WasmCoreRuntime implements CoreRuntime {
|
|
|
519
530
|
);
|
|
520
531
|
}
|
|
521
532
|
|
|
533
|
+
async actorWaitForTrackedShutdownWorkUnbounded(
|
|
534
|
+
ctx: ActorContextHandle,
|
|
535
|
+
): Promise<void> {
|
|
536
|
+
await callHandle<Promise<void>>(
|
|
537
|
+
asWasmActorContext(ctx),
|
|
538
|
+
"waitForTrackedShutdownWorkUnbounded",
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
|
|
522
542
|
actorKeepAwake(ctx: ActorContextHandle, promise: Promise<unknown>): void {
|
|
523
543
|
const wasmCtx = asWasmActorContext(ctx);
|
|
524
544
|
const regionId = callHandle<number>(wasmCtx, "beginKeepAwake");
|
|
@@ -764,9 +784,16 @@ export class WasmCoreRuntime implements CoreRuntime {
|
|
|
764
784
|
ctx: ActorContextHandle,
|
|
765
785
|
names: string[],
|
|
766
786
|
options?: RuntimeQueueWaitOptions | undefined | null,
|
|
787
|
+
signal?: CancellationTokenHandle | undefined | null,
|
|
767
788
|
): Promise<void> {
|
|
768
789
|
const queue = childHandle(asWasmActorContext(ctx), "queue");
|
|
769
|
-
await callHandleAsync(
|
|
790
|
+
await callHandleAsync(
|
|
791
|
+
queue,
|
|
792
|
+
"waitForNamesAvailable",
|
|
793
|
+
names,
|
|
794
|
+
options,
|
|
795
|
+
signal,
|
|
796
|
+
);
|
|
770
797
|
}
|
|
771
798
|
|
|
772
799
|
async actorQueueEnqueueAndWait(
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import onChange from "@rivetkit/on-change";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a proxy that tracks deep mutations on an object and calls `commit`
|
|
5
|
+
* after every change. Uses `@rivetkit/on-change` internally, which correctly
|
|
6
|
+
* detects mutations via methods on Map, Set, Date, TypedArrays, and arrays.
|
|
7
|
+
*
|
|
8
|
+
* If the value is not an object (primitive, null, undefined), it is returned
|
|
9
|
+
* as-is since primitives cannot be proxied or mutated.
|
|
10
|
+
*
|
|
11
|
+
* @param value - The root value to watch.
|
|
12
|
+
* @param commit - Called after every detected mutation with the root object.
|
|
13
|
+
* @param beforeChange - Called before every mutation with the new value being
|
|
14
|
+
* assigned. Throw to reject the change.
|
|
15
|
+
*/
|
|
16
|
+
export function createWriteThroughProxy<T>(
|
|
17
|
+
value: T,
|
|
18
|
+
commit: (next: T) => void,
|
|
19
|
+
beforeChange?: (newValue: unknown) => void,
|
|
20
|
+
): T {
|
|
21
|
+
if (!value || typeof value !== "object") {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return onChange(
|
|
26
|
+
value as T & Record<string, any>,
|
|
27
|
+
() => {
|
|
28
|
+
commit(value);
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
// Rejection is throw-based: beforeChange throws to prevent the
|
|
32
|
+
// mutation. We always return true so on-change applies the change
|
|
33
|
+
// if beforeChange did not throw.
|
|
34
|
+
onValidate(_path: string, newValue: unknown) {
|
|
35
|
+
beforeChange?.(newValue);
|
|
36
|
+
return true;
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
) as T;
|
|
40
|
+
}
|
package/src/serde.ts
CHANGED
|
@@ -2,8 +2,8 @@ import * as cbor from "cbor-x";
|
|
|
2
2
|
import invariant from "invariant";
|
|
3
3
|
import type { VersionedDataHandler } from "vbare";
|
|
4
4
|
import type { z } from "zod/v4";
|
|
5
|
+
import type { Encoding, JsonCompatValue } from "@/common/encoding";
|
|
5
6
|
import { assertUnreachable } from "@/common/utils";
|
|
6
|
-
import type { Encoding } from "@/common/encoding";
|
|
7
7
|
import {
|
|
8
8
|
encodeJsonCompatValue,
|
|
9
9
|
jsonParseCompat,
|
|
@@ -46,7 +46,7 @@ export function contentTypeForEncoding(encoding: Encoding): string {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export function encodeCborCompat(value:
|
|
49
|
+
export function encodeCborCompat(value: JsonCompatValue): Uint8Array {
|
|
50
50
|
return cbor.encode(encodeJsonCompatValue(value));
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { convertRegistryConfigToClientConfig } from "@/client/config";
|
|
2
|
+
import { stringifyError } from "@/common/utils";
|
|
2
3
|
import {
|
|
3
4
|
getDatacenters,
|
|
4
5
|
updateRunnerConfig,
|
|
5
6
|
} from "@/engine-client/api-endpoints";
|
|
6
|
-
import { stringifyError } from "@/common/utils";
|
|
7
7
|
import type { RegistryConfig } from "@/registry/config";
|
|
8
8
|
import { logger } from "@/registry/log";
|
|
9
9
|
|
|
@@ -16,11 +16,14 @@ function sleep(ms: number): Promise<void> {
|
|
|
16
16
|
|
|
17
17
|
function configureTimeoutMs() {
|
|
18
18
|
const value = process.env.RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS;
|
|
19
|
-
if (value === undefined || value === "")
|
|
19
|
+
if (value === undefined || value === "")
|
|
20
|
+
return DEFAULT_CONFIGURE_TIMEOUT_MS;
|
|
20
21
|
|
|
21
22
|
const parsed = Number(value);
|
|
22
23
|
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
23
|
-
throw new Error(
|
|
24
|
+
throw new Error(
|
|
25
|
+
"RIVET_SERVERLESS_CONFIGURE_TIMEOUT_MS must be a finite non-negative number",
|
|
26
|
+
);
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
return parsed;
|
|
@@ -40,13 +43,19 @@ export async function configureServerlessPool(
|
|
|
40
43
|
attempts += 1;
|
|
41
44
|
try {
|
|
42
45
|
if (!config.namespace) {
|
|
43
|
-
throw new Error(
|
|
46
|
+
throw new Error(
|
|
47
|
+
"namespace is required for serverless configuration",
|
|
48
|
+
);
|
|
44
49
|
}
|
|
45
50
|
if (!config.endpoint) {
|
|
46
|
-
throw new Error(
|
|
51
|
+
throw new Error(
|
|
52
|
+
"endpoint is required for serverless configuration",
|
|
53
|
+
);
|
|
47
54
|
}
|
|
48
55
|
if (!config.configurePool) {
|
|
49
|
-
throw new Error(
|
|
56
|
+
throw new Error(
|
|
57
|
+
"configurePool is required for serverless configuration",
|
|
58
|
+
);
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
const customConfig = config.configurePool;
|
|
@@ -55,7 +64,9 @@ export async function configureServerlessPool(
|
|
|
55
64
|
const poolName = customConfig.name ?? "default";
|
|
56
65
|
const serverlessToken = config.token ?? config.publicToken;
|
|
57
66
|
const headers = {
|
|
58
|
-
...(serverlessToken
|
|
67
|
+
...(serverlessToken
|
|
68
|
+
? { "x-rivet-token": serverlessToken }
|
|
69
|
+
: {}),
|
|
59
70
|
...(customConfig.headers ?? {}),
|
|
60
71
|
};
|
|
61
72
|
const serverlessConfig = {
|
package/src/test/mod.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pRetry from "p-retry";
|
|
2
2
|
import type { TestContext } from "vitest";
|
|
3
|
-
import { type Client, createClient } from "@/client/mod";
|
|
4
3
|
import { convertRegistryConfigToClientConfig } from "@/client/config";
|
|
4
|
+
import { type Client, createClient } from "@/client/mod";
|
|
5
5
|
import { getMetadata } from "@/engine-client/api-endpoints";
|
|
6
6
|
import type { Registry } from "@/registry";
|
|
7
7
|
|
|
@@ -14,13 +14,16 @@ async function waitForRegistryReady(registry: Registry<any>): Promise<void> {
|
|
|
14
14
|
registry.parseConfig(),
|
|
15
15
|
);
|
|
16
16
|
|
|
17
|
-
await pRetry(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
await pRetry(
|
|
18
|
+
async () => {
|
|
19
|
+
await getMetadata(clientConfig);
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
retries: 20,
|
|
23
|
+
minTimeout: 50,
|
|
24
|
+
maxTimeout: 250,
|
|
25
|
+
},
|
|
26
|
+
);
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
export async function setupTest<A extends Registry<any>>(
|
package/src/utils/env-vars.ts
CHANGED
|
@@ -22,6 +22,12 @@ export const getRivetTotalSlots = (): number | undefined => {
|
|
|
22
22
|
};
|
|
23
23
|
export const getRivetRunEngine = (): boolean =>
|
|
24
24
|
getEnvUniversal("RIVET_RUN_ENGINE") === "1";
|
|
25
|
+
export const getRivetRunEngineHost = (): string | undefined =>
|
|
26
|
+
getEnvUniversal("RIVET_RUN_ENGINE_HOST");
|
|
27
|
+
export const getRivetRunEnginePort = (): number | undefined => {
|
|
28
|
+
const value = getEnvUniversal("RIVET_RUN_ENGINE_PORT");
|
|
29
|
+
return value !== undefined ? parseInt(value, 10) : undefined;
|
|
30
|
+
};
|
|
25
31
|
export const getRivetRunEngineVersion = (): string | undefined =>
|
|
26
32
|
getEnvUniversal("RIVET_RUN_ENGINE_VERSION");
|
|
27
33
|
export const getRivetEnvoyKind = (): string | undefined =>
|
|
@@ -44,6 +50,37 @@ export const getRivetkitStoragePath = (): string | undefined =>
|
|
|
44
50
|
getEnvUniversal("RIVETKIT_STORAGE_PATH");
|
|
45
51
|
export const getRivetkitRuntime = (): string | undefined =>
|
|
46
52
|
getEnvUniversal("RIVETKIT_RUNTIME");
|
|
53
|
+
export type RuntimeMode = "envoy" | "serverless";
|
|
54
|
+
|
|
55
|
+
export const getRivetkitRuntimeMode = (): RuntimeMode => {
|
|
56
|
+
const value = getEnvUniversal("RIVETKIT_RUNTIME_MODE");
|
|
57
|
+
if (value === undefined) return "envoy";
|
|
58
|
+
if (value === "envoy" || value === "serverless") return value;
|
|
59
|
+
throw new Error(
|
|
60
|
+
`RIVETKIT_RUNTIME_MODE env var must be "envoy" or "serverless"; got "${value}"`,
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const getRivetkitPublicDir = (): string | undefined => {
|
|
65
|
+
const value = getEnvUniversal("RIVETKIT_PUBLIC_DIR");
|
|
66
|
+
return value === undefined || value === "" ? undefined : value;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export function parsePortEnv(raw: string | undefined): number | undefined {
|
|
70
|
+
if (raw === undefined || raw === "") return undefined;
|
|
71
|
+
const parsed = Number.parseInt(raw, 10);
|
|
72
|
+
if (
|
|
73
|
+
!Number.isFinite(parsed) ||
|
|
74
|
+
parsed < 1 ||
|
|
75
|
+
parsed > 65535 ||
|
|
76
|
+
String(parsed) !== raw.trim()
|
|
77
|
+
) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`RIVET_PORT env var must be an integer between 1 and 65535; got "${raw}"`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
return parsed;
|
|
83
|
+
}
|
|
47
84
|
|
|
48
85
|
// Logging configuration
|
|
49
86
|
// DEPRECATED: LOG_LEVEL will be removed in a future version
|
package/src/utils/router.ts
CHANGED
|
@@ -2,12 +2,12 @@ import { OpenAPIHono } from "@hono/zod-openapi";
|
|
|
2
2
|
import type { Hono } from "hono";
|
|
3
3
|
import { createMiddleware } from "hono/factory";
|
|
4
4
|
import { cors } from "@/common/cors";
|
|
5
|
+
import { getLogger } from "@/common/log";
|
|
5
6
|
import {
|
|
6
7
|
handleRouteError,
|
|
7
8
|
handleRouteNotFound,
|
|
8
9
|
loggerMiddleware,
|
|
9
10
|
} from "@/common/router";
|
|
10
|
-
import { getLogger } from "@/common/log";
|
|
11
11
|
|
|
12
12
|
export function logger() {
|
|
13
13
|
return getLogger("router");
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { stringifyError } from "@/common/utils";
|
|
2
1
|
import type { Context as HonoContext, Handler as HonoHandler } from "hono";
|
|
3
|
-
import {
|
|
2
|
+
import { stringifyError } from "@/common/utils";
|
|
4
3
|
import pkgJson from "../package.json" with { type: "json" };
|
|
5
4
|
import { getLogger } from "./common/log";
|
|
6
5
|
import { assertUnreachable } from "./common/utils";
|