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
|
@@ -1,23 +1,78 @@
|
|
|
1
1
|
import { getLogger } from "@/common/log";
|
|
2
2
|
import type {
|
|
3
3
|
DatabaseProvider,
|
|
4
|
+
NativeDatabaseProvider,
|
|
4
5
|
RawAccess,
|
|
5
6
|
SqliteDatabase,
|
|
7
|
+
SqliteProfilingOptions,
|
|
6
8
|
SqliteTransactionDatabase,
|
|
9
|
+
SqliteTransactionOptions,
|
|
7
10
|
} from "./config";
|
|
8
11
|
import {
|
|
9
12
|
isManualTransactionControl,
|
|
10
13
|
isSqliteBindingObject,
|
|
11
14
|
MIGRATION_TRANSACTION_TIMEOUT_MS,
|
|
12
15
|
toSqliteBindings,
|
|
16
|
+
validateTransactionName,
|
|
13
17
|
validateTransactionTimeout,
|
|
14
18
|
} from "./shared";
|
|
15
19
|
|
|
16
20
|
export type { RawAccess } from "./config";
|
|
17
21
|
|
|
18
|
-
interface DatabaseFactoryConfig {
|
|
22
|
+
export interface DatabaseFactoryConfig {
|
|
19
23
|
onMigrate?: (db: RawAccess) => Promise<void> | void;
|
|
20
24
|
warnOnManualTransactions?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* SQLite profiling configuration.
|
|
27
|
+
*
|
|
28
|
+
* @experimental This entire configuration surface is experimental and
|
|
29
|
+
* subject to change without notice.
|
|
30
|
+
*/
|
|
31
|
+
profiling?: SqliteProfilingOptions;
|
|
32
|
+
}
|
|
33
|
+
const nativeStateTransactionOpeners = new WeakMap<
|
|
34
|
+
NativeDatabaseProvider,
|
|
35
|
+
(
|
|
36
|
+
timeoutMs?: number,
|
|
37
|
+
context?: unknown,
|
|
38
|
+
) => Promise<SqliteTransactionDatabase>
|
|
39
|
+
>();
|
|
40
|
+
type NativeStateTransactionContext = {
|
|
41
|
+
enter(): Promise<unknown>;
|
|
42
|
+
exit(scope: unknown): void;
|
|
43
|
+
};
|
|
44
|
+
const nativeStateTransactionClientBinders = new WeakMap<
|
|
45
|
+
object,
|
|
46
|
+
(context: NativeStateTransactionContext) => object
|
|
47
|
+
>();
|
|
48
|
+
|
|
49
|
+
/** @internal */
|
|
50
|
+
export function registerNativeStateTransactionOpener<
|
|
51
|
+
T extends NativeDatabaseProvider,
|
|
52
|
+
>(
|
|
53
|
+
provider: T,
|
|
54
|
+
opener: (
|
|
55
|
+
timeoutMs?: number,
|
|
56
|
+
context?: unknown,
|
|
57
|
+
) => Promise<SqliteTransactionDatabase>,
|
|
58
|
+
): T {
|
|
59
|
+
nativeStateTransactionOpeners.set(provider, opener);
|
|
60
|
+
return provider;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** @internal */
|
|
64
|
+
export function bindNativeStateTransactionContext<T>(
|
|
65
|
+
client: T,
|
|
66
|
+
context: NativeStateTransactionContext,
|
|
67
|
+
): T {
|
|
68
|
+
if (
|
|
69
|
+
(typeof client !== "object" || client === null) &&
|
|
70
|
+
typeof client !== "function"
|
|
71
|
+
) {
|
|
72
|
+
return client;
|
|
73
|
+
}
|
|
74
|
+
const bind = nativeStateTransactionClientBinders.get(client as object);
|
|
75
|
+
return (bind?.(context) ?? client) as T;
|
|
21
76
|
}
|
|
22
77
|
|
|
23
78
|
function hasMultipleStatements(query: string): boolean {
|
|
@@ -28,8 +83,10 @@ function hasMultipleStatements(query: string): boolean {
|
|
|
28
83
|
export function db({
|
|
29
84
|
onMigrate,
|
|
30
85
|
warnOnManualTransactions = true,
|
|
86
|
+
profiling,
|
|
31
87
|
}: DatabaseFactoryConfig = {}): DatabaseProvider<RawAccess> {
|
|
32
|
-
|
|
88
|
+
const provider: DatabaseProvider<RawAccess> = {
|
|
89
|
+
sqliteProfiling: profiling,
|
|
33
90
|
createClient: async (ctx) => {
|
|
34
91
|
const nativeDatabaseProvider = ctx.nativeDatabaseProvider;
|
|
35
92
|
if (!nativeDatabaseProvider) {
|
|
@@ -52,110 +109,161 @@ export function db({
|
|
|
52
109
|
const createClient = (
|
|
53
110
|
target: SqliteDatabase | SqliteTransactionDatabase,
|
|
54
111
|
transactionScoped = false,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
unknown
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const kvReadsBefore = ctx.metrics?.totalKvReads ?? 0;
|
|
81
|
-
const kvWritesBefore = ctx.metrics?.totalKvWrites ?? 0;
|
|
82
|
-
const start = performance.now();
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
if (args.length > 0) {
|
|
86
|
-
const bindings =
|
|
87
|
-
args.length === 1 &&
|
|
88
|
-
isSqliteBindingObject(args[0])
|
|
89
|
-
? toSqliteBindings(args[0])
|
|
90
|
-
: toSqliteBindings(args);
|
|
91
|
-
const { rows, columns } = await target.execute(
|
|
92
|
-
query,
|
|
93
|
-
bindings,
|
|
94
|
-
);
|
|
95
|
-
return rows.map((row) =>
|
|
96
|
-
rowToObject<TRow>(row, columns),
|
|
112
|
+
stateTransactionContext?: NativeStateTransactionContext,
|
|
113
|
+
): RawAccess => {
|
|
114
|
+
const client: RawAccess = {
|
|
115
|
+
execute: async <
|
|
116
|
+
TRow extends Record<string, unknown> = Record<
|
|
117
|
+
string,
|
|
118
|
+
unknown
|
|
119
|
+
>,
|
|
120
|
+
>(
|
|
121
|
+
query: string,
|
|
122
|
+
...args: unknown[]
|
|
123
|
+
): Promise<TRow[]> => {
|
|
124
|
+
ensureOpen();
|
|
125
|
+
if (
|
|
126
|
+
!transactionScoped &&
|
|
127
|
+
warnOnManualTransactions &&
|
|
128
|
+
!manualTransactionWarned &&
|
|
129
|
+
!hasMultipleStatements(query) &&
|
|
130
|
+
isManualTransactionControl(query)
|
|
131
|
+
) {
|
|
132
|
+
manualTransactionWarned = true;
|
|
133
|
+
getLogger("database").warn(
|
|
134
|
+
{ actorId: ctx.actorId },
|
|
135
|
+
"Manual cross-call SQLite transactions can interleave with other actor work. Use db.transaction() for coordinated transactions. Set warnOnManualTransactions: false in your db(...) configuration to disable this warning.",
|
|
97
136
|
);
|
|
98
137
|
}
|
|
99
138
|
|
|
100
|
-
|
|
101
|
-
|
|
139
|
+
const kvReadsBefore = ctx.metrics?.totalKvReads ?? 0;
|
|
140
|
+
const kvWritesBefore = ctx.metrics?.totalKvWrites ?? 0;
|
|
141
|
+
const start = performance.now();
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
if (args.length > 0) {
|
|
145
|
+
const bindings =
|
|
146
|
+
args.length === 1 &&
|
|
147
|
+
isSqliteBindingObject(args[0])
|
|
148
|
+
? toSqliteBindings(args[0])
|
|
149
|
+
: toSqliteBindings(args);
|
|
150
|
+
const { rows, columns } = await target.execute(
|
|
151
|
+
query,
|
|
152
|
+
bindings,
|
|
153
|
+
);
|
|
154
|
+
return rows.map((row) =>
|
|
155
|
+
rowToObject<TRow>(row, columns),
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!hasMultipleStatements(query)) {
|
|
160
|
+
const { rows, columns } = await target.execute(
|
|
161
|
+
query,
|
|
162
|
+
undefined,
|
|
163
|
+
);
|
|
164
|
+
return rows.map((row) =>
|
|
165
|
+
rowToObject<TRow>(row, columns),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return await execMultiStatement<TRow>(
|
|
170
|
+
target,
|
|
102
171
|
query,
|
|
103
|
-
undefined,
|
|
104
|
-
);
|
|
105
|
-
return rows.map((row) =>
|
|
106
|
-
rowToObject<TRow>(row, columns),
|
|
107
172
|
);
|
|
173
|
+
} finally {
|
|
174
|
+
const durationMs = performance.now() - start;
|
|
175
|
+
ctx.metrics?.trackSql(query, durationMs);
|
|
176
|
+
if (ctx.metrics) {
|
|
177
|
+
const kvReads =
|
|
178
|
+
ctx.metrics.totalKvReads - kvReadsBefore;
|
|
179
|
+
const kvWrites =
|
|
180
|
+
ctx.metrics.totalKvWrites - kvWritesBefore;
|
|
181
|
+
ctx.log?.debug({
|
|
182
|
+
msg: "sql query",
|
|
183
|
+
query: query.slice(0, 120),
|
|
184
|
+
durationMs,
|
|
185
|
+
kvReads,
|
|
186
|
+
kvWrites,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
108
189
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
kvReads,
|
|
124
|
-
kvWrites,
|
|
125
|
-
});
|
|
190
|
+
},
|
|
191
|
+
transaction: async <T>(
|
|
192
|
+
callback: (tx: RawAccess) => Promise<T> | T,
|
|
193
|
+
options?: SqliteTransactionOptions,
|
|
194
|
+
): Promise<T> => {
|
|
195
|
+
validateTransactionTimeout(options?.timeout);
|
|
196
|
+
validateTransactionName(options?.name);
|
|
197
|
+
if (
|
|
198
|
+
transactionScoped &&
|
|
199
|
+
options?.experimental?.includeState
|
|
200
|
+
) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
"experimental.includeState is not supported for nested transactions",
|
|
203
|
+
);
|
|
126
204
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
validateTransactionTimeout(options?.timeout);
|
|
134
|
-
const transaction = await db.beginTransaction(
|
|
135
|
-
options?.timeout,
|
|
136
|
-
);
|
|
137
|
-
const tx = createClient(transaction, true);
|
|
138
|
-
try {
|
|
139
|
-
const result = await callback(tx);
|
|
140
|
-
await transaction.commit();
|
|
141
|
-
return result;
|
|
142
|
-
} catch (error) {
|
|
205
|
+
const includeState =
|
|
206
|
+
options?.experimental?.includeState === true;
|
|
207
|
+
const stateScope =
|
|
208
|
+
includeState && stateTransactionContext
|
|
209
|
+
? await stateTransactionContext.enter()
|
|
210
|
+
: undefined;
|
|
143
211
|
try {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
212
|
+
const transaction = includeState
|
|
213
|
+
? await (() => {
|
|
214
|
+
const beginStateTransaction =
|
|
215
|
+
ctx.nativeDatabaseProvider &&
|
|
216
|
+
nativeStateTransactionOpeners.get(
|
|
217
|
+
ctx.nativeDatabaseProvider,
|
|
218
|
+
);
|
|
219
|
+
if (!beginStateTransaction) {
|
|
220
|
+
throw new Error(
|
|
221
|
+
"experimental.includeState is only supported by RivetKit's embedded database provider",
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
return beginStateTransaction(
|
|
225
|
+
options?.timeout,
|
|
226
|
+
stateScope,
|
|
227
|
+
);
|
|
228
|
+
})()
|
|
229
|
+
: await db.beginTransaction(
|
|
230
|
+
options?.timeout,
|
|
231
|
+
options?.name,
|
|
232
|
+
);
|
|
233
|
+
const tx = createClient(transaction, true);
|
|
234
|
+
try {
|
|
235
|
+
const result = await callback(tx);
|
|
236
|
+
await transaction.commit();
|
|
237
|
+
return result;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
try {
|
|
240
|
+
await transaction.rollback();
|
|
241
|
+
} catch {
|
|
242
|
+
// Preserve the callback or commit error after expiry cleanup.
|
|
243
|
+
}
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
} finally {
|
|
247
|
+
if (stateScope !== undefined) {
|
|
248
|
+
stateTransactionContext?.exit(stateScope);
|
|
249
|
+
}
|
|
147
250
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
251
|
+
},
|
|
252
|
+
close: async () => {
|
|
253
|
+
if (!closed) {
|
|
254
|
+
closed = true;
|
|
255
|
+
await db.close();
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
nativeMetrics: () => db.nativeMetrics?.() ?? null,
|
|
259
|
+
};
|
|
260
|
+
if (!transactionScoped) {
|
|
261
|
+
nativeStateTransactionClientBinders.set(client, (context) =>
|
|
262
|
+
createClient(target, false, context),
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return client;
|
|
266
|
+
};
|
|
159
267
|
const client = createClient(db);
|
|
160
268
|
return client;
|
|
161
269
|
},
|
|
@@ -167,6 +275,7 @@ export function db({
|
|
|
167
275
|
}
|
|
168
276
|
},
|
|
169
277
|
};
|
|
278
|
+
return provider;
|
|
170
279
|
}
|
|
171
280
|
|
|
172
281
|
function rowToObject<TRow extends Record<string, unknown>>(
|
|
@@ -221,6 +330,9 @@ async function withMigrationSavepoint<T>(
|
|
|
221
330
|
throw error;
|
|
222
331
|
}
|
|
223
332
|
},
|
|
224
|
-
{
|
|
333
|
+
{
|
|
334
|
+
name: "rivetkit-migration",
|
|
335
|
+
timeout: MIGRATION_TRANSACTION_TIMEOUT_MS,
|
|
336
|
+
},
|
|
225
337
|
);
|
|
226
338
|
}
|
|
@@ -81,7 +81,14 @@ export interface JsNativeDatabaseLike {
|
|
|
81
81
|
executeBatch?(
|
|
82
82
|
statements: NativeBatchStatement[],
|
|
83
83
|
): Promise<NativeExecuteResult[]>;
|
|
84
|
-
|
|
84
|
+
beginStateTransaction?(
|
|
85
|
+
timeoutMs?: number,
|
|
86
|
+
context?: unknown,
|
|
87
|
+
): Promise<JsNativeTransactionLike>;
|
|
88
|
+
beginTransaction(
|
|
89
|
+
timeoutMs?: number,
|
|
90
|
+
name?: string,
|
|
91
|
+
): Promise<JsNativeTransactionLike>;
|
|
85
92
|
query(
|
|
86
93
|
sql: string,
|
|
87
94
|
params?: NativeBindParam[] | null,
|
|
@@ -94,6 +101,12 @@ export interface JsNativeDatabaseLike {
|
|
|
94
101
|
takeLastKvError?(): string | null;
|
|
95
102
|
close(): Promise<void>;
|
|
96
103
|
}
|
|
104
|
+
export type StateAwareSqliteDatabase = SqliteDatabase & {
|
|
105
|
+
beginStateTransaction(
|
|
106
|
+
timeoutMs?: number,
|
|
107
|
+
context?: unknown,
|
|
108
|
+
): Promise<SqliteTransactionDatabase>;
|
|
109
|
+
};
|
|
97
110
|
|
|
98
111
|
export interface JsNativeTransactionLike {
|
|
99
112
|
exec(sql: string): Promise<NativeExecResult>;
|
|
@@ -312,7 +325,7 @@ class NativeCloseGate {
|
|
|
312
325
|
|
|
313
326
|
export function wrapJsNativeDatabase(
|
|
314
327
|
database: JsNativeDatabaseLike,
|
|
315
|
-
):
|
|
328
|
+
): StateAwareSqliteDatabase {
|
|
316
329
|
const gate = new NativeCloseGate();
|
|
317
330
|
let closePromise: Promise<void> | undefined;
|
|
318
331
|
let lastInsertRowId: number | null = null;
|
|
@@ -419,11 +432,37 @@ export function wrapJsNativeDatabase(
|
|
|
419
432
|
},
|
|
420
433
|
async beginTransaction(
|
|
421
434
|
timeoutMs?: number,
|
|
435
|
+
name?: string,
|
|
422
436
|
): Promise<SqliteTransactionDatabase> {
|
|
423
437
|
const release = gate.enter();
|
|
424
438
|
let transaction: JsNativeTransactionLike;
|
|
425
439
|
try {
|
|
426
|
-
transaction = await database.beginTransaction(timeoutMs);
|
|
440
|
+
transaction = await database.beginTransaction(timeoutMs, name);
|
|
441
|
+
} catch (error) {
|
|
442
|
+
enrichNativeDatabaseError(database, error);
|
|
443
|
+
} finally {
|
|
444
|
+
release();
|
|
445
|
+
}
|
|
446
|
+
return wrapTransaction(database, transaction, gate, (result) => {
|
|
447
|
+
if (result.lastInsertRowId !== undefined) {
|
|
448
|
+
lastInsertRowId = result.lastInsertRowId;
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
},
|
|
452
|
+
async beginStateTransaction(
|
|
453
|
+
timeoutMs?: number,
|
|
454
|
+
context?: unknown,
|
|
455
|
+
): Promise<SqliteTransactionDatabase> {
|
|
456
|
+
if (!database.beginStateTransaction) {
|
|
457
|
+
throw new Error("actor state transactions are not configured");
|
|
458
|
+
}
|
|
459
|
+
const release = gate.enter();
|
|
460
|
+
let transaction: JsNativeTransactionLike;
|
|
461
|
+
try {
|
|
462
|
+
transaction = await database.beginStateTransaction(
|
|
463
|
+
timeoutMs,
|
|
464
|
+
context,
|
|
465
|
+
);
|
|
427
466
|
} catch (error) {
|
|
428
467
|
enrichNativeDatabaseError(database, error);
|
|
429
468
|
} finally {
|
|
@@ -15,6 +15,15 @@ export function validateTransactionTimeout(timeout: number | undefined): void {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export function validateTransactionName(name: string | undefined): void {
|
|
19
|
+
if (name === undefined) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (name.length === 0) {
|
|
23
|
+
throw new Error("db.transaction() name must not be empty");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
type SqliteBindingObject = Record<string, unknown>;
|
|
19
28
|
|
|
20
29
|
function isSqliteBindingValue(value: unknown): boolean {
|
package/src/db/drizzle.test.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { db } from "./drizzle";
|
|
|
12
12
|
class FakeSqliteDatabase implements SqliteDatabase {
|
|
13
13
|
executeCalls: Array<{ sql: string; params?: SqliteBindings }> = [];
|
|
14
14
|
transactionTimeouts: Array<number | undefined> = [];
|
|
15
|
+
transactionNames: Array<string | undefined> = [];
|
|
15
16
|
|
|
16
17
|
async exec(): Promise<void> {}
|
|
17
18
|
|
|
@@ -44,8 +45,10 @@ class FakeSqliteDatabase implements SqliteDatabase {
|
|
|
44
45
|
|
|
45
46
|
async beginTransaction(
|
|
46
47
|
timeoutMs?: number,
|
|
48
|
+
name?: string,
|
|
47
49
|
): Promise<SqliteTransactionDatabase> {
|
|
48
50
|
this.transactionTimeouts.push(timeoutMs);
|
|
51
|
+
this.transactionNames.push(name);
|
|
49
52
|
this.executeCalls.push({ sql: "BEGIN" });
|
|
50
53
|
return {
|
|
51
54
|
exec: async () => {},
|
|
@@ -114,6 +117,9 @@ describe("Drizzle database transactions", () => {
|
|
|
114
117
|
await provider.onMigrate(client);
|
|
115
118
|
|
|
116
119
|
expect(nativeDb.transactionTimeouts).toEqual([300_000]);
|
|
120
|
+
expect(nativeDb.transactionNames).toEqual([
|
|
121
|
+
"rivetkit-drizzle-migration",
|
|
122
|
+
]);
|
|
117
123
|
expect(nativeDb.executeCalls.map(({ sql }) => sql)).toEqual([
|
|
118
124
|
"BEGIN",
|
|
119
125
|
"SAVEPOINT __rivet_on_migrate",
|
|
@@ -133,10 +139,11 @@ describe("Drizzle database transactions", () => {
|
|
|
133
139
|
"inside",
|
|
134
140
|
);
|
|
135
141
|
},
|
|
136
|
-
{ timeout: 120_000 },
|
|
142
|
+
{ name: "drizzle-insert", timeout: 120_000 },
|
|
137
143
|
);
|
|
138
144
|
|
|
139
145
|
expect(nativeDb.transactionTimeouts).toEqual([120_000]);
|
|
146
|
+
expect(nativeDb.transactionNames).toEqual(["drizzle-insert"]);
|
|
140
147
|
expect(nativeDb.executeCalls.map(({ sql }) => sql)).toEqual([
|
|
141
148
|
"BEGIN",
|
|
142
149
|
"INSERT INTO items(value) VALUES (?)",
|
package/src/db/drizzle.ts
CHANGED
|
@@ -7,6 +7,8 @@ import type {
|
|
|
7
7
|
DatabaseProvider,
|
|
8
8
|
DatabaseProviderContext,
|
|
9
9
|
RawAccess,
|
|
10
|
+
SqliteProfilingOptions,
|
|
11
|
+
SqliteTransactionOptions,
|
|
10
12
|
SqliteDatabase,
|
|
11
13
|
SqliteTransactionDatabase,
|
|
12
14
|
} from "@/common/database/config";
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
isManualTransactionControl,
|
|
16
18
|
MIGRATION_TRANSACTION_TIMEOUT_MS,
|
|
17
19
|
toSqliteBindings,
|
|
20
|
+
validateTransactionName,
|
|
18
21
|
validateTransactionTimeout,
|
|
19
22
|
} from "@/common/database/shared";
|
|
20
23
|
import { sha256Hex } from "@/utils/crypto";
|
|
@@ -42,7 +45,7 @@ type DrizzleDatabase<TSchema extends DrizzleSchema> = Omit<
|
|
|
42
45
|
Omit<RawAccess, "transaction"> & {
|
|
43
46
|
transaction: <T>(
|
|
44
47
|
callback: (tx: DrizzleDatabase<TSchema>) => Promise<T> | T,
|
|
45
|
-
options?:
|
|
48
|
+
options?: SqliteTransactionOptions,
|
|
46
49
|
) => Promise<T>;
|
|
47
50
|
};
|
|
48
51
|
|
|
@@ -58,11 +61,12 @@ interface DrizzleMigrations {
|
|
|
58
61
|
migrations: Record<string, string>;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
interface DrizzleDatabaseFactoryConfig<TSchema extends DrizzleSchema> {
|
|
64
|
+
export interface DrizzleDatabaseFactoryConfig<TSchema extends DrizzleSchema> {
|
|
62
65
|
schema?: TSchema;
|
|
63
66
|
migrations?: DrizzleMigrations;
|
|
64
67
|
onMigrate?: (db: DrizzleDatabase<TSchema>) => Promise<void> | void;
|
|
65
68
|
warnOnManualTransactions?: boolean;
|
|
69
|
+
profiling?: SqliteProfilingOptions;
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
interface DrizzleKitConfig {
|
|
@@ -86,10 +90,12 @@ export function db<TSchema extends DrizzleSchema = Record<string, never>>({
|
|
|
86
90
|
migrations,
|
|
87
91
|
onMigrate,
|
|
88
92
|
warnOnManualTransactions = true,
|
|
93
|
+
profiling,
|
|
89
94
|
}: DrizzleDatabaseFactoryConfig<TSchema> = {}): DatabaseProvider<
|
|
90
95
|
DrizzleDatabase<TSchema>
|
|
91
96
|
> {
|
|
92
97
|
return {
|
|
98
|
+
sqliteProfiling: profiling,
|
|
93
99
|
createClient: async (ctx) => {
|
|
94
100
|
const override = ctx.overrideDrizzleDatabaseClient
|
|
95
101
|
? await ctx.overrideDrizzleDatabaseClient()
|
|
@@ -194,11 +200,13 @@ export function db<TSchema extends DrizzleSchema = Record<string, never>>({
|
|
|
194
200
|
transactionCallback: (
|
|
195
201
|
tx: DrizzleDatabase<TSchema>,
|
|
196
202
|
) => Promise<T> | T,
|
|
197
|
-
options?:
|
|
203
|
+
options?: SqliteTransactionOptions,
|
|
198
204
|
): Promise<T> => {
|
|
199
205
|
validateTransactionTimeout(options?.timeout);
|
|
206
|
+
validateTransactionName(options?.name);
|
|
200
207
|
const transaction = await nativeDb.beginTransaction(
|
|
201
208
|
options?.timeout,
|
|
209
|
+
options?.name,
|
|
202
210
|
);
|
|
203
211
|
const tx = createDrizzleClient(transaction, true);
|
|
204
212
|
try {
|
|
@@ -286,7 +294,10 @@ async function withMigrationSavepoint<TSchema extends DrizzleSchema, T>(
|
|
|
286
294
|
throw error;
|
|
287
295
|
}
|
|
288
296
|
},
|
|
289
|
-
{
|
|
297
|
+
{
|
|
298
|
+
name: "rivetkit-drizzle-migration",
|
|
299
|
+
timeout: MIGRATION_TRANSACTION_TIMEOUT_MS,
|
|
300
|
+
},
|
|
290
301
|
);
|
|
291
302
|
}
|
|
292
303
|
|
package/src/db/mod.ts
CHANGED
|
@@ -2,12 +2,15 @@ export type {
|
|
|
2
2
|
AnyDatabaseProvider,
|
|
3
3
|
DatabaseProvider,
|
|
4
4
|
DatabaseProviderContext,
|
|
5
|
+
InferDatabaseClient,
|
|
5
6
|
NativeDatabaseProvider,
|
|
6
7
|
RawAccess,
|
|
7
8
|
RawDatabaseClient,
|
|
8
9
|
SqliteBindings,
|
|
9
10
|
SqliteDatabase,
|
|
10
11
|
SqliteNativeMetrics,
|
|
12
|
+
SqliteProfilingOptions,
|
|
11
13
|
SqliteQueryResult,
|
|
14
|
+
SqliteTransactionOptions,
|
|
12
15
|
} from "@/common/database/config";
|
|
13
16
|
export { db } from "@/common/database/mod";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { JsonCompatValue } from "@/common/encoding";
|
|
2
|
+
import type { WorkflowHistoryBytes } from "@/common/inspector-transport";
|
|
3
|
+
import { encodeCborCompat } from "@/serde";
|
|
4
|
+
import { bufferToArrayBuffer } from "@/utils";
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
WorkflowBranchStatus,
|
|
8
|
+
WorkflowCbor,
|
|
9
|
+
WorkflowEntry,
|
|
10
|
+
WorkflowEntryKind,
|
|
11
|
+
WorkflowEntryMetadata,
|
|
12
|
+
WorkflowHistory,
|
|
13
|
+
WorkflowJoinEntry,
|
|
14
|
+
WorkflowLocation,
|
|
15
|
+
WorkflowLoopEntry,
|
|
16
|
+
WorkflowLoopIterationMarker,
|
|
17
|
+
WorkflowMessageEntry,
|
|
18
|
+
WorkflowNameIndex,
|
|
19
|
+
WorkflowPathSegment,
|
|
20
|
+
WorkflowRaceEntry,
|
|
21
|
+
WorkflowRemovedEntry,
|
|
22
|
+
WorkflowRollbackCheckpointEntry,
|
|
23
|
+
WorkflowSleepEntry,
|
|
24
|
+
WorkflowStepEntry,
|
|
25
|
+
WorkflowVersionCheckEntry,
|
|
26
|
+
} from "@/common/bare/transport/v1";
|
|
27
|
+
export {
|
|
28
|
+
WorkflowBranchStatusType,
|
|
29
|
+
WorkflowEntryStatus,
|
|
30
|
+
WorkflowSleepState,
|
|
31
|
+
} from "@/common/bare/transport/v1";
|
|
32
|
+
export type { WorkflowHistoryBytes } from "@/common/inspector-transport";
|
|
33
|
+
export {
|
|
34
|
+
decodeWorkflowHistoryTransport,
|
|
35
|
+
encodeWorkflowHistoryTransport,
|
|
36
|
+
} from "@/common/inspector-transport";
|
|
37
|
+
|
|
38
|
+
/** @experimental State exposed by a durable workflow run handler to the Inspector. */
|
|
39
|
+
export type WorkflowState =
|
|
40
|
+
| "pending"
|
|
41
|
+
| "running"
|
|
42
|
+
| "sleeping"
|
|
43
|
+
| "failed"
|
|
44
|
+
| "completed"
|
|
45
|
+
| "cancelled"
|
|
46
|
+
| "rolling_back";
|
|
47
|
+
|
|
48
|
+
/** @experimental The raw workflow Inspector adapter consumed by RivetKit's transport. */
|
|
49
|
+
export interface WorkflowInspectorAdapter {
|
|
50
|
+
getHistory: () => WorkflowHistoryBytes | null;
|
|
51
|
+
getState: () => Promise<WorkflowState | null>;
|
|
52
|
+
onHistoryUpdated: (
|
|
53
|
+
listener: (history: WorkflowHistoryBytes) => void,
|
|
54
|
+
) => () => void;
|
|
55
|
+
replayFromStep: (entryId?: string) => Promise<WorkflowHistoryBytes | null>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** @experimental Encodes a workflow Inspector value with RivetKit's CBOR-compatible codec. */
|
|
59
|
+
export function encodeWorkflowInspectorValue(value: unknown): ArrayBuffer {
|
|
60
|
+
return bufferToArrayBuffer(encodeCborCompat(value as JsonCompatValue));
|
|
61
|
+
}
|