rivetkit 2.3.0-rc.10 → 2.3.0-rc.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/client.d.ts +105 -56
- package/dist/browser/client.js +128 -87
- 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 +106 -66
- package/dist/tsup/agent-os/index.d.ts +106 -66
- package/dist/tsup/agent-os/index.js +2102 -2089
- package/dist/tsup/agent-os/index.js.map +1 -1
- package/dist/tsup/{chunk-4K3MV2MW.cjs → chunk-2NXFKPRB.cjs} +10 -10
- package/dist/tsup/chunk-2NXFKPRB.cjs.map +1 -0
- package/dist/tsup/{chunk-6BI2MS3S.js → chunk-3P2JUHWJ.js} +2 -2
- package/dist/tsup/{chunk-KU6VKVEK.js → chunk-4FP4FFB5.js} +18 -6
- package/dist/tsup/chunk-4FP4FFB5.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-G34LIR7S.js → chunk-GRFBV2U7.js} +22 -7
- package/dist/tsup/chunk-GRFBV2U7.js.map +1 -0
- package/dist/tsup/{chunk-PWFGP2US.cjs → chunk-GX6W4MW3.cjs} +138 -24
- package/dist/tsup/chunk-GX6W4MW3.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-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-BM3EOY7M.js → chunk-KRC4L3YB.js} +134 -20
- package/dist/tsup/chunk-KRC4L3YB.js.map +1 -0
- package/dist/tsup/{chunk-G5RULGYQ.cjs → chunk-LNP7Q6I6.cjs} +24 -9
- package/dist/tsup/chunk-LNP7Q6I6.cjs.map +1 -0
- package/dist/tsup/{chunk-Z4C3W2CQ.cjs → chunk-LW5HNCWD.cjs} +3 -3
- package/dist/tsup/{chunk-Z4C3W2CQ.cjs.map → chunk-LW5HNCWD.cjs.map} +1 -1
- package/dist/tsup/{chunk-J5P6S2LC.cjs → chunk-RDBGKI66.cjs} +25 -13
- package/dist/tsup/chunk-RDBGKI66.cjs.map +1 -0
- package/dist/tsup/{chunk-T6YVRM4K.js → chunk-T3VCJ4PV.js} +3 -1
- package/dist/tsup/chunk-T3VCJ4PV.js.map +1 -0
- package/dist/tsup/{chunk-WU2O2KIE.js → chunk-TTLUIDVH.js} +61 -77
- package/dist/tsup/chunk-TTLUIDVH.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-XV52XUWU.js → chunk-WXYWDLJY.js} +4 -4
- package/dist/tsup/chunk-WXYWDLJY.js.map +1 -0
- package/dist/tsup/{chunk-WQ4HNA4W.cjs → chunk-XCDCURZ4.cjs} +4 -2
- package/dist/tsup/chunk-XCDCURZ4.cjs.map +1 -0
- package/dist/tsup/{chunk-TE4VCDNY.cjs → chunk-XG25CGSW.cjs} +217 -233
- package/dist/tsup/chunk-XG25CGSW.cjs.map +1 -0
- package/dist/tsup/{chunk-3LGP4JSO.cjs → chunk-Y3JBOFBG.cjs} +8 -8
- package/dist/tsup/{chunk-3LGP4JSO.cjs.map → chunk-Y3JBOFBG.cjs.map} +1 -1
- package/dist/tsup/{chunk-CMYS77J6.js → chunk-YRQ4F5CD.js} +3 -3
- 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-CTwe3WwC.d.cts} +69 -19
- 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-De5UVu0V.d.ts} +69 -19
- package/dist/tsup/{context-B_IWbWne.d.ts → context-DPHISlUi.d.ts} +8 -8
- package/dist/tsup/{context-CUrQ9MHc.d.cts → context-Dmj477Uh.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 +501 -315
- 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 +405 -219
- 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 +48 -41
- package/src/actor/contexts/index.ts +7 -2
- package/src/actor/definition.ts +11 -14
- 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 +90 -54
- package/src/client/actor-conn.ts +8 -36
- package/src/client/actor-handle.ts +67 -50
- 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 +0 -149
- package/src/common/websocket-interface.ts +1 -1
- package/src/db/mod.ts +1 -1
- package/src/drivers/engine/actor-driver.ts +63 -72
- 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 +47 -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 +7 -7
- package/src/registry/index.ts +70 -71
- package/src/registry/napi-runtime.ts +7 -2
- package/src/registry/native-validation.ts +10 -12
- package/src/registry/native.ts +179 -153
- package/src/registry/process-metrics.ts +238 -0
- package/src/registry/runtime.ts +1 -3
- package/src/registry/wasm-runtime.ts +3 -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-6BI2MS3S.js.map → chunk-3P2JUHWJ.js.map} +0 -0
- /package/dist/tsup/{chunk-CMYS77J6.js.map → chunk-YRQ4F5CD.js.map} +0 -0
|
@@ -0,0 +1,238 @@
|
|
|
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?: (quantile: string, valueSeconds: number) => void;
|
|
26
|
+
jsSetEventloopUtilization?: (utilization: number) => void;
|
|
27
|
+
jsAddProcessCpuSeconds?: (mode: string, valueSeconds: number) => void;
|
|
28
|
+
jsSetProcessResidentMemoryBytes?: (bytes: number) => void;
|
|
29
|
+
jsSetHeapBytes?: (kind: string, bytes: number) => void;
|
|
30
|
+
jsSetActiveHandles?: (count: number) => void;
|
|
31
|
+
jsSetActiveRequests?: (count: number) => void;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type GcPerformanceEntry = {
|
|
35
|
+
duration: number;
|
|
36
|
+
detail?: { kind?: number };
|
|
37
|
+
kind?: number;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const processMetricsNapi = napi as OptionalProcessMetricsNapi;
|
|
41
|
+
|
|
42
|
+
// Some napi process-metrics symbols may be missing on older native binaries
|
|
43
|
+
// (the auto-generated index.js destructures them as `undefined` if the
|
|
44
|
+
// underlying `.node` was built before they were added). Guard each call so
|
|
45
|
+
// the metrics collection runs as a no-op instead of throwing
|
|
46
|
+
// `TypeError: napi.jsXxx is not a function` on every interval tick.
|
|
47
|
+
function callIfFn<T extends unknown[]>(
|
|
48
|
+
fn: ((...args: T) => void) | undefined,
|
|
49
|
+
...args: T
|
|
50
|
+
): void {
|
|
51
|
+
if (typeof fn === "function") {
|
|
52
|
+
fn(...args);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const SCRAPE_INTERVAL_MS = 5_000;
|
|
57
|
+
const HEARTBEAT_INTERVAL_MS = 100;
|
|
58
|
+
const EVENTLOOP_DELAY_RESOLUTION_MS = 20;
|
|
59
|
+
const NS_PER_SECOND = 1e9;
|
|
60
|
+
const US_PER_SECOND = 1e6;
|
|
61
|
+
|
|
62
|
+
// V8 GC kind bitfield from Node's perf_hooks documentation. A `gc` performance
|
|
63
|
+
// entry's `kind` field is one of these values.
|
|
64
|
+
const GC_KIND_NAMES: Record<number, string> = {
|
|
65
|
+
1: "minor",
|
|
66
|
+
2: "major",
|
|
67
|
+
4: "incremental",
|
|
68
|
+
8: "weakcb",
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
interface ProcessMetricsState {
|
|
72
|
+
scrapeInterval: NodeJS.Timeout;
|
|
73
|
+
heartbeatInterval: NodeJS.Timeout;
|
|
74
|
+
gcObserver: PerformanceObserver;
|
|
75
|
+
eventLoopHistogram: ReturnType<typeof monitorEventLoopDelay>;
|
|
76
|
+
lastCpuUsage: NodeJS.CpuUsage;
|
|
77
|
+
lastEventLoopUtilization: ReturnType<
|
|
78
|
+
typeof performance.eventLoopUtilization
|
|
79
|
+
>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let state: ProcessMetricsState | undefined;
|
|
83
|
+
|
|
84
|
+
export function startProcessMetrics(): void {
|
|
85
|
+
if (state) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const eventLoopHistogram = monitorEventLoopDelay({
|
|
90
|
+
resolution: EVENTLOOP_DELAY_RESOLUTION_MS,
|
|
91
|
+
});
|
|
92
|
+
eventLoopHistogram.enable();
|
|
93
|
+
|
|
94
|
+
const gcObserver = new PerformanceObserver((list) => {
|
|
95
|
+
for (const entry of list.getEntries()) {
|
|
96
|
+
const gcEntry = entry as GcPerformanceEntry;
|
|
97
|
+
const kind = gcEntry.detail?.kind ?? gcEntry.kind;
|
|
98
|
+
if (typeof kind !== "number") continue;
|
|
99
|
+
const kindName = GC_KIND_NAMES[kind];
|
|
100
|
+
if (!kindName) continue;
|
|
101
|
+
// `entry.duration` is in milliseconds; convert to seconds.
|
|
102
|
+
callIfFn(
|
|
103
|
+
processMetricsNapi.jsObserveGcDuration,
|
|
104
|
+
kindName,
|
|
105
|
+
gcEntry.duration / 1000,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
gcObserver.observe({ entryTypes: ["gc"], buffered: false });
|
|
110
|
+
|
|
111
|
+
const lastCpuUsage = process.cpuUsage();
|
|
112
|
+
const lastEventLoopUtilization = performance.eventLoopUtilization();
|
|
113
|
+
|
|
114
|
+
const heartbeatInterval = setInterval(() => {
|
|
115
|
+
callIfFn(processMetricsNapi.jsSetEventloopHeartbeatTsMs, Date.now());
|
|
116
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
117
|
+
heartbeatInterval.unref();
|
|
118
|
+
|
|
119
|
+
const scrapeInterval = setInterval(() => {
|
|
120
|
+
try {
|
|
121
|
+
collectAndPush();
|
|
122
|
+
} catch {
|
|
123
|
+
// Collection errors must never bring down the process; metrics
|
|
124
|
+
// are best-effort.
|
|
125
|
+
}
|
|
126
|
+
}, SCRAPE_INTERVAL_MS);
|
|
127
|
+
scrapeInterval.unref();
|
|
128
|
+
|
|
129
|
+
state = {
|
|
130
|
+
scrapeInterval,
|
|
131
|
+
heartbeatInterval,
|
|
132
|
+
gcObserver,
|
|
133
|
+
eventLoopHistogram,
|
|
134
|
+
lastCpuUsage,
|
|
135
|
+
lastEventLoopUtilization,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Emit one snapshot immediately so freshly-scraped instances have data.
|
|
139
|
+
callIfFn(processMetricsNapi.jsSetEventloopHeartbeatTsMs, Date.now());
|
|
140
|
+
try {
|
|
141
|
+
collectAndPush();
|
|
142
|
+
} catch {
|
|
143
|
+
// As above; best-effort.
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function stopProcessMetrics(): void {
|
|
148
|
+
if (!state) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
clearInterval(state.scrapeInterval);
|
|
152
|
+
clearInterval(state.heartbeatInterval);
|
|
153
|
+
state.gcObserver.disconnect();
|
|
154
|
+
state.eventLoopHistogram.disable();
|
|
155
|
+
state = undefined;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function collectAndPush(): void {
|
|
159
|
+
if (!state) return;
|
|
160
|
+
|
|
161
|
+
// Event loop delay quantiles. `monitorEventLoopDelay()` reports values in
|
|
162
|
+
// nanoseconds; convert to seconds. Reset after reading so the next window
|
|
163
|
+
// reflects only the new interval.
|
|
164
|
+
const hist = state.eventLoopHistogram;
|
|
165
|
+
callIfFn(
|
|
166
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
167
|
+
"p50",
|
|
168
|
+
hist.percentile(50) / NS_PER_SECOND,
|
|
169
|
+
);
|
|
170
|
+
callIfFn(
|
|
171
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
172
|
+
"p90",
|
|
173
|
+
hist.percentile(90) / NS_PER_SECOND,
|
|
174
|
+
);
|
|
175
|
+
callIfFn(
|
|
176
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
177
|
+
"p99",
|
|
178
|
+
hist.percentile(99) / NS_PER_SECOND,
|
|
179
|
+
);
|
|
180
|
+
callIfFn(
|
|
181
|
+
processMetricsNapi.jsSetEventloopLagQuantile,
|
|
182
|
+
"max",
|
|
183
|
+
hist.max / NS_PER_SECOND,
|
|
184
|
+
);
|
|
185
|
+
hist.reset();
|
|
186
|
+
|
|
187
|
+
// Event loop utilization delta over the scrape window.
|
|
188
|
+
const nextElu = performance.eventLoopUtilization();
|
|
189
|
+
const eluDelta = performance.eventLoopUtilization(
|
|
190
|
+
nextElu,
|
|
191
|
+
state.lastEventLoopUtilization,
|
|
192
|
+
);
|
|
193
|
+
state.lastEventLoopUtilization = nextElu;
|
|
194
|
+
callIfFn(processMetricsNapi.jsSetEventloopUtilization, eluDelta.utilization);
|
|
195
|
+
|
|
196
|
+
// CPU usage delta. `process.cpuUsage()` returns microseconds.
|
|
197
|
+
const nextCpu = process.cpuUsage();
|
|
198
|
+
const userDeltaUs = nextCpu.user - state.lastCpuUsage.user;
|
|
199
|
+
const systemDeltaUs = nextCpu.system - state.lastCpuUsage.system;
|
|
200
|
+
state.lastCpuUsage = nextCpu;
|
|
201
|
+
if (userDeltaUs > 0) {
|
|
202
|
+
callIfFn(
|
|
203
|
+
processMetricsNapi.jsAddProcessCpuSeconds,
|
|
204
|
+
"user",
|
|
205
|
+
userDeltaUs / US_PER_SECOND,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
if (systemDeltaUs > 0) {
|
|
209
|
+
callIfFn(
|
|
210
|
+
processMetricsNapi.jsAddProcessCpuSeconds,
|
|
211
|
+
"system",
|
|
212
|
+
systemDeltaUs / US_PER_SECOND,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Memory + heap.
|
|
217
|
+
const mem = process.memoryUsage();
|
|
218
|
+
callIfFn(processMetricsNapi.jsSetProcessResidentMemoryBytes, mem.rss);
|
|
219
|
+
callIfFn(processMetricsNapi.jsSetHeapBytes, "used", mem.heapUsed);
|
|
220
|
+
callIfFn(processMetricsNapi.jsSetHeapBytes, "total", mem.heapTotal);
|
|
221
|
+
const heapLimit = getHeapStatistics().heap_size_limit;
|
|
222
|
+
callIfFn(processMetricsNapi.jsSetHeapBytes, "limit", heapLimit);
|
|
223
|
+
|
|
224
|
+
// libuv active handles + requests. These are unstable Node internals
|
|
225
|
+
// guarded behind underscore-prefixed names; if a future Node release
|
|
226
|
+
// removes them the try/catch above keeps the rest of the collection
|
|
227
|
+
// alive.
|
|
228
|
+
const proc = process as unknown as {
|
|
229
|
+
_getActiveHandles?: () => unknown[];
|
|
230
|
+
_getActiveRequests?: () => unknown[];
|
|
231
|
+
};
|
|
232
|
+
if (typeof proc._getActiveHandles === "function") {
|
|
233
|
+
callIfFn(processMetricsNapi.jsSetActiveHandles, proc._getActiveHandles().length);
|
|
234
|
+
}
|
|
235
|
+
if (typeof proc._getActiveRequests === "function") {
|
|
236
|
+
callIfFn(processMetricsNapi.jsSetActiveRequests, proc._getActiveRequests().length);
|
|
237
|
+
}
|
|
238
|
+
}
|
package/src/registry/runtime.ts
CHANGED
|
@@ -310,9 +310,6 @@ export interface CoreRuntime {
|
|
|
310
310
|
config: RuntimeServeConfig,
|
|
311
311
|
): Promise<void>;
|
|
312
312
|
shutdownRegistry(registry: RegistryHandle): Promise<void>;
|
|
313
|
-
registryActorStopThresholdMs?(
|
|
314
|
-
registry: RegistryHandle,
|
|
315
|
-
): Promise<number | undefined>;
|
|
316
313
|
handleServerlessRequest(
|
|
317
314
|
registry: RegistryHandle,
|
|
318
315
|
req: RuntimeServerlessRequest,
|
|
@@ -491,6 +488,7 @@ export interface CoreRuntime {
|
|
|
491
488
|
ctx: ActorContextHandle,
|
|
492
489
|
names: string[],
|
|
493
490
|
options?: RuntimeQueueWaitOptions | undefined | null,
|
|
491
|
+
signal?: CancellationTokenHandle | undefined | null,
|
|
494
492
|
): Promise<void>;
|
|
495
493
|
actorQueueEnqueueAndWait(
|
|
496
494
|
ctx: ActorContextHandle,
|
|
@@ -32,8 +32,8 @@ import type {
|
|
|
32
32
|
RuntimeQueueNextBatchOptions,
|
|
33
33
|
RuntimeQueueTryNextBatchOptions,
|
|
34
34
|
RuntimeQueueWaitOptions,
|
|
35
|
-
RuntimeRequestSaveOpts,
|
|
36
35
|
RuntimeRegistryRouteResponse,
|
|
36
|
+
RuntimeRequestSaveOpts,
|
|
37
37
|
RuntimeServeConfig,
|
|
38
38
|
RuntimeServerlessRequest,
|
|
39
39
|
RuntimeServerlessResponseHead,
|
|
@@ -764,9 +764,10 @@ export class WasmCoreRuntime implements CoreRuntime {
|
|
|
764
764
|
ctx: ActorContextHandle,
|
|
765
765
|
names: string[],
|
|
766
766
|
options?: RuntimeQueueWaitOptions | undefined | null,
|
|
767
|
+
signal?: CancellationTokenHandle | undefined | null,
|
|
767
768
|
): Promise<void> {
|
|
768
769
|
const queue = childHandle(asWasmActorContext(ctx), "queue");
|
|
769
|
-
await callHandleAsync(queue, "waitForNamesAvailable", names, options);
|
|
770
|
+
await callHandleAsync(queue, "waitForNamesAvailable", names, options, signal);
|
|
770
771
|
}
|
|
771
772
|
|
|
772
773
|
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/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/serve.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { Hono } from "hono";
|
|
2
|
-
import { detectRuntime, stringifyError, type Runtime } from "../utils";
|
|
3
|
-
import { RegistryConfig } from "@/registry/config";
|
|
4
|
-
import { logger } from "@/registry/log";
|
|
5
|
-
|
|
6
1
|
// TODO: Go back to dynamic import for this
|
|
7
2
|
import getPort from "get-port";
|
|
3
|
+
import type { Hono } from "hono";
|
|
4
|
+
import type { RegistryConfig } from "@/registry/config";
|
|
5
|
+
import { logger } from "@/registry/log";
|
|
6
|
+
import { detectRuntime, type Runtime, stringifyError } from "../utils";
|
|
8
7
|
|
|
9
8
|
const DEFAULT_PORT = 6421;
|
|
10
9
|
export type ServeStatic =
|
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";
|
package/src/workflow/context.ts
CHANGED
|
@@ -1,41 +1,42 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
BranchConfig,
|
|
5
|
+
BranchOutput,
|
|
6
|
+
EntryKindType,
|
|
7
|
+
LoopConfig,
|
|
8
|
+
LoopResult,
|
|
9
|
+
StepConfig,
|
|
10
|
+
TryBlockConfig,
|
|
11
|
+
TryBlockResult,
|
|
12
|
+
TryStepConfig,
|
|
13
|
+
TryStepResult,
|
|
14
|
+
WorkflowContextInterface,
|
|
15
|
+
WorkflowQueueMessage,
|
|
16
|
+
} from "@rivetkit/workflow-engine";
|
|
3
17
|
import type {
|
|
4
18
|
QueueFilterName,
|
|
5
19
|
QueueNextBatchOptions,
|
|
6
20
|
QueueNextOptions,
|
|
7
21
|
QueueResultMessageForName,
|
|
8
22
|
} from "@/actor/config";
|
|
9
|
-
import type
|
|
10
|
-
import type { Registry } from "@/registry";
|
|
23
|
+
import { RAW_STATE_SYMBOL, type RunContext } from "@/actor/config";
|
|
11
24
|
import type {
|
|
12
|
-
BaseActorDefinition,
|
|
13
25
|
AnyActorDefinition,
|
|
26
|
+
BaseActorDefinition,
|
|
14
27
|
} from "@/actor/definition";
|
|
15
|
-
import type {
|
|
16
|
-
AnyDatabaseProvider,
|
|
17
|
-
InferDatabaseClient,
|
|
18
|
-
} from "@/common/database/config";
|
|
19
28
|
import type {
|
|
20
29
|
EventSchemaConfig,
|
|
21
30
|
InferEventArgs,
|
|
22
31
|
InferSchemaMap,
|
|
23
32
|
QueueSchemaConfig,
|
|
24
33
|
} from "@/actor/schema";
|
|
25
|
-
import type {
|
|
34
|
+
import type { Client } from "@/client/client";
|
|
26
35
|
import type {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
LoopResult,
|
|
32
|
-
StepConfig,
|
|
33
|
-
TryBlockConfig,
|
|
34
|
-
TryBlockResult,
|
|
35
|
-
TryStepConfig,
|
|
36
|
-
TryStepResult,
|
|
37
|
-
WorkflowQueueMessage,
|
|
38
|
-
} from "@rivetkit/workflow-engine";
|
|
36
|
+
AnyDatabaseProvider,
|
|
37
|
+
InferDatabaseClient,
|
|
38
|
+
} from "@/common/database/config";
|
|
39
|
+
import type { Registry } from "@/registry";
|
|
39
40
|
import { WORKFLOW_GUARD_KV_KEY } from "./constants";
|
|
40
41
|
|
|
41
42
|
type WorkflowActorQueueNextOptions<
|
|
@@ -80,7 +81,9 @@ type ActorWorkflowLoopConfig<
|
|
|
80
81
|
TQueues
|
|
81
82
|
>,
|
|
82
83
|
state: S,
|
|
83
|
-
) => Promise<
|
|
84
|
+
) => Promise<
|
|
85
|
+
LoopResult<S, T> | (S extends undefined ? undefined | void : never)
|
|
86
|
+
>;
|
|
84
87
|
};
|
|
85
88
|
|
|
86
89
|
type ActorWorkflowBranchConfig<
|
|
@@ -238,7 +241,7 @@ export class ActorWorkflowContext<
|
|
|
238
241
|
}
|
|
239
242
|
|
|
240
243
|
async step<T>(
|
|
241
|
-
nameOrConfig: string |
|
|
244
|
+
nameOrConfig: string | StepConfig<T>,
|
|
242
245
|
run?: () => Promise<T>,
|
|
243
246
|
): Promise<T> {
|
|
244
247
|
if (typeof nameOrConfig === "string") {
|
|
@@ -247,22 +250,20 @@ export class ActorWorkflowContext<
|
|
|
247
250
|
}
|
|
248
251
|
return await this.#wrapActive(() =>
|
|
249
252
|
this.#inner.step(nameOrConfig, () =>
|
|
250
|
-
this.#
|
|
253
|
+
this.#withActorAccessAndStateRollback(run),
|
|
251
254
|
),
|
|
252
255
|
);
|
|
253
256
|
}
|
|
254
257
|
const stepConfig = nameOrConfig as StepConfig<T>;
|
|
255
258
|
const config: StepConfig<T> = {
|
|
256
259
|
...stepConfig,
|
|
257
|
-
run: () => this.#
|
|
260
|
+
run: () => this.#withActorAccessAndStateRollback(stepConfig.run),
|
|
258
261
|
};
|
|
259
262
|
return await this.#wrapActive(() => this.#inner.step(config));
|
|
260
263
|
}
|
|
261
264
|
|
|
262
265
|
async tryStep<T>(
|
|
263
|
-
nameOrConfig:
|
|
264
|
-
| string
|
|
265
|
-
| Parameters<WorkflowContextInterface["tryStep"]>[0],
|
|
266
|
+
nameOrConfig: string | TryStepConfig<T>,
|
|
266
267
|
run?: () => Promise<T>,
|
|
267
268
|
): Promise<TryStepResult<T>> {
|
|
268
269
|
if (typeof nameOrConfig === "string") {
|
|
@@ -271,14 +272,14 @@ export class ActorWorkflowContext<
|
|
|
271
272
|
}
|
|
272
273
|
return await this.#wrapActive(() =>
|
|
273
274
|
this.#inner.tryStep(nameOrConfig, () =>
|
|
274
|
-
this.#
|
|
275
|
+
this.#withActorAccessAndStateRollback(run),
|
|
275
276
|
),
|
|
276
277
|
);
|
|
277
278
|
}
|
|
278
279
|
const stepConfig = nameOrConfig as TryStepConfig<T>;
|
|
279
280
|
const config: TryStepConfig<T> = {
|
|
280
281
|
...stepConfig,
|
|
281
|
-
run: () => this.#
|
|
282
|
+
run: () => this.#withActorAccessAndStateRollback(stepConfig.run),
|
|
282
283
|
};
|
|
283
284
|
return await this.#wrapActive(() => this.#inner.tryStep(config));
|
|
284
285
|
}
|
|
@@ -329,13 +330,13 @@ export class ActorWorkflowContext<
|
|
|
329
330
|
TEvents,
|
|
330
331
|
TQueues
|
|
331
332
|
>,
|
|
332
|
-
) => Promise<LoopResult<undefined, T> | void>,
|
|
333
|
+
) => Promise<LoopResult<undefined, T> | undefined | void>,
|
|
333
334
|
): Promise<T>;
|
|
334
335
|
async loop<T>(
|
|
335
336
|
name: string,
|
|
336
337
|
run: (
|
|
337
338
|
ctx: WorkflowContextInterface,
|
|
338
|
-
) => Promise<LoopResult<undefined, T> | void>,
|
|
339
|
+
) => Promise<LoopResult<undefined, T> | undefined | void>,
|
|
339
340
|
): Promise<T>;
|
|
340
341
|
async loop<S, T>(
|
|
341
342
|
config: ActorWorkflowLoopConfig<
|
|
@@ -379,7 +380,7 @@ export class ActorWorkflowContext<
|
|
|
379
380
|
TEvents,
|
|
380
381
|
TQueues
|
|
381
382
|
>,
|
|
382
|
-
) => Promise<LoopResult<undefined, any> | void>,
|
|
383
|
+
) => Promise<LoopResult<undefined, any> | undefined | void>,
|
|
383
384
|
): Promise<any> {
|
|
384
385
|
if (typeof nameOrConfig === "string") {
|
|
385
386
|
if (!run) {
|
|
@@ -612,6 +613,33 @@ export class ActorWorkflowContext<
|
|
|
612
613
|
}
|
|
613
614
|
}
|
|
614
615
|
|
|
616
|
+
async #withActorAccessAndStateRollback<T>(
|
|
617
|
+
run: () => Promise<T>,
|
|
618
|
+
): Promise<T> {
|
|
619
|
+
let stateSnapshot: { state: TState } | null = null;
|
|
620
|
+
try {
|
|
621
|
+
stateSnapshot = { state: this.#runCtx[RAW_STATE_SYMBOL]() };
|
|
622
|
+
} catch (error) {
|
|
623
|
+
this.#runCtx.log.debug({
|
|
624
|
+
msg: "failed to get state, likely due to being stateless workflow",
|
|
625
|
+
error,
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
if (stateSnapshot) {
|
|
629
|
+
stateSnapshot.state = structuredClone(stateSnapshot.state);
|
|
630
|
+
}
|
|
631
|
+
const varsSnapshot = structuredClone(this.#runCtx.vars);
|
|
632
|
+
try {
|
|
633
|
+
return await this.#withActorAccess(run);
|
|
634
|
+
} catch (error) {
|
|
635
|
+
if (stateSnapshot) {
|
|
636
|
+
this.#runCtx.state = stateSnapshot.state;
|
|
637
|
+
}
|
|
638
|
+
this.#runCtx.vars = varsSnapshot;
|
|
639
|
+
throw error;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
615
643
|
#ensureActorAccess(feature: string): void {
|
|
616
644
|
if (!this.#allowActorAccess) {
|
|
617
645
|
this.#guardViolation = true;
|
package/src/workflow/driver.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
AnyActorInstance,
|
|
5
|
-
AnyStaticActorInstance,
|
|
6
|
-
} from "@/actor/definition";
|
|
7
|
-
import { makeWorkflowKey, workflowStoragePrefix } from "@/actor/keys";
|
|
2
|
+
|
|
8
3
|
import type {
|
|
9
4
|
EngineDriver,
|
|
10
5
|
KVEntry,
|
|
@@ -12,6 +7,9 @@ import type {
|
|
|
12
7
|
Message,
|
|
13
8
|
WorkflowMessageDriver,
|
|
14
9
|
} from "@rivetkit/workflow-engine";
|
|
10
|
+
import type { RunContext } from "@/actor/config";
|
|
11
|
+
import type { AnyStaticActorInstance } from "@/actor/definition";
|
|
12
|
+
import { makeWorkflowKey, workflowStoragePrefix } from "@/actor/keys";
|
|
15
13
|
|
|
16
14
|
const WORKFLOW_STORAGE_PREFIX = workflowStoragePrefix();
|
|
17
15
|
|