rivetkit 2.3.0-rc.5 → 2.3.0-rc.7
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 +35 -3
- package/dist/browser/client.js +795 -200
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +4 -3
- 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 -74
- package/dist/tsup/actor/errors.d.ts +1 -74
- package/dist/tsup/actor/errors.js +3 -1
- package/dist/tsup/agent-os/index.cjs +7 -5
- package/dist/tsup/agent-os/index.cjs.map +1 -1
- package/dist/tsup/agent-os/index.d.cts +35 -3
- package/dist/tsup/agent-os/index.d.ts +35 -3
- package/dist/tsup/agent-os/index.js +7 -5
- package/dist/tsup/agent-os/index.js.map +1 -1
- package/dist/tsup/{chunk-2GANBXVP.cjs → chunk-2H4ISA4Y.cjs} +10 -10
- package/dist/tsup/chunk-2H4ISA4Y.cjs.map +1 -0
- package/dist/tsup/{chunk-UXTP4EBU.js → chunk-4DJMFOSU.js} +2 -2
- package/dist/tsup/{chunk-LDTT6WKJ.js → chunk-4LTY5TOO.js} +132 -4
- package/dist/tsup/chunk-4LTY5TOO.js.map +1 -0
- package/dist/tsup/{chunk-PGYEMIOE.js → chunk-52TPEKEC.js} +2 -2
- package/dist/tsup/{chunk-OVJX4IFY.cjs → chunk-55E7IR6D.cjs} +4 -4
- package/dist/tsup/{chunk-OVJX4IFY.cjs.map → chunk-55E7IR6D.cjs.map} +1 -1
- package/dist/tsup/{chunk-V3QNBJ7N.cjs → chunk-63WNTDRC.cjs} +31 -10
- package/dist/tsup/chunk-63WNTDRC.cjs.map +1 -0
- package/dist/tsup/{chunk-SULB574D.js → chunk-CMV6N5OX.js} +3 -3
- package/dist/tsup/{chunk-T6YVRM4K.js → chunk-D5G75T7J.js} +3 -1
- package/dist/tsup/chunk-D5G75T7J.js.map +1 -0
- package/dist/tsup/{chunk-NW2J4SOL.cjs → chunk-FEOG44WH.cjs} +137 -9
- package/dist/tsup/chunk-FEOG44WH.cjs.map +1 -0
- package/dist/tsup/{chunk-HR547GVH.cjs → chunk-G5HUSWP4.cjs} +8 -8
- package/dist/tsup/{chunk-HR547GVH.cjs.map → chunk-G5HUSWP4.cjs.map} +1 -1
- package/dist/tsup/{chunk-N2DQSJIW.js → chunk-HERL2VQ2.js} +17 -48
- package/dist/tsup/chunk-HERL2VQ2.js.map +1 -0
- package/dist/tsup/{chunk-LELRJK66.cjs → chunk-SJLPZEA3.cjs} +3 -3
- package/dist/tsup/{chunk-LELRJK66.cjs.map → chunk-SJLPZEA3.cjs.map} +1 -1
- package/dist/tsup/{chunk-WQ4HNA4W.cjs → chunk-SRNOPUC6.cjs} +4 -2
- package/dist/tsup/chunk-SRNOPUC6.cjs.map +1 -0
- package/dist/tsup/{chunk-K34B3OVG.js → chunk-TMLOKTRB.js} +30 -9
- package/dist/tsup/chunk-TMLOKTRB.js.map +1 -0
- package/dist/tsup/{chunk-NATOT3ET.js → chunk-VFIY6GWO.js} +4 -4
- package/dist/tsup/chunk-VFIY6GWO.js.map +1 -0
- package/dist/tsup/{chunk-JY73X7VU.js → chunk-VJ4Y4WBT.js} +692 -114
- package/dist/tsup/chunk-VJ4Y4WBT.js.map +1 -0
- package/dist/tsup/{chunk-JRCZDHXT.cjs → chunk-X6HIFXNK.cjs} +23 -54
- package/dist/tsup/chunk-X6HIFXNK.cjs.map +1 -0
- package/dist/tsup/{chunk-FTZIZ3JG.cjs → chunk-ZGPX6KAH.cjs} +838 -260
- package/dist/tsup/chunk-ZGPX6KAH.cjs.map +1 -0
- package/dist/tsup/client/mod.cjs +7 -7
- package/dist/tsup/client/mod.d.cts +3 -4
- package/dist/tsup/client/mod.d.ts +3 -4
- package/dist/tsup/client/mod.js +6 -6
- 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-CvQUtDp9.d.ts → config-Ak1lv4gF.d.ts} +27 -5
- package/dist/tsup/{config-C-a9vrke.d.cts → config-DU_xj4qZ.d.cts} +27 -5
- package/dist/tsup/{context-A7R0bsZL.d.ts → context-DAAp4Lpg.d.ts} +1 -1
- package/dist/tsup/{context-CA3r-pf2.d.cts → context-Dt_L55q8.d.cts} +1 -1
- package/dist/tsup/inspector/mod.cjs +6 -6
- package/dist/tsup/inspector/mod.js +5 -5
- package/dist/tsup/mod.cjs +507 -308
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +4 -5
- package/dist/tsup/mod.d.ts +4 -5
- package/dist/tsup/mod.js +432 -233
- package/dist/tsup/mod.js.map +1 -1
- package/dist/tsup/process-metrics-NW754INA.js +118 -0
- package/dist/tsup/process-metrics-NW754INA.js.map +1 -0
- package/dist/tsup/process-metrics-TYAGKCEJ.cjs +118 -0
- package/dist/tsup/process-metrics-TYAGKCEJ.cjs.map +1 -0
- package/dist/tsup/test/mod.cjs +10 -10
- package/dist/tsup/test/mod.d.cts +2 -3
- package/dist/tsup/test/mod.d.ts +2 -3
- package/dist/tsup/test/mod.js +6 -6
- package/dist/tsup/utils-DVekpm4I.d.cts +103 -0
- package/dist/tsup/utils-DVekpm4I.d.ts +103 -0
- 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 +41 -16
- package/dist/tsup/workflow/mod.cjs.map +1 -1
- package/dist/tsup/workflow/mod.d.cts +4 -5
- package/dist/tsup/workflow/mod.d.ts +4 -5
- package/dist/tsup/workflow/mod.js +35 -10
- package/dist/tsup/workflow/mod.js.map +1 -1
- package/package.json +11 -10
- package/src/actor/config.ts +3 -0
- package/src/actor/errors.ts +53 -7
- package/src/agent-os/actor/session.ts +2 -2
- package/src/client/actor-conn.ts +55 -60
- package/src/client/actor-handle.ts +59 -24
- package/src/client/errors.ts +2 -1
- package/src/client/queue.ts +2 -1
- package/src/client/raw-utils.ts +2 -4
- package/src/client/utils.ts +32 -4
- package/src/common/actor-router-consts.ts +4 -0
- package/src/common/bare/generated/client-protocol/v4.ts +599 -0
- package/src/common/client-protocol-versioned.ts +125 -18
- package/src/common/client-protocol-zod.ts +7 -0
- package/src/common/client-protocol.ts +1 -1
- package/src/common/database/native-database.test.ts +35 -0
- package/src/common/database/native-database.ts +8 -4
- package/src/common/encoding.ts +243 -5
- package/src/common/inline-websocket-adapter.ts +12 -12
- package/src/common/log.ts +1 -0
- package/src/common/router.ts +40 -10
- package/src/common/utils.ts +9 -200
- package/src/drivers/engine/actor-driver.ts +29 -28
- package/src/engine-client/actor-websocket-client.ts +2 -1
- package/src/engine-client/mod.ts +3 -2
- package/src/registry/config/index.ts +3 -5
- package/src/registry/index.ts +90 -16
- package/src/registry/napi-runtime.ts +15 -0
- package/src/registry/native.ts +197 -255
- package/src/registry/process-metrics.ts +183 -0
- package/src/registry/runtime.ts +4 -0
- package/src/registry/wasm-runtime.ts +9 -0
- package/src/registry/write-through-proxy.ts +40 -0
- package/src/serde.ts +2 -2
- package/src/workflow/context.ts +32 -5
- package/src/workflow/inspector.ts +2 -1
- package/dist/tsup/chunk-2GANBXVP.cjs.map +0 -1
- package/dist/tsup/chunk-FTZIZ3JG.cjs.map +0 -1
- package/dist/tsup/chunk-JRCZDHXT.cjs.map +0 -1
- package/dist/tsup/chunk-JY73X7VU.js.map +0 -1
- package/dist/tsup/chunk-K34B3OVG.js.map +0 -1
- package/dist/tsup/chunk-LDTT6WKJ.js.map +0 -1
- package/dist/tsup/chunk-N2DQSJIW.js.map +0 -1
- package/dist/tsup/chunk-NATOT3ET.js.map +0 -1
- package/dist/tsup/chunk-NW2J4SOL.cjs.map +0 -1
- package/dist/tsup/chunk-T6YVRM4K.js.map +0 -1
- package/dist/tsup/chunk-V3QNBJ7N.cjs.map +0 -1
- package/dist/tsup/chunk-WQ4HNA4W.cjs.map +0 -1
- package/dist/tsup/utils-fwx3o3K9.d.cts +0 -18
- package/dist/tsup/utils-fwx3o3K9.d.ts +0 -18
- /package/dist/tsup/{chunk-UXTP4EBU.js.map → chunk-4DJMFOSU.js.map} +0 -0
- /package/dist/tsup/{chunk-PGYEMIOE.js.map → chunk-52TPEKEC.js.map} +0 -0
- /package/dist/tsup/{chunk-SULB574D.js.map → chunk-CMV6N5OX.js.map} +0 -0
package/src/common/utils.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { Next } from "hono";
|
|
2
2
|
import type { ContentfulStatusCode } from "hono/utils/http-status";
|
|
3
3
|
import * as errors from "@/actor/errors";
|
|
4
|
-
import { EXTRA_ERROR_LOG } from "@/utils";
|
|
5
4
|
import { getLogErrorStack } from "@/utils/env-vars";
|
|
6
|
-
import type { Logger } from "./log";
|
|
7
5
|
|
|
8
6
|
export function assertUnreachable(x: never): never {
|
|
9
7
|
throw new Error(`Unreachable case: ${x}`);
|
|
@@ -38,154 +36,6 @@ export function safeStringify(obj: unknown, maxSize: number) {
|
|
|
38
36
|
return JSON.stringify(obj, replacer);
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
// TODO: Instead of doing this, use a temp var for state and attempt to write
|
|
42
|
-
// it. Roll back state if fails to serialize.
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Check if a value is CBOR serializable.
|
|
46
|
-
* Optionally pass an onInvalid callback to receive the path to invalid values.
|
|
47
|
-
*
|
|
48
|
-
* For a complete list of supported CBOR tags, see:
|
|
49
|
-
* https://github.com/kriszyp/cbor-x/blob/cc1cf9df8ba72288c7842af1dd374d73e34cdbc1/README.md#list-of-supported-tags-for-decoding
|
|
50
|
-
*/
|
|
51
|
-
export function isCborSerializable(
|
|
52
|
-
value: unknown,
|
|
53
|
-
onInvalid?: (path: string) => void,
|
|
54
|
-
currentPath = "",
|
|
55
|
-
): boolean {
|
|
56
|
-
// Handle primitive types directly
|
|
57
|
-
if (value === null || value === undefined) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (typeof value === "number") {
|
|
62
|
-
if (!Number.isFinite(value)) {
|
|
63
|
-
onInvalid?.(currentPath);
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (typeof value === "boolean" || typeof value === "string") {
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Handle BigInt (CBOR tags 2 and 3)
|
|
74
|
-
if (typeof value === "bigint") {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Handle Date objects (CBOR tags 0 and 1)
|
|
79
|
-
if (value instanceof Date) {
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Handle typed arrays (CBOR tags 64-82)
|
|
84
|
-
if (
|
|
85
|
-
value instanceof Uint8Array ||
|
|
86
|
-
value instanceof Uint8ClampedArray ||
|
|
87
|
-
value instanceof Uint16Array ||
|
|
88
|
-
value instanceof Uint32Array ||
|
|
89
|
-
value instanceof BigUint64Array ||
|
|
90
|
-
value instanceof Int8Array ||
|
|
91
|
-
value instanceof Int16Array ||
|
|
92
|
-
value instanceof Int32Array ||
|
|
93
|
-
value instanceof BigInt64Array ||
|
|
94
|
-
value instanceof Float32Array ||
|
|
95
|
-
value instanceof Float64Array
|
|
96
|
-
) {
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Handle Map (CBOR tag 259)
|
|
101
|
-
if (value instanceof Map) {
|
|
102
|
-
for (const [key, val] of value.entries()) {
|
|
103
|
-
const keyPath = currentPath
|
|
104
|
-
? `${currentPath}.key(${String(key)})`
|
|
105
|
-
: `key(${String(key)})`;
|
|
106
|
-
const valPath = currentPath
|
|
107
|
-
? `${currentPath}.value(${String(key)})`
|
|
108
|
-
: `value(${String(key)})`;
|
|
109
|
-
if (
|
|
110
|
-
!isCborSerializable(key, onInvalid, keyPath) ||
|
|
111
|
-
!isCborSerializable(val, onInvalid, valPath)
|
|
112
|
-
) {
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Handle Set (CBOR tag 258)
|
|
120
|
-
if (value instanceof Set) {
|
|
121
|
-
let index = 0;
|
|
122
|
-
for (const item of value.values()) {
|
|
123
|
-
const itemPath = currentPath
|
|
124
|
-
? `${currentPath}.set[${index}]`
|
|
125
|
-
: `set[${index}]`;
|
|
126
|
-
if (!isCborSerializable(item, onInvalid, itemPath)) {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
index++;
|
|
130
|
-
}
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Handle RegExp (CBOR tag 27)
|
|
135
|
-
if (value instanceof RegExp) {
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Handle Error objects (CBOR tag 27)
|
|
140
|
-
if (value instanceof Error) {
|
|
141
|
-
return true;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Handle arrays
|
|
145
|
-
if (Array.isArray(value)) {
|
|
146
|
-
for (let i = 0; i < value.length; i++) {
|
|
147
|
-
const itemPath = currentPath ? `${currentPath}[${i}]` : `[${i}]`;
|
|
148
|
-
if (!isCborSerializable(value[i], onInvalid, itemPath)) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Handle plain objects and records (CBOR tags 105, 51, 57344-57599)
|
|
156
|
-
if (typeof value === "object") {
|
|
157
|
-
// Allow plain objects and objects with prototypes (for records and named objects)
|
|
158
|
-
const proto = Object.getPrototypeOf(value);
|
|
159
|
-
if (proto !== null && proto !== Object.prototype) {
|
|
160
|
-
// Check if it's a known serializable object type
|
|
161
|
-
const protoConstructor = value.constructor;
|
|
162
|
-
if (protoConstructor && typeof protoConstructor.name === "string") {
|
|
163
|
-
// Allow objects with named constructors (records, named objects)
|
|
164
|
-
// This includes user-defined classes and built-in objects
|
|
165
|
-
// that CBOR can serialize with tag 27 or record tags
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Check all properties recursively
|
|
170
|
-
for (const key in value) {
|
|
171
|
-
const propPath = currentPath ? `${currentPath}.${key}` : key;
|
|
172
|
-
if (
|
|
173
|
-
!isCborSerializable(
|
|
174
|
-
value[key as keyof typeof value],
|
|
175
|
-
onInvalid,
|
|
176
|
-
propPath,
|
|
177
|
-
)
|
|
178
|
-
) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Not serializable
|
|
186
|
-
onInvalid?.(currentPath);
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
39
|
|
|
190
40
|
export interface DeconstructedError {
|
|
191
41
|
__type: "ActorError";
|
|
@@ -195,6 +45,7 @@ export interface DeconstructedError {
|
|
|
195
45
|
code: string;
|
|
196
46
|
message: string;
|
|
197
47
|
metadata?: unknown;
|
|
48
|
+
actor?: errors.ActorSpecifier;
|
|
198
49
|
}
|
|
199
50
|
|
|
200
51
|
function isCanonicalStructuredRivetError(
|
|
@@ -221,19 +72,16 @@ function isCanonicalStructuredRivetError(
|
|
|
221
72
|
*/
|
|
222
73
|
export function deconstructError(
|
|
223
74
|
error: unknown,
|
|
224
|
-
logger: Logger,
|
|
225
|
-
extraLog: Record<string, unknown>,
|
|
226
75
|
exposeInternalError = false,
|
|
227
76
|
): DeconstructedError {
|
|
228
77
|
// Build response error information. Only return errors if flagged as public in order to prevent leaking internal behavior.
|
|
229
|
-
//
|
|
230
|
-
// We log the error here instead of after generating the code & message because we need to log the original error, not the masked internal error.
|
|
231
78
|
let statusCode: ContentfulStatusCode;
|
|
232
79
|
let public_: boolean;
|
|
233
80
|
let group: string;
|
|
234
81
|
let code: string;
|
|
235
82
|
let message: string;
|
|
236
83
|
let metadata: unknown;
|
|
84
|
+
let actor: errors.ActorSpecifier | undefined;
|
|
237
85
|
// Structured errors from core or from pre-built `RivetError` instances are canonical.
|
|
238
86
|
// Only unstructured errors go through the classifier below.
|
|
239
87
|
if (isCanonicalStructuredRivetError(error)) {
|
|
@@ -249,15 +97,7 @@ export function deconstructError(
|
|
|
249
97
|
code = error.code;
|
|
250
98
|
message = error.message;
|
|
251
99
|
metadata = error.metadata;
|
|
252
|
-
|
|
253
|
-
logger.info({
|
|
254
|
-
msg: "structured error passthrough",
|
|
255
|
-
group,
|
|
256
|
-
code,
|
|
257
|
-
message,
|
|
258
|
-
...EXTRA_ERROR_LOG,
|
|
259
|
-
...extraLog,
|
|
260
|
-
});
|
|
100
|
+
actor = error.actor;
|
|
261
101
|
} else if (errors.ActorError.isActorError(error) && error.public) {
|
|
262
102
|
// Check if error has statusCode (could be ActorError instance or DeconstructedError)
|
|
263
103
|
statusCode = (
|
|
@@ -268,15 +108,7 @@ export function deconstructError(
|
|
|
268
108
|
code = error.code;
|
|
269
109
|
message = getErrorMessage(error);
|
|
270
110
|
metadata = error.metadata;
|
|
271
|
-
|
|
272
|
-
logger.info({
|
|
273
|
-
msg: "public error",
|
|
274
|
-
group,
|
|
275
|
-
code,
|
|
276
|
-
message,
|
|
277
|
-
...EXTRA_ERROR_LOG,
|
|
278
|
-
...extraLog,
|
|
279
|
-
});
|
|
111
|
+
actor = error.actor;
|
|
280
112
|
} else if (exposeInternalError) {
|
|
281
113
|
if (errors.ActorError.isActorError(error)) {
|
|
282
114
|
statusCode = 500;
|
|
@@ -285,32 +117,13 @@ export function deconstructError(
|
|
|
285
117
|
code = error.code;
|
|
286
118
|
message = getErrorMessage(error);
|
|
287
119
|
metadata = error.metadata;
|
|
288
|
-
|
|
289
|
-
logger.info({
|
|
290
|
-
msg: "internal error",
|
|
291
|
-
group,
|
|
292
|
-
code,
|
|
293
|
-
message,
|
|
294
|
-
stack: (error as Error)?.stack,
|
|
295
|
-
...EXTRA_ERROR_LOG,
|
|
296
|
-
...extraLog,
|
|
297
|
-
});
|
|
120
|
+
actor = error.actor;
|
|
298
121
|
} else {
|
|
299
122
|
statusCode = 500;
|
|
300
123
|
public_ = false;
|
|
301
124
|
group = "rivetkit";
|
|
302
125
|
code = errors.INTERNAL_ERROR_CODE;
|
|
303
126
|
message = getErrorMessage(error);
|
|
304
|
-
|
|
305
|
-
logger.info({
|
|
306
|
-
msg: "internal error",
|
|
307
|
-
group,
|
|
308
|
-
code,
|
|
309
|
-
message,
|
|
310
|
-
stack: (error as Error)?.stack,
|
|
311
|
-
...EXTRA_ERROR_LOG,
|
|
312
|
-
...extraLog,
|
|
313
|
-
});
|
|
314
127
|
}
|
|
315
128
|
} else {
|
|
316
129
|
statusCode = 500;
|
|
@@ -318,17 +131,12 @@ export function deconstructError(
|
|
|
318
131
|
group = "rivetkit";
|
|
319
132
|
code = errors.INTERNAL_ERROR_CODE;
|
|
320
133
|
message = errors.INTERNAL_ERROR_DESCRIPTION;
|
|
134
|
+
if (errors.ActorError.isActorError(error)) {
|
|
135
|
+
actor = error.actor;
|
|
136
|
+
}
|
|
321
137
|
metadata = {
|
|
322
138
|
//url: `https://hub.rivet.dev/projects/${actorMetadata.project.slug}/environments/${actorMetadata.environment.slug}/actors?actorId=${actorMetadata.actor.id}`,
|
|
323
139
|
} satisfies errors.InternalErrorMetadata;
|
|
324
|
-
|
|
325
|
-
logger.warn({
|
|
326
|
-
msg: "internal error",
|
|
327
|
-
error: getErrorMessage(error),
|
|
328
|
-
stack: (error as Error)?.stack,
|
|
329
|
-
...EXTRA_ERROR_LOG,
|
|
330
|
-
...extraLog,
|
|
331
|
-
});
|
|
332
140
|
}
|
|
333
141
|
|
|
334
142
|
return {
|
|
@@ -339,6 +147,7 @@ export function deconstructError(
|
|
|
339
147
|
code,
|
|
340
148
|
message,
|
|
341
149
|
metadata,
|
|
150
|
+
actor,
|
|
342
151
|
};
|
|
343
152
|
}
|
|
344
153
|
|
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
import { logger } from "./log";
|
|
79
79
|
|
|
80
80
|
const ENVOY_SSE_PING_INTERVAL = 1000;
|
|
81
|
-
const
|
|
81
|
+
const FALLBACK_ENVOY_STOP_WAIT_MS = 15_000;
|
|
82
82
|
const INITIAL_SLEEP_TIMEOUT_MS = 250;
|
|
83
83
|
const REMOTE_ACK_HOOK_QUERY_PARAM = "__rivetkitAckHook";
|
|
84
84
|
|
|
@@ -284,7 +284,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
284
284
|
logger().debug({
|
|
285
285
|
msg: "actor crash cleanup errored",
|
|
286
286
|
actorId,
|
|
287
|
-
|
|
287
|
+
error: stringifyError(err),
|
|
288
288
|
});
|
|
289
289
|
}
|
|
290
290
|
}
|
|
@@ -847,6 +847,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
847
847
|
return;
|
|
848
848
|
}
|
|
849
849
|
this.#isShuttingDown = true;
|
|
850
|
+
const envoyStopWaitMs = this.#envoyStopWaitMs();
|
|
850
851
|
|
|
851
852
|
logger().info({ msg: "stopping engine actor driver", immediate });
|
|
852
853
|
if (!immediate) {
|
|
@@ -861,7 +862,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
861
862
|
this.startSleep(actorId);
|
|
862
863
|
}
|
|
863
864
|
|
|
864
|
-
const actorSleepDeadline = Date.now() +
|
|
865
|
+
const actorSleepDeadline = Date.now() + envoyStopWaitMs;
|
|
865
866
|
while (this.#actors.size > 0 && Date.now() < actorSleepDeadline) {
|
|
866
867
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
867
868
|
}
|
|
@@ -870,7 +871,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
870
871
|
logger().warn({
|
|
871
872
|
msg: "timed out waiting for actors to stop before envoy drain",
|
|
872
873
|
remainingActors: this.#actors.size,
|
|
873
|
-
waitMs:
|
|
874
|
+
waitMs: envoyStopWaitMs,
|
|
874
875
|
});
|
|
875
876
|
// Snapshot so concurrent removals from `stopActor` do not
|
|
876
877
|
// invalidate the iterator.
|
|
@@ -912,13 +913,13 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
912
913
|
const stopped = await Promise.race([
|
|
913
914
|
this.#envoyStopped.promise.then(() => true),
|
|
914
915
|
new Promise<false>((resolve) =>
|
|
915
|
-
setTimeout(() => resolve(false),
|
|
916
|
+
setTimeout(() => resolve(false), envoyStopWaitMs),
|
|
916
917
|
),
|
|
917
918
|
]);
|
|
918
919
|
if (!stopped) {
|
|
919
920
|
logger().warn({
|
|
920
921
|
msg: "timed out waiting for envoy shutdown",
|
|
921
|
-
waitMs:
|
|
922
|
+
waitMs: envoyStopWaitMs,
|
|
922
923
|
});
|
|
923
924
|
}
|
|
924
925
|
|
|
@@ -929,6 +930,16 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
929
930
|
await this.#envoy.started();
|
|
930
931
|
}
|
|
931
932
|
|
|
933
|
+
#envoyStopWaitMs(): number {
|
|
934
|
+
const actorStopThreshold = Number(
|
|
935
|
+
this.#envoy.getProtocolMetadata()?.actorStopThreshold,
|
|
936
|
+
);
|
|
937
|
+
if (Number.isFinite(actorStopThreshold) && actorStopThreshold > 0) {
|
|
938
|
+
return actorStopThreshold;
|
|
939
|
+
}
|
|
940
|
+
return FALLBACK_ENVOY_STOP_WAIT_MS;
|
|
941
|
+
}
|
|
942
|
+
|
|
932
943
|
async #bindHibernatableConnectSocket(
|
|
933
944
|
binding: HibernatableConnectBinding,
|
|
934
945
|
isRestoringHibernatable: boolean,
|
|
@@ -1346,7 +1357,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1346
1357
|
logger().warn({
|
|
1347
1358
|
msg: "failed to rebind dynamic hibernatable runner websocket",
|
|
1348
1359
|
actorId,
|
|
1349
|
-
|
|
1360
|
+
error: stringifyError(result.reason),
|
|
1350
1361
|
});
|
|
1351
1362
|
}
|
|
1352
1363
|
}
|
|
@@ -1369,7 +1380,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1369
1380
|
logger().warn({
|
|
1370
1381
|
msg: "failed to rebind hibernatable connect socket",
|
|
1371
1382
|
actorId,
|
|
1372
|
-
|
|
1383
|
+
error: stringifyError(result.reason),
|
|
1373
1384
|
});
|
|
1374
1385
|
}
|
|
1375
1386
|
}
|
|
@@ -1629,7 +1640,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1629
1640
|
logger().warn({
|
|
1630
1641
|
msg: "failed to restore dynamic hibernating requests after actor start",
|
|
1631
1642
|
actorId,
|
|
1632
|
-
|
|
1643
|
+
error: stringifyError(error),
|
|
1633
1644
|
});
|
|
1634
1645
|
}
|
|
1635
1646
|
} else if (isStaticActorDefinition(definition)) {
|
|
@@ -1696,7 +1707,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1696
1707
|
logger().debug({
|
|
1697
1708
|
msg: "failed to dispose dynamic runtime after actor start failure",
|
|
1698
1709
|
actorId,
|
|
1699
|
-
|
|
1710
|
+
error: stringifyError(disposeError),
|
|
1700
1711
|
});
|
|
1701
1712
|
}
|
|
1702
1713
|
this.#dynamicRuntimes.delete(actorId);
|
|
@@ -1719,7 +1730,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1719
1730
|
actorId,
|
|
1720
1731
|
name,
|
|
1721
1732
|
key,
|
|
1722
|
-
|
|
1733
|
+
error: stringifyError(error),
|
|
1723
1734
|
});
|
|
1724
1735
|
|
|
1725
1736
|
try {
|
|
@@ -1728,7 +1739,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1728
1739
|
logger().debug({
|
|
1729
1740
|
msg: "failed to stop actor after start failure",
|
|
1730
1741
|
actorId,
|
|
1731
|
-
|
|
1742
|
+
error: stringifyError(stopError),
|
|
1732
1743
|
});
|
|
1733
1744
|
}
|
|
1734
1745
|
}
|
|
@@ -1775,7 +1786,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1775
1786
|
logger().debug({
|
|
1776
1787
|
msg: "actor start failed during stop, cleaning up handler",
|
|
1777
1788
|
actorId,
|
|
1778
|
-
|
|
1789
|
+
error: stringifyError(err),
|
|
1779
1790
|
});
|
|
1780
1791
|
}
|
|
1781
1792
|
}
|
|
@@ -1793,7 +1804,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1793
1804
|
} catch (err) {
|
|
1794
1805
|
logger().error({
|
|
1795
1806
|
msg: "error in onStop, proceeding with removing actor",
|
|
1796
|
-
|
|
1807
|
+
error: stringifyError(err),
|
|
1797
1808
|
});
|
|
1798
1809
|
}
|
|
1799
1810
|
}
|
|
@@ -1978,8 +1989,8 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1978
1989
|
isHibernatable,
|
|
1979
1990
|
isRestoringHibernatable,
|
|
1980
1991
|
);
|
|
1981
|
-
} catch (
|
|
1982
|
-
logger().error({ msg: "building websocket handlers errored",
|
|
1992
|
+
} catch (error) {
|
|
1993
|
+
logger().error({ msg: "building websocket handlers errored", error });
|
|
1983
1994
|
websocketRaw.close(1011, "ws.route_error");
|
|
1984
1995
|
return;
|
|
1985
1996
|
}
|
|
@@ -2190,12 +2201,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
2190
2201
|
isRestoringHibernatable,
|
|
2191
2202
|
);
|
|
2192
2203
|
} catch (error) {
|
|
2193
|
-
const { group, code } = deconstructError(
|
|
2194
|
-
error,
|
|
2195
|
-
logger(),
|
|
2196
|
-
{},
|
|
2197
|
-
false,
|
|
2198
|
-
);
|
|
2204
|
+
const { group, code } = deconstructError(error, false);
|
|
2199
2205
|
logger().error({
|
|
2200
2206
|
msg: "failed to bind dynamic hibernatable websocket",
|
|
2201
2207
|
actorId,
|
|
@@ -2233,12 +2239,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
2233
2239
|
},
|
|
2234
2240
|
);
|
|
2235
2241
|
} catch (error) {
|
|
2236
|
-
const { group, code } = deconstructError(
|
|
2237
|
-
error,
|
|
2238
|
-
logger(),
|
|
2239
|
-
{},
|
|
2240
|
-
false,
|
|
2241
|
-
);
|
|
2242
|
+
const { group, code } = deconstructError(error, false);
|
|
2242
2243
|
logger().error({
|
|
2243
2244
|
msg: "failed to open dynamic websocket",
|
|
2244
2245
|
actorId,
|
|
@@ -16,6 +16,7 @@ import { importWebSocket } from "@/common/websocket";
|
|
|
16
16
|
import { setRemoteHibernatableWebSocketAckTestHooks } from "@/common/websocket-test-hooks";
|
|
17
17
|
import type { ActorGatewayQuery, CrashPolicy } from "@/client/query";
|
|
18
18
|
import type { Encoding, UniversalWebSocket } from "@/mod";
|
|
19
|
+
import type { JsonCompatValue } from "@/common/encoding";
|
|
19
20
|
import { encodeCborCompat, uint8ArrayToBase64 } from "@/serde";
|
|
20
21
|
import { combineUrlPath } from "@/utils";
|
|
21
22
|
import { shouldSkipReadyWait, type GatewayRequestOptions } from "./driver";
|
|
@@ -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.`,
|
package/src/engine-client/mod.ts
CHANGED
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
RuntimeDisplayInformation,
|
|
24
24
|
} from "@/engine-client/driver";
|
|
25
25
|
import type { Encoding, UniversalWebSocket } from "@/mod";
|
|
26
|
+
import type { JsonCompatValue } from "@/common/encoding";
|
|
26
27
|
import { encodeCborCompat, uint8ArrayToBase64 } from "@/serde";
|
|
27
28
|
import { combineUrlPath, type GetUpgradeWebSocket } from "@/utils";
|
|
28
29
|
import { getNextPhase } from "@/utils/env-vars";
|
|
@@ -181,7 +182,7 @@ export class RemoteEngineControlClient implements EngineControlClient {
|
|
|
181
182
|
key: serializeActorKey(key),
|
|
182
183
|
runner_name_selector: this.#config.poolName,
|
|
183
184
|
input: actorInput
|
|
184
|
-
? uint8ArrayToBase64(encodeCborCompat(actorInput))
|
|
185
|
+
? uint8ArrayToBase64(encodeCborCompat(actorInput as JsonCompatValue))
|
|
185
186
|
: undefined,
|
|
186
187
|
crash_policy: crashPolicy ?? "sleep",
|
|
187
188
|
});
|
|
@@ -215,7 +216,7 @@ export class RemoteEngineControlClient implements EngineControlClient {
|
|
|
215
216
|
runner_name_selector: this.#config.poolName,
|
|
216
217
|
key: serializeActorKey(key),
|
|
217
218
|
input: input
|
|
218
|
-
? uint8ArrayToBase64(encodeCborCompat(input))
|
|
219
|
+
? uint8ArrayToBase64(encodeCborCompat(input as JsonCompatValue))
|
|
219
220
|
: undefined,
|
|
220
221
|
crash_policy: crashPolicy ?? "sleep",
|
|
221
222
|
});
|
|
@@ -264,8 +264,8 @@ export const RegistryConfigSchema = z
|
|
|
264
264
|
.object({
|
|
265
265
|
/**
|
|
266
266
|
* Wait this many milliseconds for the serve promise to resolve
|
|
267
|
-
* after calling `CoreRegistry::shutdown()`. Defaults to
|
|
268
|
-
*
|
|
267
|
+
* after calling `CoreRegistry::shutdown()`. Defaults to the
|
|
268
|
+
* engine-provided actor stop threshold once the envoy connects.
|
|
269
269
|
*
|
|
270
270
|
* Must be >= rivetkit-core's drain timeout (20s) + margin.
|
|
271
271
|
*/
|
|
@@ -273,8 +273,7 @@ export const RegistryConfigSchema = z
|
|
|
273
273
|
.number()
|
|
274
274
|
.int()
|
|
275
275
|
.min(1_000)
|
|
276
|
-
.optional()
|
|
277
|
-
.default(30_000),
|
|
276
|
+
.optional(),
|
|
278
277
|
/**
|
|
279
278
|
* If true, rivetkit will not install SIGINT/SIGTERM handlers.
|
|
280
279
|
* Use when the host application owns signal policy and will
|
|
@@ -284,7 +283,6 @@ export const RegistryConfigSchema = z
|
|
|
284
283
|
})
|
|
285
284
|
.optional()
|
|
286
285
|
.default(() => ({
|
|
287
|
-
gracePeriodMs: 30_000,
|
|
288
286
|
disableSignalHandlers: false,
|
|
289
287
|
})),
|
|
290
288
|
})
|