@rivetkit/workflow-engine 0.0.0-sqlite-profiling-compat.4a9a623 → 0.0.0-sqlite-sync-3x-release.a00b07f
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/schemas/v1.ts +25 -0
- package/dist/tsup/{chunk-KA2T56AJ.js → chunk-AAAPEYGX.js} +221 -44
- package/dist/tsup/chunk-AAAPEYGX.js.map +1 -0
- package/dist/tsup/{chunk-GQWOLYBA.cjs → chunk-XRITRTKT.cjs} +221 -44
- package/dist/tsup/chunk-XRITRTKT.cjs.map +1 -0
- package/dist/tsup/index.cjs +2 -2
- package/dist/tsup/index.cjs.map +1 -1
- package/dist/tsup/index.d.cts +65 -3
- package/dist/tsup/index.d.ts +65 -3
- package/dist/tsup/index.js +1 -1
- package/dist/tsup/testing.cjs +29 -23
- package/dist/tsup/testing.cjs.map +1 -1
- package/dist/tsup/testing.d.cts +2 -1
- package/dist/tsup/testing.d.ts +2 -1
- package/dist/tsup/testing.js +7 -1
- package/dist/tsup/testing.js.map +1 -1
- package/package.json +2 -2
- package/schemas/serde.ts +16 -0
- package/schemas/v1.bare +10 -1
- package/schemas/versioned.ts +1 -0
- package/src/context.ts +108 -2
- package/src/driver.ts +51 -0
- package/src/index.ts +88 -22
- package/src/keys.ts +1 -0
- package/src/storage.ts +52 -16
- package/src/testing.ts +7 -0
- package/src/types.ts +17 -2
- package/dist/tsup/chunk-GQWOLYBA.cjs.map +0 -1
- package/dist/tsup/chunk-KA2T56AJ.js.map +0 -1
package/src/storage.ts
CHANGED
|
@@ -43,6 +43,9 @@ import type {
|
|
|
43
43
|
export const MAX_KV_BATCH_ENTRIES = 128;
|
|
44
44
|
export const MAX_KV_BATCH_PAYLOAD_BYTES = 976 * 1024;
|
|
45
45
|
|
|
46
|
+
/** Max delete ops (one transaction/permit each) run at once, under the 128-permit cap. */
|
|
47
|
+
export const MAX_CONCURRENT_DELETES = 64;
|
|
48
|
+
|
|
46
49
|
/**
|
|
47
50
|
* Create an empty storage instance.
|
|
48
51
|
*/
|
|
@@ -318,26 +321,20 @@ export async function flush(
|
|
|
318
321
|
}
|
|
319
322
|
|
|
320
323
|
if (writes.length > 0) {
|
|
321
|
-
|
|
322
|
-
await driver.batch(
|
|
324
|
+
if (driver.atomicBatch) {
|
|
325
|
+
await driver.batch(writes);
|
|
326
|
+
} else {
|
|
327
|
+
for (const chunk of splitBatchWrites(writes)) {
|
|
328
|
+
await driver.batch(chunk);
|
|
329
|
+
}
|
|
323
330
|
}
|
|
324
331
|
}
|
|
325
332
|
|
|
326
333
|
// Apply pending deletions after the batch write. These are collected
|
|
327
334
|
// by collectLoopPruning so pruning happens alongside the state write.
|
|
328
335
|
if (pendingDeletions) {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
deleteOps.push(driver.deletePrefix(prefix));
|
|
332
|
-
}
|
|
333
|
-
for (const range of pendingDeletions.ranges) {
|
|
334
|
-
deleteOps.push(driver.deleteRange(range.start, range.end));
|
|
335
|
-
}
|
|
336
|
-
for (const key of pendingDeletions.keys) {
|
|
337
|
-
deleteOps.push(driver.delete(key));
|
|
338
|
-
}
|
|
339
|
-
if (deleteOps.length > 0) {
|
|
340
|
-
await Promise.all(deleteOps);
|
|
336
|
+
const didChange = await runDeletes(driver, pendingDeletions);
|
|
337
|
+
if (didChange) {
|
|
341
338
|
historyUpdated = true;
|
|
342
339
|
}
|
|
343
340
|
}
|
|
@@ -393,6 +390,46 @@ function splitBatchWrites(writes: KVWrite[]): KVWrite[][] {
|
|
|
393
390
|
return chunks;
|
|
394
391
|
}
|
|
395
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Split delete keys into batches within one KV transaction (MAX_KV_BATCH_ENTRIES).
|
|
395
|
+
*/
|
|
396
|
+
function splitBatchDeletes(keys: Uint8Array[]): Uint8Array[][] {
|
|
397
|
+
const chunks: Uint8Array[][] = [];
|
|
398
|
+
for (let i = 0; i < keys.length; i += MAX_KV_BATCH_ENTRIES) {
|
|
399
|
+
chunks.push(keys.slice(i, i + MAX_KV_BATCH_ENTRIES));
|
|
400
|
+
}
|
|
401
|
+
return chunks;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Apply deletions concurrently in bounded rounds; returns whether anything was deleted.
|
|
406
|
+
*/
|
|
407
|
+
async function runDeletes(
|
|
408
|
+
driver: EngineDriver,
|
|
409
|
+
deletions: PendingDeletions,
|
|
410
|
+
): Promise<boolean> {
|
|
411
|
+
const ops = [
|
|
412
|
+
...deletions.prefixes.map(
|
|
413
|
+
(prefix) => () => driver.deletePrefix(prefix),
|
|
414
|
+
),
|
|
415
|
+
...deletions.ranges.map(
|
|
416
|
+
(range) => () => driver.deleteRange(range.start, range.end),
|
|
417
|
+
),
|
|
418
|
+
...splitBatchDeletes(deletions.keys).map(
|
|
419
|
+
(chunk) => () => driver.batchDelete(chunk),
|
|
420
|
+
),
|
|
421
|
+
];
|
|
422
|
+
if (ops.length === 0) {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
for (let i = 0; i < ops.length; i += MAX_CONCURRENT_DELETES) {
|
|
426
|
+
await Promise.all(
|
|
427
|
+
ops.slice(i, i + MAX_CONCURRENT_DELETES).map((op) => op()),
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
|
|
396
433
|
/**
|
|
397
434
|
* Delete entries with a given location prefix (used for loop forgetting).
|
|
398
435
|
* Also cleans up associated metadata from both memory and driver.
|
|
@@ -406,8 +443,7 @@ export async function deleteEntriesWithPrefix(
|
|
|
406
443
|
const deletions = collectDeletionsForPrefix(storage, prefixLocation);
|
|
407
444
|
|
|
408
445
|
// Apply deletions to driver
|
|
409
|
-
await driver
|
|
410
|
-
await Promise.all(deletions.keys.map((key) => driver.delete(key)));
|
|
446
|
+
await runDeletes(driver, deletions);
|
|
411
447
|
|
|
412
448
|
if (deletions.keys.length > 0 && onHistoryUpdated) {
|
|
413
449
|
onHistoryUpdated();
|
package/src/testing.ts
CHANGED
|
@@ -173,6 +173,13 @@ export class InMemoryDriver implements EngineDriver {
|
|
|
173
173
|
this.kv.delete(keyToHex(key));
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
async batchDelete(keys: Uint8Array[]): Promise<void> {
|
|
177
|
+
await sleep(this.latency);
|
|
178
|
+
for (const key of keys) {
|
|
179
|
+
this.kv.delete(keyToHex(key));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
176
183
|
async deletePrefix(prefix: Uint8Array): Promise<void> {
|
|
177
184
|
await sleep(this.latency);
|
|
178
185
|
for (const [hexKey, entry] of this.kv) {
|
package/src/types.ts
CHANGED
|
@@ -135,6 +135,17 @@ export interface RemovedEntry {
|
|
|
135
135
|
originalName?: string;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Version check entry data - records which version of a code path this
|
|
140
|
+
* workflow instance is pinned to at a given location.
|
|
141
|
+
*/
|
|
142
|
+
export interface VersionCheckEntry {
|
|
143
|
+
/** The version this instance resolved to at this location. */
|
|
144
|
+
resolved: number;
|
|
145
|
+
/** The `latest` value seen when this entry was first resolved (diagnostics). */
|
|
146
|
+
latest: number;
|
|
147
|
+
}
|
|
148
|
+
|
|
138
149
|
/**
|
|
139
150
|
* All possible entry kind types.
|
|
140
151
|
*/
|
|
@@ -146,7 +157,8 @@ export type EntryKindType =
|
|
|
146
157
|
| "rollback_checkpoint"
|
|
147
158
|
| "join"
|
|
148
159
|
| "race"
|
|
149
|
-
| "removed"
|
|
160
|
+
| "removed"
|
|
161
|
+
| "version_check";
|
|
150
162
|
|
|
151
163
|
/**
|
|
152
164
|
* Type-specific entry data.
|
|
@@ -159,7 +171,8 @@ export type EntryKind =
|
|
|
159
171
|
| { type: "rollback_checkpoint"; data: RollbackCheckpointEntry }
|
|
160
172
|
| { type: "join"; data: JoinEntry }
|
|
161
173
|
| { type: "race"; data: RaceEntry }
|
|
162
|
-
| { type: "removed"; data: RemovedEntry }
|
|
174
|
+
| { type: "removed"; data: RemovedEntry }
|
|
175
|
+
| { type: "version_check"; data: VersionCheckEntry };
|
|
163
176
|
|
|
164
177
|
/**
|
|
165
178
|
* An entry in the workflow history.
|
|
@@ -539,6 +552,8 @@ export interface WorkflowContextInterface {
|
|
|
539
552
|
|
|
540
553
|
removed(name: string, originalType: EntryKindType): Promise<void>;
|
|
541
554
|
|
|
555
|
+
getVersion(name: string, latest: number): Promise<number>;
|
|
556
|
+
|
|
542
557
|
isEvicted(): boolean;
|
|
543
558
|
}
|
|
544
559
|
|