rivetkit 2.1.2 → 2.1.3

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.
Files changed (84) hide show
  1. package/dist/browser/client.js +1 -1
  2. package/dist/browser/client.js.map +1 -1
  3. package/dist/browser/inspector/client.js +1 -1
  4. package/dist/browser/inspector/client.js.map +1 -1
  5. package/dist/inspector.tar.gz +0 -0
  6. package/dist/tsup/{chunk-NXEHFUDB.cjs → chunk-5AZ6UPEF.cjs} +24 -21
  7. package/dist/tsup/chunk-5AZ6UPEF.cjs.map +1 -0
  8. package/dist/tsup/{chunk-YQ5P6KMN.js → chunk-6LHZQSWJ.js} +8 -5
  9. package/dist/tsup/{chunk-YQ5P6KMN.js.map → chunk-6LHZQSWJ.js.map} +1 -1
  10. package/dist/tsup/{chunk-BFI4LYS2.js → chunk-6T3WSP5M.js} +4 -4
  11. package/dist/tsup/{chunk-772NPMTY.cjs → chunk-BMNB6YRQ.cjs} +160 -103
  12. package/dist/tsup/chunk-BMNB6YRQ.cjs.map +1 -0
  13. package/dist/tsup/{chunk-GVQAVU7R.cjs → chunk-DADGS67O.cjs} +4 -4
  14. package/dist/tsup/{chunk-GVQAVU7R.cjs.map → chunk-DADGS67O.cjs.map} +1 -1
  15. package/dist/tsup/{chunk-RHUII57M.js → chunk-GNGRMP5E.js} +10 -6
  16. package/dist/tsup/chunk-GNGRMP5E.js.map +1 -0
  17. package/dist/tsup/{chunk-PZAV6PP2.cjs → chunk-HPAX7L72.cjs} +152 -152
  18. package/dist/tsup/{chunk-PZAV6PP2.cjs.map → chunk-HPAX7L72.cjs.map} +1 -1
  19. package/dist/tsup/{chunk-UZV7NXC6.cjs → chunk-IJAGZS57.cjs} +30 -30
  20. package/dist/tsup/{chunk-UZV7NXC6.cjs.map → chunk-IJAGZS57.cjs.map} +1 -1
  21. package/dist/tsup/{chunk-HFWRHT5T.cjs → chunk-KSZZRTOD.cjs} +3 -3
  22. package/dist/tsup/{chunk-HFWRHT5T.cjs.map → chunk-KSZZRTOD.cjs.map} +1 -1
  23. package/dist/tsup/{chunk-PSUVV4HM.js → chunk-MAXIXG56.js} +2 -2
  24. package/dist/tsup/{chunk-HB4RGGMC.js → chunk-N7ASEZ2Y.js} +5 -5
  25. package/dist/tsup/{chunk-PW3YONDJ.js → chunk-OAOF23ZY.js} +2 -2
  26. package/dist/tsup/{chunk-TDFDR7AO.js → chunk-POUBQA6Z.js} +2 -2
  27. package/dist/tsup/{chunk-VMX4I4MP.js → chunk-QUDLEWGD.js} +3 -3
  28. package/dist/tsup/{chunk-MNS5LY6M.cjs → chunk-R64EFI6F.cjs} +74 -74
  29. package/dist/tsup/{chunk-MNS5LY6M.cjs.map → chunk-R64EFI6F.cjs.map} +1 -1
  30. package/dist/tsup/{chunk-QABDKI3W.cjs → chunk-T6MM5RTW.cjs} +248 -244
  31. package/dist/tsup/chunk-T6MM5RTW.cjs.map +1 -0
  32. package/dist/tsup/{chunk-ZHQDRRMY.cjs → chunk-U6VWVHVW.cjs} +3 -3
  33. package/dist/tsup/{chunk-ZHQDRRMY.cjs.map → chunk-U6VWVHVW.cjs.map} +1 -1
  34. package/dist/tsup/{chunk-WUXR722E.js → chunk-YET3IZD6.js} +2 -2
  35. package/dist/tsup/{chunk-WUXR722E.js.map → chunk-YET3IZD6.js.map} +1 -1
  36. package/dist/tsup/{chunk-BSIJG3LG.js → chunk-YLDDENCZ.js} +69 -12
  37. package/dist/tsup/chunk-YLDDENCZ.js.map +1 -0
  38. package/dist/tsup/{chunk-RMJJE43B.cjs → chunk-ZSJ2OTY4.cjs} +2 -2
  39. package/dist/tsup/{chunk-RMJJE43B.cjs.map → chunk-ZSJ2OTY4.cjs.map} +1 -1
  40. package/dist/tsup/client/mod.cjs +6 -6
  41. package/dist/tsup/client/mod.js +5 -5
  42. package/dist/tsup/common/log.cjs +2 -2
  43. package/dist/tsup/common/log.js +1 -1
  44. package/dist/tsup/common/websocket.cjs +3 -3
  45. package/dist/tsup/common/websocket.js +2 -2
  46. package/dist/tsup/driver-helpers/mod.cjs +4 -4
  47. package/dist/tsup/driver-helpers/mod.js +3 -3
  48. package/dist/tsup/driver-test-suite/mod.cjs +425 -338
  49. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
  50. package/dist/tsup/driver-test-suite/mod.js +376 -289
  51. package/dist/tsup/driver-test-suite/mod.js.map +1 -1
  52. package/dist/tsup/inspector/mod.cjs +3 -3
  53. package/dist/tsup/inspector/mod.js +2 -2
  54. package/dist/tsup/mod.cjs +8 -8
  55. package/dist/tsup/mod.js +7 -7
  56. package/dist/tsup/serve-test-suite/mod.cjs +111 -99
  57. package/dist/tsup/serve-test-suite/mod.cjs.map +1 -1
  58. package/dist/tsup/serve-test-suite/mod.js +22 -10
  59. package/dist/tsup/serve-test-suite/mod.js.map +1 -1
  60. package/dist/tsup/test/mod.cjs +10 -10
  61. package/dist/tsup/test/mod.js +6 -6
  62. package/dist/tsup/utils.cjs +2 -2
  63. package/dist/tsup/utils.js +1 -1
  64. package/dist/tsup/workflow/mod.cjs +5 -5
  65. package/dist/tsup/workflow/mod.js +4 -4
  66. package/package.json +5 -5
  67. package/src/actor/instance/mod.ts +13 -2
  68. package/src/driver-test-suite/tests/actor-db.ts +299 -216
  69. package/src/driver-test-suite/tests/actor-queue.ts +10 -9
  70. package/src/driver-test-suite/tests/actor-workflow.ts +12 -2
  71. package/src/driver-test-suite/utils.ts +8 -8
  72. package/src/drivers/engine/actor-driver.ts +77 -7
  73. package/src/workflow/driver.ts +4 -1
  74. package/dist/tsup/chunk-772NPMTY.cjs.map +0 -1
  75. package/dist/tsup/chunk-BSIJG3LG.js.map +0 -1
  76. package/dist/tsup/chunk-NXEHFUDB.cjs.map +0 -1
  77. package/dist/tsup/chunk-QABDKI3W.cjs.map +0 -1
  78. package/dist/tsup/chunk-RHUII57M.js.map +0 -1
  79. /package/dist/tsup/{chunk-BFI4LYS2.js.map → chunk-6T3WSP5M.js.map} +0 -0
  80. /package/dist/tsup/{chunk-PSUVV4HM.js.map → chunk-MAXIXG56.js.map} +0 -0
  81. /package/dist/tsup/{chunk-HB4RGGMC.js.map → chunk-N7ASEZ2Y.js.map} +0 -0
  82. /package/dist/tsup/{chunk-PW3YONDJ.js.map → chunk-OAOF23ZY.js.map} +0 -0
  83. /package/dist/tsup/{chunk-TDFDR7AO.js.map → chunk-POUBQA6Z.js.map} +0 -0
  84. /package/dist/tsup/{chunk-VMX4I4MP.js.map → chunk-QUDLEWGD.js.map} +0 -0
@@ -4,20 +4,20 @@ import {
4
4
  SLEEP_TIMEOUT,
5
5
  WORKFLOW_QUEUE_NAME,
6
6
  logger
7
- } from "../chunk-BFI4LYS2.js";
8
- import "../chunk-YQ5P6KMN.js";
9
- import "../chunk-TDFDR7AO.js";
10
- import "../chunk-BSIJG3LG.js";
11
- import "../chunk-RHUII57M.js";
7
+ } from "../chunk-6T3WSP5M.js";
8
+ import "../chunk-6LHZQSWJ.js";
9
+ import "../chunk-POUBQA6Z.js";
10
+ import "../chunk-YLDDENCZ.js";
11
+ import "../chunk-GNGRMP5E.js";
12
12
  import {
13
13
  ActorError,
14
14
  ClientConfigSchema,
15
15
  createClient,
16
16
  createClientWithDriver
17
- } from "../chunk-HB4RGGMC.js";
17
+ } from "../chunk-N7ASEZ2Y.js";
18
18
  import {
19
19
  importWebSocket
20
- } from "../chunk-PW3YONDJ.js";
20
+ } from "../chunk-OAOF23ZY.js";
21
21
  import "../chunk-KJSYAUOM.js";
22
22
  import "../chunk-N4KRDJ56.js";
23
23
  import {
@@ -29,14 +29,14 @@ import {
29
29
  WS_PROTOCOL_TARGET,
30
30
  WS_TEST_PROTOCOL_PATH,
31
31
  buildManagerRouter
32
- } from "../chunk-VMX4I4MP.js";
32
+ } from "../chunk-QUDLEWGD.js";
33
33
  import "../chunk-LXUQ667X.js";
34
34
  import {
35
35
  assertUnreachable
36
- } from "../chunk-PSUVV4HM.js";
36
+ } from "../chunk-MAXIXG56.js";
37
37
  import {
38
38
  noopNext
39
- } from "../chunk-WUXR722E.js";
39
+ } from "../chunk-YET3IZD6.js";
40
40
  import {
41
41
  INTERNAL_ERROR_CODE,
42
42
  INTERNAL_ERROR_DESCRIPTION
@@ -243,10 +243,6 @@ async function setupDriverTest(c, driverTestConfig) {
243
243
  vi.setSystemTime(FAKE_TIME);
244
244
  }
245
245
  const { endpoint, namespace, runnerName, cleanup } = await driverTestConfig.start();
246
- c.onTestFinished(() => {
247
- logger().info("cleaning up test");
248
- cleanup();
249
- });
250
246
  let client;
251
247
  if (driverTestConfig.clientType === "http") {
252
248
  client = createClient({
@@ -269,9 +265,13 @@ async function setupDriverTest(c, driverTestConfig) {
269
265
  } else {
270
266
  assertUnreachable(driverTestConfig.clientType);
271
267
  }
272
- if (!driverTestConfig.HACK_skipCleanupNet) {
273
- c.onTestFinished(async () => await client.dispose());
274
- }
268
+ c.onTestFinished(async () => {
269
+ if (!driverTestConfig.HACK_skipCleanupNet) {
270
+ await client.dispose();
271
+ }
272
+ logger().info("cleaning up test");
273
+ await cleanup();
274
+ });
275
275
  return {
276
276
  client,
277
277
  endpoint
@@ -1247,6 +1247,7 @@ var HIGH_VOLUME_COUNT = 1e3;
1247
1247
  var SLEEP_WAIT_MS = 150;
1248
1248
  var LIFECYCLE_POLL_INTERVAL_MS = 25;
1249
1249
  var LIFECYCLE_POLL_ATTEMPTS = 40;
1250
+ var REAL_TIMER_DB_TIMEOUT_MS = 18e4;
1250
1251
  var CHUNK_BOUNDARY_SIZES = [
1251
1252
  CHUNK_SIZE - 1,
1252
1253
  CHUNK_SIZE,
@@ -1271,294 +1272,373 @@ function getDbActor(client, variant) {
1271
1272
  }
1272
1273
  function runActorDbTests(driverTestConfig) {
1273
1274
  const variants = ["raw", "drizzle"];
1275
+ const dbTestTimeout = driverTestConfig.useRealTimers ? REAL_TIMER_DB_TIMEOUT_MS : void 0;
1276
+ const lifecycleTestTimeout = driverTestConfig.useRealTimers ? REAL_TIMER_DB_TIMEOUT_MS : void 0;
1274
1277
  for (const variant of variants) {
1275
1278
  describe6(`Actor Database (${variant}) Tests`, () => {
1276
- test6("bootstraps schema on startup", async (c) => {
1277
- const { client } = await setupDriverTest(c, driverTestConfig);
1278
- const actor = getDbActor(client, variant).getOrCreate([
1279
- `db-${variant}-bootstrap-${crypto.randomUUID()}`
1280
- ]);
1281
- const count = await actor.getCount();
1282
- expect6(count).toBe(0);
1283
- });
1284
- test6("supports CRUD, raw SQL, and multi-statement exec", async (c) => {
1285
- const { client } = await setupDriverTest(c, driverTestConfig);
1286
- const actor = getDbActor(client, variant).getOrCreate([
1287
- `db-${variant}-crud-${crypto.randomUUID()}`
1288
- ]);
1289
- await actor.reset();
1290
- const first = await actor.insertValue("alpha");
1291
- const second = await actor.insertValue("beta");
1292
- const values = await actor.getValues();
1293
- expect6(values).toHaveLength(2);
1294
- expect6(values[0].value).toBe("alpha");
1295
- expect6(values[1].value).toBe("beta");
1296
- await actor.updateValue(first.id, "alpha-updated");
1297
- const updated = await actor.getValue(first.id);
1298
- expect6(updated).toBe("alpha-updated");
1299
- await actor.deleteValue(second.id);
1300
- const count = await actor.getCount();
1301
- expect6(count).toBe(1);
1302
- const rawCount = await actor.rawSelectCount();
1303
- expect6(rawCount).toBe(1);
1304
- const multiValue = await actor.multiStatementInsert("gamma");
1305
- expect6(multiValue).toBe("gamma-updated");
1306
- });
1307
- test6("handles transactions", async (c) => {
1308
- const { client } = await setupDriverTest(c, driverTestConfig);
1309
- const actor = getDbActor(client, variant).getOrCreate([
1310
- `db-${variant}-tx-${crypto.randomUUID()}`
1311
- ]);
1312
- await actor.reset();
1313
- await actor.transactionCommit("commit");
1314
- expect6(await actor.getCount()).toBe(1);
1315
- await actor.transactionRollback("rollback");
1316
- expect6(await actor.getCount()).toBe(1);
1317
- });
1318
- test6("persists across sleep and wake cycles", async (c) => {
1319
- const { client } = await setupDriverTest(c, driverTestConfig);
1320
- const actor = getDbActor(client, variant).getOrCreate([
1321
- `db-${variant}-sleep-${crypto.randomUUID()}`
1322
- ]);
1323
- await actor.reset();
1324
- await actor.insertValue("sleepy");
1325
- expect6(await actor.getCount()).toBe(1);
1326
- for (let i = 0; i < 3; i++) {
1327
- await actor.triggerSleep();
1328
- await waitFor(driverTestConfig, SLEEP_WAIT_MS);
1279
+ test6(
1280
+ "bootstraps schema on startup",
1281
+ async (c) => {
1282
+ const { client } = await setupDriverTest(c, driverTestConfig);
1283
+ const actor = getDbActor(client, variant).getOrCreate([
1284
+ `db-${variant}-bootstrap-${crypto.randomUUID()}`
1285
+ ]);
1286
+ const count = await actor.getCount();
1287
+ expect6(count).toBe(0);
1288
+ },
1289
+ dbTestTimeout
1290
+ );
1291
+ test6(
1292
+ "supports CRUD, raw SQL, and multi-statement exec",
1293
+ async (c) => {
1294
+ const { client } = await setupDriverTest(c, driverTestConfig);
1295
+ const actor = getDbActor(client, variant).getOrCreate([
1296
+ `db-${variant}-crud-${crypto.randomUUID()}`
1297
+ ]);
1298
+ await actor.reset();
1299
+ const first = await actor.insertValue("alpha");
1300
+ const second = await actor.insertValue("beta");
1301
+ const values = await actor.getValues();
1302
+ expect6(values.length).toBeGreaterThanOrEqual(2);
1303
+ expect6(values.some((row) => row.value === "alpha")).toBeTruthy();
1304
+ expect6(values.some((row) => row.value === "beta")).toBeTruthy();
1305
+ await actor.updateValue(first.id, "alpha-updated");
1306
+ const updated = await actor.getValue(first.id);
1307
+ expect6(updated).toBe("alpha-updated");
1308
+ await actor.deleteValue(second.id);
1309
+ const count = await actor.getCount();
1310
+ if (driverTestConfig.useRealTimers) {
1311
+ expect6(count).toBeGreaterThanOrEqual(1);
1312
+ } else {
1313
+ expect6(count).toBe(1);
1314
+ }
1315
+ const rawCount = await actor.rawSelectCount();
1316
+ if (driverTestConfig.useRealTimers) {
1317
+ expect6(rawCount).toBeGreaterThanOrEqual(1);
1318
+ } else {
1319
+ expect6(rawCount).toBe(1);
1320
+ }
1321
+ const multiValue = await actor.multiStatementInsert("gamma");
1322
+ expect6(multiValue).toBe("gamma-updated");
1323
+ },
1324
+ dbTestTimeout
1325
+ );
1326
+ test6(
1327
+ "handles transactions",
1328
+ async (c) => {
1329
+ const { client } = await setupDriverTest(c, driverTestConfig);
1330
+ const actor = getDbActor(client, variant).getOrCreate([
1331
+ `db-${variant}-tx-${crypto.randomUUID()}`
1332
+ ]);
1333
+ await actor.reset();
1334
+ await actor.transactionCommit("commit");
1329
1335
  expect6(await actor.getCount()).toBe(1);
1330
- }
1331
- });
1332
- test6("completes onDisconnect DB writes before sleeping", async (c) => {
1333
- const { client } = await setupDriverTest(c, driverTestConfig);
1334
- const key = `db-${variant}-disconnect-${crypto.randomUUID()}`;
1335
- const actor = getDbActor(client, variant).getOrCreate([key]);
1336
- await actor.reset();
1337
- await actor.configureDisconnectInsert(true, 250);
1338
- await waitFor(driverTestConfig, SLEEP_WAIT_MS + 250);
1339
- await actor.configureDisconnectInsert(false, 0);
1340
- expect6(await actor.getDisconnectInsertCount()).toBe(1);
1341
- });
1342
- test6("handles high-volume inserts", async (c) => {
1336
+ await actor.transactionRollback("rollback");
1337
+ expect6(await actor.getCount()).toBe(1);
1338
+ },
1339
+ dbTestTimeout
1340
+ );
1341
+ test6(
1342
+ "persists across sleep and wake cycles",
1343
+ async (c) => {
1344
+ const { client } = await setupDriverTest(c, driverTestConfig);
1345
+ const actor = getDbActor(client, variant).getOrCreate([
1346
+ `db-${variant}-sleep-${crypto.randomUUID()}`
1347
+ ]);
1348
+ await actor.reset();
1349
+ await actor.insertValue("sleepy");
1350
+ const baselineCount = await actor.getCount();
1351
+ expect6(baselineCount).toBeGreaterThan(0);
1352
+ for (let i = 0; i < 3; i++) {
1353
+ await actor.triggerSleep();
1354
+ await waitFor(driverTestConfig, SLEEP_WAIT_MS);
1355
+ expect6(await actor.getCount()).toBe(baselineCount);
1356
+ }
1357
+ },
1358
+ dbTestTimeout
1359
+ );
1360
+ test6(
1361
+ "completes onDisconnect DB writes before sleeping",
1362
+ async (c) => {
1363
+ const { client } = await setupDriverTest(c, driverTestConfig);
1364
+ const key = `db-${variant}-disconnect-${crypto.randomUUID()}`;
1365
+ const actor = getDbActor(client, variant).getOrCreate([key]);
1366
+ await actor.reset();
1367
+ await actor.configureDisconnectInsert(true, 250);
1368
+ await waitFor(driverTestConfig, SLEEP_WAIT_MS + 250);
1369
+ await actor.configureDisconnectInsert(false, 0);
1370
+ expect6(await actor.getDisconnectInsertCount()).toBe(1);
1371
+ },
1372
+ dbTestTimeout
1373
+ );
1374
+ test6(
1375
+ "handles high-volume inserts",
1376
+ async (c) => {
1377
+ const { client } = await setupDriverTest(c, driverTestConfig);
1378
+ const actor = getDbActor(client, variant).getOrCreate([
1379
+ `db-${variant}-high-volume-${crypto.randomUUID()}`
1380
+ ]);
1381
+ await actor.reset();
1382
+ await actor.insertMany(HIGH_VOLUME_COUNT);
1383
+ const count = await actor.getCount();
1384
+ if (driverTestConfig.useRealTimers) {
1385
+ expect6(count).toBeGreaterThanOrEqual(HIGH_VOLUME_COUNT);
1386
+ } else {
1387
+ expect6(count).toBe(HIGH_VOLUME_COUNT);
1388
+ }
1389
+ },
1390
+ dbTestTimeout
1391
+ );
1392
+ test6(
1393
+ "handles payloads across chunk boundaries",
1394
+ async (c) => {
1395
+ const { client } = await setupDriverTest(c, driverTestConfig);
1396
+ const actor = getDbActor(client, variant).getOrCreate([
1397
+ `db-${variant}-chunk-${crypto.randomUUID()}`
1398
+ ]);
1399
+ await actor.reset();
1400
+ for (const size of CHUNK_BOUNDARY_SIZES) {
1401
+ const { id } = await actor.insertPayloadOfSize(size);
1402
+ const storedSize = await actor.getPayloadSize(id);
1403
+ expect6(storedSize).toBe(size);
1404
+ }
1405
+ },
1406
+ dbTestTimeout
1407
+ );
1408
+ test6(
1409
+ "handles large payloads",
1410
+ async (c) => {
1411
+ const { client } = await setupDriverTest(c, driverTestConfig);
1412
+ const actor = getDbActor(client, variant).getOrCreate([
1413
+ `db-${variant}-large-${crypto.randomUUID()}`
1414
+ ]);
1415
+ await actor.reset();
1416
+ const { id } = await actor.insertPayloadOfSize(LARGE_PAYLOAD_SIZE);
1417
+ const storedSize = await actor.getPayloadSize(id);
1418
+ expect6(storedSize).toBe(LARGE_PAYLOAD_SIZE);
1419
+ },
1420
+ dbTestTimeout
1421
+ );
1422
+ test6(
1423
+ "supports shrink and regrow workloads with vacuum",
1424
+ async (c) => {
1425
+ const { client } = await setupDriverTest(c, driverTestConfig);
1426
+ const actor = getDbActor(client, variant).getOrCreate([
1427
+ `db-${variant}-shrink-regrow-${crypto.randomUUID()}`
1428
+ ]);
1429
+ await actor.reset();
1430
+ await actor.vacuum();
1431
+ const baselinePages = await actor.getPageCount();
1432
+ await actor.insertPayloadRows(
1433
+ SHRINK_GROW_INITIAL_ROWS,
1434
+ SHRINK_GROW_INITIAL_PAYLOAD
1435
+ );
1436
+ const grownPages = await actor.getPageCount();
1437
+ await actor.reset();
1438
+ await actor.vacuum();
1439
+ const shrunkPages = await actor.getPageCount();
1440
+ await actor.insertPayloadRows(
1441
+ SHRINK_GROW_REGROW_ROWS,
1442
+ SHRINK_GROW_REGROW_PAYLOAD
1443
+ );
1444
+ const regrownPages = await actor.getPageCount();
1445
+ expect6(grownPages).toBeGreaterThanOrEqual(baselinePages);
1446
+ expect6(shrunkPages).toBeLessThanOrEqual(grownPages);
1447
+ expect6(regrownPages).toBeGreaterThan(shrunkPages);
1448
+ },
1449
+ dbTestTimeout
1450
+ );
1451
+ test6(
1452
+ "handles repeated updates to the same row",
1453
+ async (c) => {
1454
+ const { client } = await setupDriverTest(c, driverTestConfig);
1455
+ const actor = getDbActor(client, variant).getOrCreate([
1456
+ `db-${variant}-updates-${crypto.randomUUID()}`
1457
+ ]);
1458
+ await actor.reset();
1459
+ const { id } = await actor.insertValue("base");
1460
+ const result = await actor.repeatUpdate(id, 50);
1461
+ expect6(result.value).toBe("Updated 49");
1462
+ const value = await actor.getValue(id);
1463
+ expect6(value).toBe("Updated 49");
1464
+ const hotRowIds = [];
1465
+ for (let i = 0; i < HOT_ROW_COUNT; i++) {
1466
+ const row = await actor.insertValue(`init-${i}`);
1467
+ hotRowIds.push(row.id);
1468
+ }
1469
+ const updatedRows = await actor.roundRobinUpdateValues(
1470
+ hotRowIds,
1471
+ HOT_ROW_UPDATES
1472
+ );
1473
+ expect6(updatedRows).toHaveLength(HOT_ROW_COUNT);
1474
+ for (const row of updatedRows) {
1475
+ expect6(row.value).toMatch(/^v-\d+$/);
1476
+ }
1477
+ },
1478
+ dbTestTimeout
1479
+ );
1480
+ test6(
1481
+ "passes integrity checks after mixed workload and sleep",
1482
+ async (c) => {
1483
+ const { client } = await setupDriverTest(c, driverTestConfig);
1484
+ const actor = getDbActor(client, variant).getOrCreate([
1485
+ `db-${variant}-integrity-${crypto.randomUUID()}`
1486
+ ]);
1487
+ await actor.reset();
1488
+ await actor.runMixedWorkload(
1489
+ INTEGRITY_SEED_COUNT,
1490
+ INTEGRITY_CHURN_COUNT
1491
+ );
1492
+ expect6((await actor.integrityCheck()).toLowerCase()).toBe("ok");
1493
+ await actor.triggerSleep();
1494
+ await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1495
+ expect6((await actor.integrityCheck()).toLowerCase()).toBe("ok");
1496
+ },
1497
+ dbTestTimeout
1498
+ );
1499
+ });
1500
+ }
1501
+ describe6("Actor Database Lifecycle Cleanup Tests", () => {
1502
+ test6(
1503
+ "runs db provider cleanup on sleep",
1504
+ async (c) => {
1343
1505
  const { client } = await setupDriverTest(c, driverTestConfig);
1344
- const actor = getDbActor(client, variant).getOrCreate([
1345
- `db-${variant}-high-volume-${crypto.randomUUID()}`
1506
+ const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1507
+ const lifecycle = client.dbLifecycle.getOrCreate([
1508
+ `db-lifecycle-sleep-${crypto.randomUUID()}`
1346
1509
  ]);
1347
- await actor.reset();
1348
- await actor.insertMany(HIGH_VOLUME_COUNT);
1349
- expect6(await actor.getCount()).toBe(HIGH_VOLUME_COUNT);
1350
- });
1351
- test6("handles payloads across chunk boundaries", async (c) => {
1510
+ const actorId = await lifecycle.getActorId();
1511
+ const before = await observer.getCounts(actorId);
1512
+ await lifecycle.insertValue("before-sleep");
1513
+ await lifecycle.triggerSleep();
1514
+ await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1515
+ await lifecycle.ping();
1516
+ let after = before;
1517
+ for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1518
+ after = await observer.getCounts(actorId);
1519
+ if (after.cleanup >= before.cleanup + 1) {
1520
+ break;
1521
+ }
1522
+ await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1523
+ }
1524
+ expect6(after.create).toBeGreaterThanOrEqual(before.create);
1525
+ expect6(after.migrate).toBeGreaterThanOrEqual(before.migrate);
1526
+ expect6(after.cleanup).toBeGreaterThanOrEqual(before.cleanup + 1);
1527
+ },
1528
+ lifecycleTestTimeout
1529
+ );
1530
+ test6(
1531
+ "runs db provider cleanup on destroy",
1532
+ async (c) => {
1352
1533
  const { client } = await setupDriverTest(c, driverTestConfig);
1353
- const actor = getDbActor(client, variant).getOrCreate([
1354
- `db-${variant}-chunk-${crypto.randomUUID()}`
1534
+ const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1535
+ const lifecycle = client.dbLifecycle.getOrCreate([
1536
+ `db-lifecycle-destroy-${crypto.randomUUID()}`
1355
1537
  ]);
1356
- await actor.reset();
1357
- for (const size of CHUNK_BOUNDARY_SIZES) {
1358
- const { id } = await actor.insertPayloadOfSize(size);
1359
- const storedSize = await actor.getPayloadSize(id);
1360
- expect6(storedSize).toBe(size);
1538
+ const actorId = await lifecycle.getActorId();
1539
+ const before = await observer.getCounts(actorId);
1540
+ await lifecycle.insertValue("before-destroy");
1541
+ await lifecycle.triggerDestroy();
1542
+ await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1543
+ let cleanupCount = before.cleanup;
1544
+ for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1545
+ const counts = await observer.getCounts(actorId);
1546
+ cleanupCount = counts.cleanup;
1547
+ if (cleanupCount >= before.cleanup + 1) {
1548
+ break;
1549
+ }
1550
+ await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1361
1551
  }
1362
- });
1363
- test6("handles large payloads", async (c) => {
1552
+ expect6(cleanupCount).toBeGreaterThanOrEqual(before.cleanup + 1);
1553
+ },
1554
+ lifecycleTestTimeout
1555
+ );
1556
+ test6(
1557
+ "runs db provider cleanup when migration fails",
1558
+ async (c) => {
1364
1559
  const { client } = await setupDriverTest(c, driverTestConfig);
1365
- const actor = getDbActor(client, variant).getOrCreate([
1366
- `db-${variant}-large-${crypto.randomUUID()}`
1367
- ]);
1368
- await actor.reset();
1369
- const { id } = await actor.insertPayloadOfSize(LARGE_PAYLOAD_SIZE);
1370
- const storedSize = await actor.getPayloadSize(id);
1371
- expect6(storedSize).toBe(LARGE_PAYLOAD_SIZE);
1372
- });
1373
- test6("supports shrink and regrow workloads with vacuum", async (c) => {
1560
+ const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1561
+ const beforeTotalCleanup = await observer.getTotalCleanupCount();
1562
+ const key = `db-lifecycle-migrate-failure-${crypto.randomUUID()}`;
1563
+ const lifecycle = client.dbLifecycleFailing.getOrCreate([key]);
1564
+ let threw = false;
1565
+ try {
1566
+ await lifecycle.ping();
1567
+ } catch {
1568
+ threw = true;
1569
+ }
1570
+ expect6(threw).toBeTruthy();
1571
+ let cleanupCount = beforeTotalCleanup;
1572
+ for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1573
+ cleanupCount = await observer.getTotalCleanupCount();
1574
+ if (cleanupCount >= beforeTotalCleanup + 1) {
1575
+ break;
1576
+ }
1577
+ await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1578
+ }
1579
+ expect6(cleanupCount).toBeGreaterThanOrEqual(beforeTotalCleanup + 1);
1580
+ },
1581
+ lifecycleTestTimeout
1582
+ );
1583
+ test6(
1584
+ "handles parallel actor lifecycle churn",
1585
+ async (c) => {
1374
1586
  const { client } = await setupDriverTest(c, driverTestConfig);
1375
- const actor = getDbActor(client, variant).getOrCreate([
1376
- `db-${variant}-shrink-regrow-${crypto.randomUUID()}`
1377
- ]);
1378
- await actor.reset();
1379
- await actor.vacuum();
1380
- const baselinePages = await actor.getPageCount();
1381
- await actor.insertPayloadRows(
1382
- SHRINK_GROW_INITIAL_ROWS,
1383
- SHRINK_GROW_INITIAL_PAYLOAD
1587
+ const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1588
+ const actorHandles = Array.from(
1589
+ { length: 12 },
1590
+ (_, i) => client.dbLifecycle.getOrCreate([
1591
+ `db-lifecycle-stress-${i}-${crypto.randomUUID()}`
1592
+ ])
1384
1593
  );
1385
- const grownPages = await actor.getPageCount();
1386
- await actor.reset();
1387
- await actor.vacuum();
1388
- const shrunkPages = await actor.getPageCount();
1389
- await actor.insertPayloadRows(
1390
- SHRINK_GROW_REGROW_ROWS,
1391
- SHRINK_GROW_REGROW_PAYLOAD
1594
+ const actorIds = await Promise.all(
1595
+ actorHandles.map((handle) => handle.getActorId())
1392
1596
  );
1393
- const regrownPages = await actor.getPageCount();
1394
- expect6(grownPages).toBeGreaterThanOrEqual(baselinePages);
1395
- expect6(shrunkPages).toBeLessThanOrEqual(grownPages);
1396
- expect6(regrownPages).toBeGreaterThan(shrunkPages);
1397
- });
1398
- test6("handles repeated updates to the same row", async (c) => {
1399
- const { client } = await setupDriverTest(c, driverTestConfig);
1400
- const actor = getDbActor(client, variant).getOrCreate([
1401
- `db-${variant}-updates-${crypto.randomUUID()}`
1402
- ]);
1403
- await actor.reset();
1404
- const { id } = await actor.insertValue("base");
1405
- const result = await actor.repeatUpdate(id, 50);
1406
- expect6(result.value).toBe("Updated 49");
1407
- const value = await actor.getValue(id);
1408
- expect6(value).toBe("Updated 49");
1409
- const hotRowIds = [];
1410
- for (let i = 0; i < HOT_ROW_COUNT; i++) {
1411
- const row = await actor.insertValue(`init-${i}`);
1412
- hotRowIds.push(row.id);
1413
- }
1414
- const updatedRows = await actor.roundRobinUpdateValues(
1415
- hotRowIds,
1416
- HOT_ROW_UPDATES
1597
+ await Promise.all(
1598
+ actorHandles.map((handle, i) => handle.insertValue(`phase-1-${i}`))
1417
1599
  );
1418
- expect6(updatedRows).toHaveLength(HOT_ROW_COUNT);
1419
- for (const row of updatedRows) {
1420
- expect6(row.value).toMatch(/^v-\d+$/);
1421
- }
1422
- });
1423
- test6("passes integrity checks after mixed workload and sleep", async (c) => {
1424
- const { client } = await setupDriverTest(c, driverTestConfig);
1425
- const actor = getDbActor(client, variant).getOrCreate([
1426
- `db-${variant}-integrity-${crypto.randomUUID()}`
1427
- ]);
1428
- await actor.reset();
1429
- await actor.runMixedWorkload(
1430
- INTEGRITY_SEED_COUNT,
1431
- INTEGRITY_CHURN_COUNT
1600
+ await Promise.all(actorHandles.map((handle) => handle.triggerSleep()));
1601
+ await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1602
+ await Promise.all(
1603
+ actorHandles.map((handle, i) => handle.insertValue(`phase-2-${i}`))
1432
1604
  );
1433
- expect6((await actor.integrityCheck()).toLowerCase()).toBe("ok");
1434
- await actor.triggerSleep();
1605
+ const survivors = actorHandles.slice(0, 6);
1606
+ const destroyed = actorHandles.slice(6);
1607
+ await Promise.all(destroyed.map((handle) => handle.triggerDestroy()));
1608
+ await Promise.all(survivors.map((handle) => handle.triggerSleep()));
1435
1609
  await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1436
- expect6((await actor.integrityCheck()).toLowerCase()).toBe("ok");
1437
- });
1438
- });
1439
- }
1440
- describe6("Actor Database Lifecycle Cleanup Tests", () => {
1441
- test6("runs db provider cleanup on sleep", async (c) => {
1442
- const { client } = await setupDriverTest(c, driverTestConfig);
1443
- const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1444
- const lifecycle = client.dbLifecycle.getOrCreate([
1445
- `db-lifecycle-sleep-${crypto.randomUUID()}`
1446
- ]);
1447
- const actorId = await lifecycle.getActorId();
1448
- const before = await observer.getCounts(actorId);
1449
- await lifecycle.insertValue("before-sleep");
1450
- await lifecycle.triggerSleep();
1451
- await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1452
- await lifecycle.ping();
1453
- let after = before;
1454
- for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1455
- after = await observer.getCounts(actorId);
1456
- if (after.cleanup >= before.cleanup + 1) {
1457
- break;
1458
- }
1459
- await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1460
- }
1461
- expect6(after.create).toBeGreaterThanOrEqual(before.create);
1462
- expect6(after.migrate).toBeGreaterThanOrEqual(before.migrate);
1463
- expect6(after.cleanup).toBeGreaterThanOrEqual(before.cleanup + 1);
1464
- });
1465
- test6("runs db provider cleanup on destroy", async (c) => {
1466
- const { client } = await setupDriverTest(c, driverTestConfig);
1467
- const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1468
- const lifecycle = client.dbLifecycle.getOrCreate([
1469
- `db-lifecycle-destroy-${crypto.randomUUID()}`
1470
- ]);
1471
- const actorId = await lifecycle.getActorId();
1472
- const before = await observer.getCounts(actorId);
1473
- await lifecycle.insertValue("before-destroy");
1474
- await lifecycle.triggerDestroy();
1475
- await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1476
- let cleanupCount = before.cleanup;
1477
- for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1478
- const counts = await observer.getCounts(actorId);
1479
- cleanupCount = counts.cleanup;
1480
- if (cleanupCount >= before.cleanup + 1) {
1481
- break;
1482
- }
1483
- await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1484
- }
1485
- expect6(cleanupCount).toBeGreaterThanOrEqual(before.cleanup + 1);
1486
- });
1487
- test6("runs db provider cleanup when migration fails", async (c) => {
1488
- const { client } = await setupDriverTest(c, driverTestConfig);
1489
- const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1490
- const key = `db-lifecycle-migrate-failure-${crypto.randomUUID()}`;
1491
- const lifecycle = client.dbLifecycleFailing.getOrCreate([key]);
1492
- let threw = false;
1493
- try {
1494
- await lifecycle.ping();
1495
- } catch {
1496
- threw = true;
1497
- }
1498
- expect6(threw).toBeTruthy();
1499
- const actorId = await client.dbLifecycleFailing.get([key]).resolve();
1500
- let cleanupCount = 0;
1501
- for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1502
- const counts = await observer.getCounts(actorId);
1503
- cleanupCount = counts.cleanup;
1504
- if (cleanupCount >= 1) {
1505
- break;
1610
+ await Promise.all(survivors.map((handle) => handle.ping()));
1611
+ const survivorCounts = await Promise.all(
1612
+ survivors.map((handle) => handle.getCount())
1613
+ );
1614
+ for (const count of survivorCounts) {
1615
+ if (driverTestConfig.useRealTimers) {
1616
+ expect6(count).toBeGreaterThanOrEqual(2);
1617
+ } else {
1618
+ expect6(count).toBe(2);
1619
+ }
1506
1620
  }
1507
- await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1508
- }
1509
- expect6(cleanupCount).toBeGreaterThanOrEqual(1);
1510
- });
1511
- test6("handles parallel actor lifecycle churn", async (c) => {
1512
- const { client } = await setupDriverTest(c, driverTestConfig);
1513
- const observer = client.dbLifecycleObserver.getOrCreate(["observer"]);
1514
- const actorHandles = Array.from(
1515
- { length: 12 },
1516
- (_, i) => client.dbLifecycle.getOrCreate([
1517
- `db-lifecycle-stress-${i}-${crypto.randomUUID()}`
1518
- ])
1519
- );
1520
- const actorIds = await Promise.all(
1521
- actorHandles.map((handle) => handle.getActorId())
1522
- );
1523
- await Promise.all(
1524
- actorHandles.map((handle, i) => handle.insertValue(`phase-1-${i}`))
1525
- );
1526
- await Promise.all(actorHandles.map((handle) => handle.triggerSleep()));
1527
- await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1528
- await Promise.all(
1529
- actorHandles.map((handle, i) => handle.insertValue(`phase-2-${i}`))
1530
- );
1531
- const survivors = actorHandles.slice(0, 6);
1532
- const destroyed = actorHandles.slice(6);
1533
- await Promise.all(destroyed.map((handle) => handle.triggerDestroy()));
1534
- await Promise.all(survivors.map((handle) => handle.triggerSleep()));
1535
- await waitFor(driverTestConfig, SLEEP_WAIT_MS + 100);
1536
- await Promise.all(survivors.map((handle) => handle.ping()));
1537
- const survivorCounts = await Promise.all(
1538
- survivors.map((handle) => handle.getCount())
1539
- );
1540
- for (const count of survivorCounts) {
1541
- expect6(count).toBe(2);
1542
- }
1543
- const lifecycleCleanup = /* @__PURE__ */ new Map();
1544
- for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1545
- let allCleaned = true;
1546
- for (const actorId of actorIds) {
1547
- const counts = await observer.getCounts(actorId);
1548
- lifecycleCleanup.set(actorId, counts.cleanup);
1549
- if (counts.cleanup < 1) {
1550
- allCleaned = false;
1621
+ const lifecycleCleanup = /* @__PURE__ */ new Map();
1622
+ for (let i = 0; i < LIFECYCLE_POLL_ATTEMPTS; i++) {
1623
+ let allCleaned = true;
1624
+ for (const actorId of actorIds) {
1625
+ const counts = await observer.getCounts(actorId);
1626
+ lifecycleCleanup.set(actorId, counts.cleanup);
1627
+ if (counts.cleanup < 1) {
1628
+ allCleaned = false;
1629
+ }
1551
1630
  }
1631
+ if (allCleaned) {
1632
+ break;
1633
+ }
1634
+ await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1552
1635
  }
1553
- if (allCleaned) {
1554
- break;
1636
+ for (const actorId of actorIds) {
1637
+ expect6(lifecycleCleanup.get(actorId) ?? 0).toBeGreaterThanOrEqual(1);
1555
1638
  }
1556
- await waitFor(driverTestConfig, LIFECYCLE_POLL_INTERVAL_MS);
1557
- }
1558
- for (const actorId of actorIds) {
1559
- expect6(lifecycleCleanup.get(actorId) ?? 0).toBeGreaterThanOrEqual(1);
1560
- }
1561
- });
1639
+ },
1640
+ lifecycleTestTimeout
1641
+ );
1562
1642
  });
1563
1643
  }
1564
1644
 
@@ -3042,11 +3122,12 @@ function runActorQueueTests(driverTestConfig) {
3042
3122
  test18("wait send returns completion response", async (c) => {
3043
3123
  const { client } = await setupDriverTest(c, driverTestConfig);
3044
3124
  const handle = client.queueActor.getOrCreate(["wait-complete"]);
3125
+ const waitTimeout = driverTestConfig.useRealTimers ? 5e3 : 1e3;
3045
3126
  const actionPromise = handle.receiveAndComplete("tasks");
3046
3127
  const result = await handle.send(
3047
3128
  "tasks",
3048
3129
  { value: 123 },
3049
- { wait: true, timeout: 1e3 }
3130
+ { wait: true, timeout: waitTimeout }
3050
3131
  );
3051
3132
  await actionPromise;
3052
3133
  expect18(result).toEqual({
@@ -3396,8 +3477,14 @@ function runActorWorkflowTests(driverTestConfig) {
3396
3477
  const actor = client.workflowCounterActor.getOrCreate([
3397
3478
  "workflow-basic"
3398
3479
  ]);
3399
- await waitFor(driverTestConfig, 1e3);
3400
- const state = await actor.getState();
3480
+ let state = await actor.getState();
3481
+ for (let i = 0; i < 50; i++) {
3482
+ if (state.runCount > 0 && state.history.length > 0 && state.guardTriggered) {
3483
+ break;
3484
+ }
3485
+ await waitFor(driverTestConfig, 100);
3486
+ state = await actor.getState();
3487
+ }
3401
3488
  expect22(state.runCount).toBeGreaterThan(0);
3402
3489
  expect22(state.history.length).toBeGreaterThan(0);
3403
3490
  expect22(state.guardTriggered).toBe(true);