rivetkit 2.3.11-rc.8 → 2.3.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 +96 -14
- package/dist/browser/client.js +12 -2
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.d.ts +139 -139
- package/dist/browser/inspector/client.js +12 -2
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/tsup/agent-os/index.cjs +146 -76
- package/dist/tsup/agent-os/index.cjs.map +1 -1
- package/dist/tsup/agent-os/index.d.cts +83 -9
- package/dist/tsup/agent-os/index.d.ts +83 -9
- package/dist/tsup/agent-os/index.js +146 -76
- package/dist/tsup/agent-os/index.js.map +1 -1
- package/dist/tsup/{chunk-JBQ63WSM.js → chunk-3ZR542SK.js} +4 -4
- package/dist/tsup/chunk-3ZR542SK.js.map +1 -0
- package/dist/tsup/{chunk-HNHLBM3Y.cjs → chunk-4KGXFC6M.cjs} +42 -5
- package/dist/tsup/chunk-4KGXFC6M.cjs.map +1 -0
- package/dist/tsup/chunk-5UYWLCRO.js +14 -0
- package/dist/tsup/chunk-5UYWLCRO.js.map +1 -0
- package/dist/tsup/{chunk-QWLJCP3X.js → chunk-6W5VGLFT.js} +42 -5
- package/dist/tsup/chunk-6W5VGLFT.js.map +1 -0
- package/dist/tsup/chunk-6WYATRS4.js +243 -0
- package/dist/tsup/chunk-6WYATRS4.js.map +1 -0
- package/dist/tsup/chunk-B3W74FBB.cjs +14 -0
- package/dist/tsup/chunk-B3W74FBB.cjs.map +1 -0
- package/dist/tsup/{chunk-V6ANE6JM.js → chunk-FWROC5LA.js} +2 -2
- package/dist/tsup/{chunk-ZVM35ICH.cjs → chunk-GLIPKKEC.cjs} +7 -7
- package/dist/tsup/{chunk-ZVM35ICH.cjs.map → chunk-GLIPKKEC.cjs.map} +1 -1
- package/dist/tsup/{chunk-CCUO5OKD.cjs → chunk-GN2EUMEW.cjs} +3 -3
- package/dist/tsup/{chunk-CCUO5OKD.cjs.map → chunk-GN2EUMEW.cjs.map} +1 -1
- package/dist/tsup/{chunk-2ROUKH7W.cjs → chunk-GU7ML3KE.cjs} +13 -3
- package/dist/tsup/chunk-GU7ML3KE.cjs.map +1 -0
- package/dist/tsup/{chunk-WRRB24UY.js → chunk-JQ2AZ5FN.js} +3 -3
- package/dist/tsup/{chunk-7AFZMFPQ.js → chunk-JTHHCZCZ.js} +10 -1
- package/dist/tsup/chunk-JTHHCZCZ.js.map +1 -0
- package/dist/tsup/{chunk-UEULFXUI.cjs → chunk-KVFIONKQ.cjs} +11 -2
- package/dist/tsup/chunk-KVFIONKQ.cjs.map +1 -0
- package/dist/tsup/chunk-LWQFXGKS.cjs +243 -0
- package/dist/tsup/chunk-LWQFXGKS.cjs.map +1 -0
- package/dist/tsup/{chunk-KVD6ZWNM.js → chunk-MO2SSUOR.js} +8 -7
- package/dist/tsup/chunk-MO2SSUOR.js.map +1 -0
- package/dist/tsup/{chunk-AGNBLCNJ.js → chunk-OUENKQHB.js} +13 -3
- package/dist/tsup/chunk-OUENKQHB.js.map +1 -0
- package/dist/tsup/{chunk-E6WB2BLO.cjs → chunk-PUZY2XCD.cjs} +10 -9
- package/dist/tsup/chunk-PUZY2XCD.cjs.map +1 -0
- package/dist/tsup/{chunk-4EDGOGCB.js → chunk-QFJ24MBU.js} +27 -2
- package/dist/tsup/{chunk-4EDGOGCB.js.map → chunk-QFJ24MBU.js.map} +1 -1
- package/dist/tsup/{chunk-A55CGZIV.cjs → chunk-RXXDNJXB.cjs} +140 -140
- package/dist/tsup/{chunk-A55CGZIV.cjs.map → chunk-RXXDNJXB.cjs.map} +1 -1
- package/dist/tsup/{chunk-N6MBTYGX.cjs → chunk-VBJQIBXI.cjs} +30 -5
- package/dist/tsup/chunk-VBJQIBXI.cjs.map +1 -0
- package/dist/tsup/client/mod.cjs +6 -6
- package/dist/tsup/client/mod.d.cts +4 -3
- package/dist/tsup/client/mod.d.ts +4 -3
- package/dist/tsup/client/mod.js +5 -5
- package/dist/tsup/common/log.cjs +2 -2
- package/dist/tsup/common/log.js +1 -1
- package/dist/tsup/common/websocket.cjs +3 -3
- package/dist/tsup/common/websocket.js +2 -2
- package/dist/tsup/{config-CZcjyT5B.d.ts → config-C4OSv0QP.d.ts} +92 -7
- package/dist/tsup/{config-rGWrumlO.d.cts → config-DTGoWdkG.d.cts} +92 -7
- package/dist/tsup/{config-BxOimoGX.d.cts → config-ey2I2zz5.d.cts} +46 -6
- package/dist/tsup/{config-BxOimoGX.d.ts → config-ey2I2zz5.d.ts} +46 -6
- package/dist/tsup/{context-B8W8E8nW.d.cts → context-C6cvDNyk.d.cts} +2 -2
- package/dist/tsup/{context-_UrDZhEh.d.ts → context-CMygeBxS.d.ts} +2 -2
- package/dist/tsup/db/drizzle.cjs +18 -10
- package/dist/tsup/db/drizzle.cjs.map +1 -1
- package/dist/tsup/db/drizzle.d.cts +5 -6
- package/dist/tsup/db/drizzle.d.ts +5 -6
- package/dist/tsup/db/drizzle.js +13 -5
- package/dist/tsup/db/drizzle.js.map +1 -1
- package/dist/tsup/db/mod.cjs +5 -175
- package/dist/tsup/db/mod.cjs.map +1 -1
- package/dist/tsup/db/mod.d.cts +11 -4
- package/dist/tsup/db/mod.d.ts +11 -4
- package/dist/tsup/db/mod.js +4 -174
- package/dist/tsup/db/mod.js.map +1 -1
- package/dist/tsup/dynamic/mod.cjs +2 -2
- package/dist/tsup/dynamic/mod.d.cts +3 -2
- package/dist/tsup/dynamic/mod.d.ts +3 -2
- package/dist/tsup/dynamic/mod.js +1 -1
- package/dist/tsup/inspector/mod.cjs +5 -4
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.d.cts +12 -146
- package/dist/tsup/inspector/mod.d.ts +12 -146
- package/dist/tsup/inspector/mod.js +4 -3
- package/dist/tsup/inspector/mod.js.map +1 -1
- package/dist/tsup/inspector/workflow.cjs +21 -0
- package/dist/tsup/inspector/workflow.cjs.map +1 -0
- package/dist/tsup/inspector/workflow.d.cts +144 -0
- package/dist/tsup/inspector/workflow.d.ts +144 -0
- package/dist/tsup/inspector/workflow.js +21 -0
- package/dist/tsup/inspector/workflow.js.map +1 -0
- package/dist/tsup/inspector-tab/mod.cjs +2 -2
- package/dist/tsup/inspector-tab/mod.d.cts +4 -3
- package/dist/tsup/inspector-tab/mod.d.ts +4 -3
- package/dist/tsup/inspector-tab/mod.js +1 -1
- package/dist/tsup/mod.cjs +837 -243
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +6 -5
- package/dist/tsup/mod.d.ts +6 -5
- package/dist/tsup/mod.js +766 -172
- package/dist/tsup/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +7 -7
- package/dist/tsup/test/mod.d.cts +3 -2
- package/dist/tsup/test/mod.d.ts +3 -2
- package/dist/tsup/test/mod.js +5 -5
- package/dist/tsup/unstable/migrations.d.cts +1 -1
- package/dist/tsup/unstable/migrations.d.ts +1 -1
- package/dist/tsup/utils.cjs +2 -2
- package/dist/tsup/utils.js +1 -1
- package/dist/tsup/workflow/mod.cjs +89 -95
- package/dist/tsup/workflow/mod.cjs.map +1 -1
- package/dist/tsup/workflow/mod.d.cts +5 -4
- package/dist/tsup/workflow/mod.d.ts +5 -4
- package/dist/tsup/workflow/mod.js +86 -92
- package/dist/tsup/workflow/mod.js.map +1 -1
- package/package.json +19 -9
- package/src/actor/config.test.ts +65 -1
- package/src/actor/config.ts +169 -5
- package/src/actor/mod.ts +10 -1
- package/src/client/actor-common.ts +5 -14
- package/src/common/database/config.ts +50 -3
- package/src/common/database/mod.test.ts +142 -4
- package/src/common/database/mod.ts +210 -98
- package/src/common/database/native-database.ts +42 -3
- package/src/common/database/shared.ts +9 -0
- package/src/db/drizzle.test.ts +8 -1
- package/src/db/drizzle.ts +15 -4
- package/src/db/mod.ts +3 -0
- package/src/inspector/workflow.ts +61 -0
- package/src/registry/napi-runtime.ts +69 -1
- package/src/registry/native.ts +505 -155
- package/src/registry/run-handler-coordinator.test.ts +252 -0
- package/src/registry/run-handler-coordinator.ts +219 -0
- package/src/registry/runtime.ts +34 -1
- package/src/registry/wasm-runtime.ts +122 -17
- package/src/registry/write-through-proxy.ts +101 -0
- package/src/utils/node.ts +44 -28
- package/src/workflow/driver.ts +56 -58
- package/src/workflow/inspector.ts +10 -15
- package/src/workflow/mod.ts +48 -70
- package/dist/tsup/chunk-2ROUKH7W.cjs.map +0 -1
- package/dist/tsup/chunk-7AFZMFPQ.js.map +0 -1
- package/dist/tsup/chunk-AGNBLCNJ.js.map +0 -1
- package/dist/tsup/chunk-E6WB2BLO.cjs.map +0 -1
- package/dist/tsup/chunk-HNHLBM3Y.cjs.map +0 -1
- package/dist/tsup/chunk-JBQ63WSM.js.map +0 -1
- package/dist/tsup/chunk-KVD6ZWNM.js.map +0 -1
- package/dist/tsup/chunk-N6MBTYGX.cjs.map +0 -1
- package/dist/tsup/chunk-QWLJCP3X.js.map +0 -1
- package/dist/tsup/chunk-UEULFXUI.cjs.map +0 -1
- /package/dist/tsup/{chunk-V6ANE6JM.js.map → chunk-FWROC5LA.js.map} +0 -0
- /package/dist/tsup/{chunk-WRRB24UY.js.map → chunk-JQ2AZ5FN.js.map} +0 -0
package/src/actor/config.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
InferDatabaseClient,
|
|
6
6
|
} from "@/common/database/config";
|
|
7
7
|
import type { UniversalWebSocket } from "@/common/websocket-interface";
|
|
8
|
+
import type { WorkflowState } from "@/inspector/workflow";
|
|
8
9
|
import type { Registry } from "@/registry";
|
|
9
10
|
import { flattenActionHandlers } from "./actions";
|
|
10
11
|
import type { BaseActorDefinition } from "./definition";
|
|
@@ -64,7 +65,7 @@ type ActorKvListOptions<
|
|
|
64
65
|
type ActorClientFor<T> = T extends Registry<any> ? Client<T> : T;
|
|
65
66
|
|
|
66
67
|
/**
|
|
67
|
-
* @deprecated Actor KV is deprecated. Use embedded SQLite (`c.db`
|
|
68
|
+
* @deprecated Actor KV is deprecated. Use embedded SQLite (`c.db`)
|
|
68
69
|
* or actor state instead.
|
|
69
70
|
*/
|
|
70
71
|
export interface ActorKv {
|
|
@@ -332,6 +333,16 @@ export interface ActorQueue<
|
|
|
332
333
|
names: readonly TName[],
|
|
333
334
|
opts?: QueueWaitOptions<TCompletable>,
|
|
334
335
|
): Promise<any>;
|
|
336
|
+
/** @experimental */
|
|
337
|
+
waitForAvailable<const TName extends QueueFilterName<TQueues>>(
|
|
338
|
+
names?: readonly TName[],
|
|
339
|
+
opts?: Omit<QueueWaitOptions<false>, "completable">,
|
|
340
|
+
): Promise<void>;
|
|
341
|
+
/** @experimental */
|
|
342
|
+
complete<const TName extends QueueFilterName<TQueues>>(
|
|
343
|
+
message: { id: number | bigint; name: TName },
|
|
344
|
+
...args: QueueCompleteArgsForName<TQueues, TName>
|
|
345
|
+
): Promise<void>;
|
|
335
346
|
enqueueAndWait<const TName extends QueueFilterName<TQueues>>(
|
|
336
347
|
name: TName,
|
|
337
348
|
body: QueueMessageForName<TQueues, TName>["body"],
|
|
@@ -389,7 +400,7 @@ export interface ActorContext<
|
|
|
389
400
|
state: TState;
|
|
390
401
|
vars: TVars;
|
|
391
402
|
/**
|
|
392
|
-
* @deprecated Actor KV is deprecated. Use embedded SQLite (`db`
|
|
403
|
+
* @deprecated Actor KV is deprecated. Use embedded SQLite (`c.db`)
|
|
393
404
|
* or actor state instead.
|
|
394
405
|
*/
|
|
395
406
|
readonly kv: ActorKv;
|
|
@@ -397,6 +408,8 @@ export interface ActorContext<
|
|
|
397
408
|
readonly schedule: ActorSchedule;
|
|
398
409
|
readonly cron: ActorCron;
|
|
399
410
|
readonly queue: ActorQueue<TQueues>;
|
|
411
|
+
/** @experimental */
|
|
412
|
+
readonly run: ActorRun;
|
|
400
413
|
readonly actorId: string;
|
|
401
414
|
readonly name: string;
|
|
402
415
|
readonly key: string[];
|
|
@@ -434,6 +447,15 @@ export interface ActorContext<
|
|
|
434
447
|
[key: string]: any;
|
|
435
448
|
}
|
|
436
449
|
|
|
450
|
+
/** @experimental */
|
|
451
|
+
export interface ActorRun {
|
|
452
|
+
/**
|
|
453
|
+
* @experimental Sets or clears the durable Unix-millisecond deadline that
|
|
454
|
+
* ensures this actor's run handler is active, starting it if inactive.
|
|
455
|
+
*/
|
|
456
|
+
setWakeAt(timestamp: number | null): Promise<void>;
|
|
457
|
+
}
|
|
458
|
+
|
|
437
459
|
export type ActionContext<
|
|
438
460
|
TState,
|
|
439
461
|
TConnParams,
|
|
@@ -821,20 +843,27 @@ const zActionTree = z
|
|
|
821
843
|
|
|
822
844
|
export type InspectorUnsubscribe = () => void;
|
|
823
845
|
|
|
846
|
+
/** @experimental */
|
|
824
847
|
export interface WorkflowInspectorConfig<THistory = unknown> {
|
|
825
848
|
getHistory: () => THistory | null;
|
|
849
|
+
getState?: () => Promise<WorkflowState | null>;
|
|
826
850
|
onHistoryUpdated?: (
|
|
827
851
|
listener: (history: THistory) => void,
|
|
828
852
|
) => InspectorUnsubscribe;
|
|
829
853
|
replayFromStep?: (entryId?: string) => Promise<THistory | null>;
|
|
830
854
|
}
|
|
831
855
|
|
|
856
|
+
/** @experimental */
|
|
832
857
|
export interface RunInspectorConfig<THistory = unknown> {
|
|
833
858
|
workflow?: WorkflowInspectorConfig<THistory>;
|
|
834
859
|
}
|
|
835
860
|
|
|
836
861
|
const WorkflowInspectorConfigSchema = z.object({
|
|
837
862
|
getHistory: zFunction<WorkflowInspectorConfig<unknown>["getHistory"]>(),
|
|
863
|
+
getState:
|
|
864
|
+
zFunction<
|
|
865
|
+
NonNullable<WorkflowInspectorConfig<unknown>["getState"]>
|
|
866
|
+
>().optional(),
|
|
838
867
|
onHistoryUpdated:
|
|
839
868
|
zFunction<
|
|
840
869
|
NonNullable<WorkflowInspectorConfig<unknown>["onHistoryUpdated"]>
|
|
@@ -981,9 +1010,72 @@ type AnyRunConfig = RunConfig<
|
|
|
981
1010
|
any
|
|
982
1011
|
>;
|
|
983
1012
|
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1013
|
+
const RUN_FUNCTION_CONFIG_SYMBOL = Symbol.for("rivetkit.run_function_config");
|
|
1014
|
+
|
|
1015
|
+
/** @experimental */
|
|
1016
|
+
export type RunInspectorKind = "workflow";
|
|
1017
|
+
|
|
1018
|
+
/** @experimental */
|
|
1019
|
+
export interface RunWithInactiveOptions {
|
|
1020
|
+
/** Restart the run handler before releasing the exclusive gate on success. */
|
|
1021
|
+
restartOnSuccess?: boolean;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/** @experimental */
|
|
1025
|
+
export interface RunControl {
|
|
1026
|
+
run: {
|
|
1027
|
+
/**
|
|
1028
|
+
* Executes only while no run handler is active or waiting to start.
|
|
1029
|
+
*
|
|
1030
|
+
* This is a non-blocking acquisition: concurrent replay/control requests
|
|
1031
|
+
* fail instead of waiting behind an active run.
|
|
1032
|
+
*/
|
|
1033
|
+
withInactive<T>(
|
|
1034
|
+
options: RunWithInactiveOptions,
|
|
1035
|
+
callback: () => T | Promise<T>,
|
|
1036
|
+
): Promise<T>;
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/** @experimental */
|
|
1041
|
+
export interface RunInspectorFactoryContext {
|
|
1042
|
+
actorId: string;
|
|
1043
|
+
control: RunControl;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/** @experimental */
|
|
1047
|
+
export interface RunInspectorFactoryResult<THistory = unknown> {
|
|
1048
|
+
inspector: {
|
|
1049
|
+
workflow: Required<WorkflowInspectorConfig<THistory>> & {
|
|
1050
|
+
getState: () => Promise<WorkflowState | null>;
|
|
1051
|
+
};
|
|
1052
|
+
};
|
|
1053
|
+
/** Releases actor-specific listeners and encoded history. */
|
|
1054
|
+
dispose?: () => void;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
interface RunHandlerDisplayOptions {
|
|
1058
|
+
name?: string;
|
|
1059
|
+
icon?: string;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/** @experimental */
|
|
1063
|
+
export type DefineRunHandlerOptions<THistory = unknown> =
|
|
1064
|
+
RunHandlerDisplayOptions &
|
|
1065
|
+
(
|
|
1066
|
+
| {
|
|
1067
|
+
inspectorKind?: never;
|
|
1068
|
+
createInspector?: never;
|
|
1069
|
+
}
|
|
1070
|
+
| {
|
|
1071
|
+
/** Static metadata used to install Inspector callbacks at registry build time. */
|
|
1072
|
+
inspectorKind: RunInspectorKind;
|
|
1073
|
+
/** Creates one Inspector adapter for each live actor. */
|
|
1074
|
+
createInspector: (
|
|
1075
|
+
context: RunInspectorFactoryContext,
|
|
1076
|
+
) => RunInspectorFactoryResult<THistory>;
|
|
1077
|
+
}
|
|
1078
|
+
);
|
|
987
1079
|
|
|
988
1080
|
interface RunFunctionConfig {
|
|
989
1081
|
name?: string;
|
|
@@ -992,12 +1084,69 @@ interface RunFunctionConfig {
|
|
|
992
1084
|
inspectorFactory?: (actor: unknown) => RunInspectorConfig | undefined;
|
|
993
1085
|
/** Release any per-actor inspector state held for this actor id. */
|
|
994
1086
|
disposeInspector?: (actorId: string) => void;
|
|
1087
|
+
inspectorKind?: RunInspectorKind;
|
|
1088
|
+
createInspector?: (
|
|
1089
|
+
context: RunInspectorFactoryContext,
|
|
1090
|
+
) => RunInspectorFactoryResult;
|
|
995
1091
|
}
|
|
996
1092
|
|
|
997
1093
|
type RunFunctionWithConfig = ((...args: any[]) => any) & {
|
|
998
1094
|
[RUN_FUNCTION_CONFIG_SYMBOL]?: RunFunctionConfig;
|
|
999
1095
|
};
|
|
1000
1096
|
|
|
1097
|
+
/**
|
|
1098
|
+
* @experimental Adds supported RivetKit run metadata while preserving the function's exact
|
|
1099
|
+
* callable type.
|
|
1100
|
+
*/
|
|
1101
|
+
export function defineRunHandler<
|
|
1102
|
+
TRun extends (...args: any[]) => any,
|
|
1103
|
+
THistory = unknown,
|
|
1104
|
+
>(run: TRun, options: DefineRunHandlerOptions<THistory>): TRun {
|
|
1105
|
+
if (
|
|
1106
|
+
(options.inspectorKind === undefined) !==
|
|
1107
|
+
(options.createInspector === undefined)
|
|
1108
|
+
) {
|
|
1109
|
+
throw new TypeError(
|
|
1110
|
+
"defineRunHandler requires inspectorKind and createInspector together",
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
Object.defineProperty(run, RUN_FUNCTION_CONFIG_SYMBOL, {
|
|
1115
|
+
configurable: false,
|
|
1116
|
+
enumerable: false,
|
|
1117
|
+
writable: false,
|
|
1118
|
+
value: {
|
|
1119
|
+
name: options.name,
|
|
1120
|
+
icon: options.icon,
|
|
1121
|
+
inspectorKind: options.inspectorKind,
|
|
1122
|
+
createInspector:
|
|
1123
|
+
options.createInspector as RunFunctionConfig["createInspector"],
|
|
1124
|
+
} satisfies RunFunctionConfig,
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1127
|
+
return run;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/** @internal */
|
|
1131
|
+
export function getRunInspectorKind(
|
|
1132
|
+
run: ((...args: any[]) => any) | AnyRunConfig | undefined,
|
|
1133
|
+
): RunInspectorKind | undefined {
|
|
1134
|
+
if (!run || typeof run !== "function") return undefined;
|
|
1135
|
+
return (run as RunFunctionWithConfig)[RUN_FUNCTION_CONFIG_SYMBOL]
|
|
1136
|
+
?.inspectorKind;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/** @internal */
|
|
1140
|
+
export function createRunInspector(
|
|
1141
|
+
run: ((...args: any[]) => any) | AnyRunConfig | undefined,
|
|
1142
|
+
context: RunInspectorFactoryContext,
|
|
1143
|
+
): RunInspectorFactoryResult | undefined {
|
|
1144
|
+
if (!run || typeof run !== "function") return undefined;
|
|
1145
|
+
return (run as RunFunctionWithConfig)[
|
|
1146
|
+
RUN_FUNCTION_CONFIG_SYMBOL
|
|
1147
|
+
]?.createInspector?.(context);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1001
1150
|
// Run can be either a function or an object with name/icon/run
|
|
1002
1151
|
const zRunHandler = z.union([zFunction(), RunConfigSchema]).optional();
|
|
1003
1152
|
|
|
@@ -1042,6 +1191,21 @@ export function getRunInspectorConfig(
|
|
|
1042
1191
|
return run.inspector;
|
|
1043
1192
|
}
|
|
1044
1193
|
|
|
1194
|
+
/** @internal */
|
|
1195
|
+
export function hasRunInspectorConfig(
|
|
1196
|
+
run: ((...args: any[]) => any) | AnyRunConfig | undefined,
|
|
1197
|
+
): boolean {
|
|
1198
|
+
if (!run) return false;
|
|
1199
|
+
if (typeof run !== "function") return run.inspector !== undefined;
|
|
1200
|
+
const config = (run as RunFunctionWithConfig)[RUN_FUNCTION_CONFIG_SYMBOL];
|
|
1201
|
+
return (
|
|
1202
|
+
config?.inspectorKind !== undefined ||
|
|
1203
|
+
config?.createInspector !== undefined ||
|
|
1204
|
+
config?.inspector !== undefined ||
|
|
1205
|
+
config?.inspectorFactory !== undefined
|
|
1206
|
+
);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1045
1209
|
/** Release per-actor inspector state for a destroyed actor, if the run handler registered a disposer. */
|
|
1046
1210
|
export function disposeRunInspector(
|
|
1047
1211
|
run: ((...args: any[]) => any) | AnyRunConfig | undefined,
|
package/src/actor/mod.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type {
|
|
|
14
14
|
UniversalWebSocket,
|
|
15
15
|
} from "@/common/websocket-interface";
|
|
16
16
|
export type * from "./config";
|
|
17
|
+
export { defineRunHandler } from "./config";
|
|
17
18
|
export type {
|
|
18
19
|
ActionContextOf,
|
|
19
20
|
BeforeActionResponseContextOf,
|
|
@@ -57,4 +58,12 @@ export {
|
|
|
57
58
|
UserError,
|
|
58
59
|
type UserErrorOptions,
|
|
59
60
|
} from "./errors";
|
|
60
|
-
export {
|
|
61
|
+
export {
|
|
62
|
+
type EventSchemaConfig,
|
|
63
|
+
event,
|
|
64
|
+
type InferEventArgs,
|
|
65
|
+
type InferSchemaMap,
|
|
66
|
+
type QueueSchemaConfig,
|
|
67
|
+
queue,
|
|
68
|
+
type Type,
|
|
69
|
+
} from "./schema";
|
|
@@ -48,20 +48,11 @@ type ActorActionMap<R> = {
|
|
|
48
48
|
: never;
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
type ActionsOf<AD extends AnyActorDefinition> =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
any,
|
|
57
|
-
any,
|
|
58
|
-
any,
|
|
59
|
-
any,
|
|
60
|
-
any,
|
|
61
|
-
infer R
|
|
62
|
-
>
|
|
63
|
-
? R
|
|
64
|
-
: never;
|
|
51
|
+
type ActionsOf<AD extends AnyActorDefinition> = AD["config"] extends {
|
|
52
|
+
actions?: infer R;
|
|
53
|
+
}
|
|
54
|
+
? R
|
|
55
|
+
: never;
|
|
65
56
|
|
|
66
57
|
export interface ActorGatewayOptions {
|
|
67
58
|
skipReadyWait?: boolean;
|
|
@@ -9,7 +9,7 @@ export interface ActorMetricsLike {
|
|
|
9
9
|
export type InferDatabaseClient<DBProvider extends AnyDatabaseProvider> =
|
|
10
10
|
DBProvider extends DatabaseProvider<any>
|
|
11
11
|
? Awaited<ReturnType<DBProvider["createClient"]>>
|
|
12
|
-
:
|
|
12
|
+
: RawAccess;
|
|
13
13
|
|
|
14
14
|
export type SqliteBindings = unknown[] | Record<string, unknown>;
|
|
15
15
|
|
|
@@ -28,6 +28,43 @@ export interface SqliteBatchStatement {
|
|
|
28
28
|
params?: SqliteBindings;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export interface SqliteTransactionOptions {
|
|
32
|
+
/** Static operation name used to aggregate transaction performance. */
|
|
33
|
+
name?: string;
|
|
34
|
+
/** Deadlock-safety timeout in milliseconds. */
|
|
35
|
+
timeout?: number;
|
|
36
|
+
/** @experimental */
|
|
37
|
+
experimental?: {
|
|
38
|
+
/**
|
|
39
|
+
* Atomically includes actor and hibernatable connection state.
|
|
40
|
+
* Only single-statement `execute` calls are supported in the transaction.
|
|
41
|
+
* Concurrent actions that try to mutate state while the transaction is
|
|
42
|
+
* active fail with `actor.state_transaction_conflict`.
|
|
43
|
+
*/
|
|
44
|
+
includeState?: boolean;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* SQLite profiling configuration.
|
|
50
|
+
*
|
|
51
|
+
* @experimental This entire configuration surface is experimental and subject
|
|
52
|
+
* to change without notice.
|
|
53
|
+
*/
|
|
54
|
+
export interface SqliteProfilingOptions {
|
|
55
|
+
enabled?: boolean;
|
|
56
|
+
maxTrackedStatementFingerprints?: number;
|
|
57
|
+
maxTrackedTransactionFingerprints?: number;
|
|
58
|
+
maxPrometheusSeries?: number;
|
|
59
|
+
maxStatementsPerTransactionTrace?: number;
|
|
60
|
+
maxGetPagesRequestsPerTrace?: number;
|
|
61
|
+
maxTransactionNameBytes?: number;
|
|
62
|
+
slowOperationThresholdMs?: number;
|
|
63
|
+
baselineSampleRate?: number;
|
|
64
|
+
maxDiagnosticEventsPerMinute?: number;
|
|
65
|
+
diagnosticEventQueueCapacity?: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
31
68
|
export interface SqliteNativeMetrics {
|
|
32
69
|
requestBuildNs: number;
|
|
33
70
|
serializeNs: number;
|
|
@@ -51,7 +88,10 @@ export interface SqliteDatabase {
|
|
|
51
88
|
executeBatch(
|
|
52
89
|
statements: SqliteBatchStatement[],
|
|
53
90
|
): Promise<SqliteExecuteResult[]>;
|
|
54
|
-
beginTransaction(
|
|
91
|
+
beginTransaction(
|
|
92
|
+
timeoutMs?: number,
|
|
93
|
+
name?: string,
|
|
94
|
+
): Promise<SqliteTransactionDatabase>;
|
|
55
95
|
run(sql: string, params?: SqliteBindings): Promise<void>;
|
|
56
96
|
query(sql: string, params?: SqliteBindings): Promise<SqliteQueryResult>;
|
|
57
97
|
nativeMetrics?():
|
|
@@ -121,6 +161,13 @@ export interface DatabaseProviderContext {
|
|
|
121
161
|
}
|
|
122
162
|
|
|
123
163
|
export type DatabaseProvider<DB extends RawAccess> = {
|
|
164
|
+
/**
|
|
165
|
+
* Local SQLite profiling controls consumed by the actor runtime.
|
|
166
|
+
*
|
|
167
|
+
* @experimental This entire configuration surface is experimental and
|
|
168
|
+
* subject to change without notice.
|
|
169
|
+
*/
|
|
170
|
+
sqliteProfiling?: SqliteProfilingOptions;
|
|
124
171
|
/**
|
|
125
172
|
* Creates a new database client for the actor.
|
|
126
173
|
* The result is passed to the actor context as `c.db`.
|
|
@@ -165,7 +212,7 @@ export type RawAccess = {
|
|
|
165
212
|
/** Runs a callback in an isolated SQLite transaction. */
|
|
166
213
|
transaction: <T>(
|
|
167
214
|
callback: (tx: RawAccess) => Promise<T> | T,
|
|
168
|
-
options?:
|
|
215
|
+
options?: SqliteTransactionOptions,
|
|
169
216
|
) => Promise<T>;
|
|
170
217
|
/**
|
|
171
218
|
* Returns native SQLite metrics when the active runtime supports them.
|
|
@@ -8,14 +8,16 @@ import type {
|
|
|
8
8
|
SqliteExecuteResult,
|
|
9
9
|
SqliteTransactionDatabase,
|
|
10
10
|
} from "./config";
|
|
11
|
-
import { db } from "./mod";
|
|
11
|
+
import { db, registerNativeStateTransactionOpener } from "./mod";
|
|
12
12
|
|
|
13
13
|
let logLines: string[];
|
|
14
14
|
|
|
15
15
|
class FakeSqliteDatabase implements SqliteDatabase {
|
|
16
16
|
failSql = new Map<string, Error>();
|
|
17
17
|
executeCalls: { sql: string; params?: SqliteBindings }[] = [];
|
|
18
|
+
stateTransactionTimeouts: Array<number | undefined> = [];
|
|
18
19
|
transactionTimeouts: Array<number | undefined> = [];
|
|
20
|
+
transactionNames: Array<string | undefined> = [];
|
|
19
21
|
|
|
20
22
|
async exec(): Promise<void> {}
|
|
21
23
|
|
|
@@ -29,8 +31,10 @@ class FakeSqliteDatabase implements SqliteDatabase {
|
|
|
29
31
|
|
|
30
32
|
async beginTransaction(
|
|
31
33
|
timeoutMs?: number,
|
|
34
|
+
name?: string,
|
|
32
35
|
): Promise<SqliteTransactionDatabase> {
|
|
33
36
|
this.transactionTimeouts.push(timeoutMs);
|
|
37
|
+
this.transactionNames.push(name);
|
|
34
38
|
this.record("BEGIN");
|
|
35
39
|
return {
|
|
36
40
|
exec: async () => {},
|
|
@@ -42,6 +46,21 @@ class FakeSqliteDatabase implements SqliteDatabase {
|
|
|
42
46
|
rollback: async () => this.record("ROLLBACK"),
|
|
43
47
|
};
|
|
44
48
|
}
|
|
49
|
+
async beginStateTransaction(
|
|
50
|
+
timeoutMs?: number,
|
|
51
|
+
): Promise<SqliteTransactionDatabase> {
|
|
52
|
+
this.stateTransactionTimeouts.push(timeoutMs);
|
|
53
|
+
this.record("BEGIN_STATE");
|
|
54
|
+
return {
|
|
55
|
+
exec: async () => {},
|
|
56
|
+
execute: async (sql, params) => {
|
|
57
|
+
this.record(sql, params);
|
|
58
|
+
return emptyResult();
|
|
59
|
+
},
|
|
60
|
+
commit: async () => this.record("COMMIT"),
|
|
61
|
+
rollback: async () => this.record("ROLLBACK"),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
45
64
|
|
|
46
65
|
async executeBatch(
|
|
47
66
|
statements: Array<{ sql: string; params?: SqliteBindings }>,
|
|
@@ -81,7 +100,8 @@ function emptyResult(): SqliteExecuteResult {
|
|
|
81
100
|
}
|
|
82
101
|
|
|
83
102
|
function testProviderContext(
|
|
84
|
-
database:
|
|
103
|
+
database: FakeSqliteDatabase,
|
|
104
|
+
includeStateTransactions = false,
|
|
85
105
|
): DatabaseProviderContext {
|
|
86
106
|
return {
|
|
87
107
|
actorId: "actor-a",
|
|
@@ -91,7 +111,13 @@ function testProviderContext(
|
|
|
91
111
|
batchDelete: async () => {},
|
|
92
112
|
deleteRange: async () => {},
|
|
93
113
|
},
|
|
94
|
-
nativeDatabaseProvider:
|
|
114
|
+
nativeDatabaseProvider: includeStateTransactions
|
|
115
|
+
? registerNativeStateTransactionOpener(
|
|
116
|
+
{ open: async () => database },
|
|
117
|
+
async (timeoutMs?: number) =>
|
|
118
|
+
await database.beginStateTransaction(timeoutMs),
|
|
119
|
+
)
|
|
120
|
+
: { open: async () => database },
|
|
95
121
|
};
|
|
96
122
|
}
|
|
97
123
|
|
|
@@ -128,6 +154,23 @@ describe("db", () => {
|
|
|
128
154
|
"COMMIT",
|
|
129
155
|
]);
|
|
130
156
|
expect(nativeDb.transactionTimeouts).toEqual([300_000]);
|
|
157
|
+
expect(nativeDb.transactionNames).toEqual(["rivetkit-migration"]);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("exposes profiling controls to the actor runtime", () => {
|
|
161
|
+
const provider = db({
|
|
162
|
+
profiling: {
|
|
163
|
+
enabled: false,
|
|
164
|
+
maxTrackedStatementFingerprints: 12,
|
|
165
|
+
baselineSampleRate: 0.25,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
expect(provider.sqliteProfiling).toEqual({
|
|
170
|
+
enabled: false,
|
|
171
|
+
maxTrackedStatementFingerprints: 12,
|
|
172
|
+
baselineSampleRate: 0.25,
|
|
173
|
+
});
|
|
131
174
|
});
|
|
132
175
|
|
|
133
176
|
test("rolls back migrations when onMigrate fails", async () => {
|
|
@@ -163,10 +206,11 @@ describe("db", () => {
|
|
|
163
206
|
);
|
|
164
207
|
return 42;
|
|
165
208
|
},
|
|
166
|
-
{ timeout: 120_000 },
|
|
209
|
+
{ name: "insert-item", timeout: 120_000 },
|
|
167
210
|
);
|
|
168
211
|
expect(value).toBe(42);
|
|
169
212
|
expect(nativeDb.transactionTimeouts).toEqual([120_000]);
|
|
213
|
+
expect(nativeDb.transactionNames).toEqual(["insert-item"]);
|
|
170
214
|
expect(nativeDb.executeCalls.map(({ sql }) => sql)).toEqual([
|
|
171
215
|
"BEGIN",
|
|
172
216
|
"INSERT INTO items(value) VALUES (?)",
|
|
@@ -174,6 +218,25 @@ describe("db", () => {
|
|
|
174
218
|
]);
|
|
175
219
|
});
|
|
176
220
|
|
|
221
|
+
test("validates transaction names", async () => {
|
|
222
|
+
const client = await db().createClient(
|
|
223
|
+
testProviderContext(new FakeSqliteDatabase()),
|
|
224
|
+
);
|
|
225
|
+
await expect(
|
|
226
|
+
client.transaction(async () => {}, { name: "" }),
|
|
227
|
+
).rejects.toThrow("must not be empty");
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test("defers the configured transaction name byte limit to the runtime", async () => {
|
|
231
|
+
const nativeDb = new FakeSqliteDatabase();
|
|
232
|
+
const client = await db().createClient(testProviderContext(nativeDb));
|
|
233
|
+
const name = "x".repeat(129);
|
|
234
|
+
|
|
235
|
+
await client.transaction(async () => {}, { name });
|
|
236
|
+
|
|
237
|
+
expect(nativeDb.transactionNames).toEqual([name]);
|
|
238
|
+
});
|
|
239
|
+
|
|
177
240
|
test("rolls back a transaction when the callback throws", async () => {
|
|
178
241
|
const nativeDb = new FakeSqliteDatabase();
|
|
179
242
|
const client = await db().createClient(testProviderContext(nativeDb));
|
|
@@ -193,6 +256,81 @@ describe("db", () => {
|
|
|
193
256
|
]);
|
|
194
257
|
});
|
|
195
258
|
|
|
259
|
+
test("uses the state-aware transaction bridge when explicitly requested", async () => {
|
|
260
|
+
const nativeDb = new FakeSqliteDatabase();
|
|
261
|
+
const client = await db().createClient(
|
|
262
|
+
testProviderContext(nativeDb, true),
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
await client.transaction(
|
|
266
|
+
async (tx) => {
|
|
267
|
+
await tx.execute(
|
|
268
|
+
"INSERT INTO items(value) VALUES (?)",
|
|
269
|
+
"inside",
|
|
270
|
+
);
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
timeout: 120_000,
|
|
274
|
+
experimental: { includeState: true },
|
|
275
|
+
},
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
expect(nativeDb.transactionTimeouts).toEqual([]);
|
|
279
|
+
expect(nativeDb.stateTransactionTimeouts).toEqual([120_000]);
|
|
280
|
+
expect(nativeDb.executeCalls.map(({ sql }) => sql)).toEqual([
|
|
281
|
+
"BEGIN_STATE",
|
|
282
|
+
"INSERT INTO items(value) VALUES (?)",
|
|
283
|
+
"COMMIT",
|
|
284
|
+
]);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test("rolls back state-aware transactions when the callback throws", async () => {
|
|
288
|
+
const nativeDb = new FakeSqliteDatabase();
|
|
289
|
+
const client = await db().createClient(
|
|
290
|
+
testProviderContext(nativeDb, true),
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
await expect(
|
|
294
|
+
client.transaction(
|
|
295
|
+
async (tx) => {
|
|
296
|
+
await tx.execute(
|
|
297
|
+
"INSERT INTO items(value) VALUES (?)",
|
|
298
|
+
"inside",
|
|
299
|
+
);
|
|
300
|
+
throw new Error("callback failed");
|
|
301
|
+
},
|
|
302
|
+
{ experimental: { includeState: true } },
|
|
303
|
+
),
|
|
304
|
+
).rejects.toThrow("callback failed");
|
|
305
|
+
expect(nativeDb.executeCalls.map(({ sql }) => sql)).toEqual([
|
|
306
|
+
"BEGIN_STATE",
|
|
307
|
+
"INSERT INTO items(value) VALUES (?)",
|
|
308
|
+
"ROLLBACK",
|
|
309
|
+
]);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test("rejects nested state-aware transactions", async () => {
|
|
313
|
+
const nativeDb = new FakeSqliteDatabase();
|
|
314
|
+
const client = await db().createClient(
|
|
315
|
+
testProviderContext(nativeDb, true),
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
await expect(
|
|
319
|
+
client.transaction(
|
|
320
|
+
async (tx) => {
|
|
321
|
+
await tx.transaction(async () => {}, {
|
|
322
|
+
experimental: { includeState: true },
|
|
323
|
+
});
|
|
324
|
+
},
|
|
325
|
+
{ experimental: { includeState: true } },
|
|
326
|
+
),
|
|
327
|
+
).rejects.toThrow("not supported for nested transactions");
|
|
328
|
+
expect(nativeDb.executeCalls.map(({ sql }) => sql)).toEqual([
|
|
329
|
+
"BEGIN_STATE",
|
|
330
|
+
"ROLLBACK",
|
|
331
|
+
]);
|
|
332
|
+
});
|
|
333
|
+
|
|
196
334
|
test("validates transaction timeouts", async () => {
|
|
197
335
|
const client = await db().createClient(
|
|
198
336
|
testProviderContext(new FakeSqliteDatabase()),
|