rivetkit 2.1.4 → 2.1.6-rc.1
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 +593 -588
- package/dist/browser/client.js +215 -35
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +109 -10
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/inspector.tar.gz +0 -0
- package/dist/tsup/actor/errors.cjs +2 -2
- package/dist/tsup/actor/errors.js +1 -1
- package/dist/tsup/{actor-router-consts-D29T1Z-K.d.cts → actor-router-consts-DU-1IdQj.d.cts} +1 -1
- package/dist/tsup/{actor-router-consts-D29T1Z-K.d.ts → actor-router-consts-DU-1IdQj.d.ts} +1 -1
- package/dist/tsup/chunk-2ELYUO6C.cjs +112 -0
- package/dist/tsup/chunk-2ELYUO6C.cjs.map +1 -0
- package/dist/tsup/chunk-2LY7RW3Y.cjs +2316 -0
- package/dist/tsup/chunk-2LY7RW3Y.cjs.map +1 -0
- package/dist/tsup/{chunk-L47L3ZWJ.cjs → chunk-6G7ZNM27.cjs} +11 -6
- package/dist/tsup/chunk-6G7ZNM27.cjs.map +1 -0
- package/dist/tsup/{chunk-LK36OGGO.cjs → chunk-A4KEUCB6.cjs} +84 -34
- package/dist/tsup/chunk-A4KEUCB6.cjs.map +1 -0
- package/dist/tsup/{chunk-7HTNH26M.js → chunk-AKUJ5OTO.js} +11 -6
- package/dist/tsup/chunk-AKUJ5OTO.js.map +1 -0
- package/dist/tsup/{chunk-ANKZ2FS6.js → chunk-C22JYHVT.js} +77 -27
- package/dist/tsup/chunk-C22JYHVT.js.map +1 -0
- package/dist/tsup/chunk-C4EB42ET.js +1459 -0
- package/dist/tsup/chunk-C4EB42ET.js.map +1 -0
- package/dist/tsup/chunk-CGGGBIDP.cjs +1459 -0
- package/dist/tsup/chunk-CGGGBIDP.cjs.map +1 -0
- package/dist/tsup/chunk-CMQPDBBR.cjs +1486 -0
- package/dist/tsup/chunk-CMQPDBBR.cjs.map +1 -0
- package/dist/tsup/{chunk-AQD4CBZ2.cjs → chunk-DH6UINWA.cjs} +4 -4
- package/dist/tsup/{chunk-AQD4CBZ2.cjs.map → chunk-DH6UINWA.cjs.map} +1 -1
- package/dist/tsup/chunk-DK46YYCJ.js +1486 -0
- package/dist/tsup/chunk-DK46YYCJ.js.map +1 -0
- package/dist/tsup/chunk-EGWXXBZV.js +2316 -0
- package/dist/tsup/chunk-EGWXXBZV.js.map +1 -0
- package/dist/tsup/{chunk-HBYEYBIC.js → chunk-EONWXYMN.js} +2 -2
- package/dist/tsup/{chunk-N4KRDJ56.js → chunk-GFGRBYO2.js} +35 -6
- package/dist/tsup/chunk-GFGRBYO2.js.map +1 -0
- package/dist/tsup/{chunk-TEUL4UYN.cjs → chunk-GUHXWPGB.cjs} +1515 -1479
- package/dist/tsup/chunk-GUHXWPGB.cjs.map +1 -0
- package/dist/tsup/{chunk-3B6PCYJB.cjs → chunk-HNE2AK6C.cjs} +2375 -3713
- package/dist/tsup/chunk-HNE2AK6C.cjs.map +1 -0
- package/dist/tsup/{chunk-5UEFNG7P.js → chunk-I5I6OALK.js} +2 -2
- package/dist/tsup/chunk-IHQAF2HV.cjs +23 -0
- package/dist/tsup/chunk-IHQAF2HV.cjs.map +1 -0
- package/dist/tsup/{chunk-UWAGLDT6.cjs → chunk-JJNZQDUN.cjs} +667 -2517
- package/dist/tsup/chunk-JJNZQDUN.cjs.map +1 -0
- package/dist/tsup/{chunk-M6H4XIF4.js → chunk-JJSPHLJN.js} +219 -287
- package/dist/tsup/chunk-JJSPHLJN.js.map +1 -0
- package/dist/tsup/chunk-JRKPV5NJ.js +481 -0
- package/dist/tsup/chunk-JRKPV5NJ.js.map +1 -0
- package/dist/tsup/{chunk-VKVNIQRQ.js → chunk-K7MVU5SI.js} +36 -41
- package/dist/tsup/chunk-K7MVU5SI.js.map +1 -0
- package/dist/tsup/{chunk-KJSYAUOM.js → chunk-MLK3GY6P.js} +43 -27
- package/dist/tsup/chunk-MLK3GY6P.js.map +1 -0
- package/dist/tsup/{chunk-4KSHPFXF.cjs → chunk-MPLMTJY5.cjs} +123 -23
- package/dist/tsup/chunk-MPLMTJY5.cjs.map +1 -0
- package/dist/tsup/{chunk-UDMRZR6A.js → chunk-PQWI44WD.js} +1755 -3093
- package/dist/tsup/chunk-PQWI44WD.js.map +1 -0
- package/dist/tsup/{chunk-SR3KQE7Q.cjs → chunk-SQFCIDCG.cjs} +35 -6
- package/dist/tsup/chunk-SQFCIDCG.cjs.map +1 -0
- package/dist/tsup/{chunk-3GTO6H3E.js → chunk-SVHJSM2E.js} +110 -24
- package/dist/tsup/chunk-SVHJSM2E.js.map +1 -0
- package/dist/tsup/chunk-T5KYKM6R.js +49 -0
- package/dist/tsup/chunk-T5KYKM6R.js.map +1 -0
- package/dist/tsup/{chunk-GXRVSSVD.cjs → chunk-TJ7DKW6F.cjs} +123 -37
- package/dist/tsup/chunk-TJ7DKW6F.cjs.map +1 -0
- package/dist/tsup/chunk-UQZRMTM3.js +23 -0
- package/dist/tsup/chunk-UQZRMTM3.js.map +1 -0
- package/dist/tsup/{chunk-QPADHLDU.cjs → chunk-V3JSZR5P.cjs} +3 -3
- package/dist/tsup/{chunk-QPADHLDU.cjs.map → chunk-V3JSZR5P.cjs.map} +1 -1
- package/dist/tsup/{chunk-HKOSZKKZ.cjs → chunk-VBR35EQF.cjs} +271 -339
- package/dist/tsup/chunk-VBR35EQF.cjs.map +1 -0
- package/dist/tsup/{chunk-DZXDUGLL.js → chunk-VWYO36X4.js} +117 -17
- package/dist/tsup/chunk-VWYO36X4.js.map +1 -0
- package/dist/tsup/{chunk-I6PL6QIY.js → chunk-WW27B6DM.js} +1452 -1416
- package/dist/tsup/chunk-WW27B6DM.js.map +1 -0
- package/dist/tsup/chunk-YAE3MEJM.cjs +49 -0
- package/dist/tsup/chunk-YAE3MEJM.cjs.map +1 -0
- package/dist/tsup/{chunk-KTWY3K6Z.js → chunk-YGYGANCA.js} +473 -2323
- package/dist/tsup/chunk-YGYGANCA.js.map +1 -0
- package/dist/tsup/chunk-YZJWZBY5.cjs +481 -0
- package/dist/tsup/chunk-YZJWZBY5.cjs.map +1 -0
- package/dist/tsup/{chunk-ZFY5J2EP.cjs → chunk-ZZLJ5TSM.cjs} +39 -44
- package/dist/tsup/chunk-ZZLJ5TSM.cjs.map +1 -0
- package/dist/tsup/client/mod.cjs +10 -7
- package/dist/tsup/client/mod.cjs.map +1 -1
- package/dist/tsup/client/mod.d.cts +6 -6
- package/dist/tsup/client/mod.d.ts +6 -6
- package/dist/tsup/client/mod.js +11 -8
- package/dist/tsup/common/log.cjs +3 -3
- package/dist/tsup/common/log.js +2 -2
- package/dist/tsup/common/websocket.cjs +4 -4
- package/dist/tsup/common/websocket.js +3 -3
- package/dist/tsup/{config-Qj-zLJPc.d.ts → config-C2Wwnc69.d.ts} +142 -208
- package/dist/tsup/{config-BiNoIHRs.d.ts → config-DROwzBLT.d.cts} +82 -6
- package/dist/tsup/{config-BiNoIHRs.d.cts → config-DROwzBLT.d.ts} +82 -6
- package/dist/tsup/{config-iPj5l1bL.d.cts → config-ehT-_3BB.d.cts} +142 -208
- package/dist/tsup/{context-DzvH1PBK.d.cts → context-DGMJuAyc.d.ts} +16 -3
- package/dist/tsup/{context-CQCMuHND.d.ts → context-Dpp2RJbW.d.cts} +16 -3
- package/dist/tsup/db/drizzle/mod.cjs +3 -3
- package/dist/tsup/db/drizzle/mod.d.cts +1 -1
- package/dist/tsup/db/drizzle/mod.d.ts +1 -1
- package/dist/tsup/db/drizzle/mod.js +2 -2
- package/dist/tsup/db/mod.cjs +3 -3
- package/dist/tsup/db/mod.d.cts +1 -1
- package/dist/tsup/db/mod.d.ts +1 -1
- package/dist/tsup/db/mod.js +2 -2
- package/dist/tsup/{driver-Jo8v-kbU.d.ts → driver-CYZP9QYo.d.ts} +1 -1
- package/dist/tsup/{driver-iV8J-WMv.d.cts → driver-CoTFpipv.d.cts} +1 -1
- package/dist/tsup/driver-helpers/mod.cjs +7 -5
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +17 -18
- package/dist/tsup/driver-helpers/mod.d.ts +17 -18
- package/dist/tsup/driver-helpers/mod.js +11 -9
- package/dist/tsup/driver-test-suite/mod.cjs +1275 -228
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +6 -5
- package/dist/tsup/driver-test-suite/mod.d.ts +6 -5
- package/dist/tsup/driver-test-suite/mod.js +1581 -534
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +4 -4
- package/dist/tsup/inspector/mod.js +3 -3
- package/dist/tsup/mod.cjs +15 -9
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +9 -9
- package/dist/tsup/mod.d.ts +9 -9
- package/dist/tsup/mod.js +19 -13
- package/dist/tsup/sandbox/client.cjs +28 -0
- package/dist/tsup/sandbox/client.cjs.map +1 -0
- package/dist/tsup/sandbox/client.d.cts +88 -0
- package/dist/tsup/sandbox/client.d.ts +88 -0
- package/dist/tsup/sandbox/client.js +28 -0
- package/dist/tsup/sandbox/client.js.map +1 -0
- package/dist/tsup/sandbox/index.cjs +761 -0
- package/dist/tsup/sandbox/index.cjs.map +1 -0
- package/dist/tsup/sandbox/index.d.cts +120 -0
- package/dist/tsup/sandbox/index.d.ts +120 -0
- package/dist/tsup/sandbox/index.js +761 -0
- package/dist/tsup/sandbox/index.js.map +1 -0
- package/dist/tsup/sandbox/providers/computesdk.cjs +3 -0
- package/dist/tsup/sandbox/providers/computesdk.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/computesdk.d.cts +7 -0
- package/dist/tsup/sandbox/providers/computesdk.d.ts +7 -0
- package/dist/tsup/sandbox/providers/computesdk.js +3 -0
- package/dist/tsup/sandbox/providers/computesdk.js.map +1 -0
- package/dist/tsup/sandbox/providers/daytona.cjs +3 -0
- package/dist/tsup/sandbox/providers/daytona.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/daytona.d.cts +1 -0
- package/dist/tsup/sandbox/providers/daytona.d.ts +1 -0
- package/dist/tsup/sandbox/providers/daytona.js +3 -0
- package/dist/tsup/sandbox/providers/daytona.js.map +1 -0
- package/dist/tsup/sandbox/providers/docker.cjs +3 -0
- package/dist/tsup/sandbox/providers/docker.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/docker.d.cts +1 -0
- package/dist/tsup/sandbox/providers/docker.d.ts +1 -0
- package/dist/tsup/sandbox/providers/docker.js +3 -0
- package/dist/tsup/sandbox/providers/docker.js.map +1 -0
- package/dist/tsup/sandbox/providers/e2b.cjs +3 -0
- package/dist/tsup/sandbox/providers/e2b.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/e2b.d.cts +1 -0
- package/dist/tsup/sandbox/providers/e2b.d.ts +1 -0
- package/dist/tsup/sandbox/providers/e2b.js +3 -0
- package/dist/tsup/sandbox/providers/e2b.js.map +1 -0
- package/dist/tsup/sandbox/providers/local.cjs +3 -0
- package/dist/tsup/sandbox/providers/local.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/local.d.cts +1 -0
- package/dist/tsup/sandbox/providers/local.d.ts +1 -0
- package/dist/tsup/sandbox/providers/local.js +3 -0
- package/dist/tsup/sandbox/providers/local.js.map +1 -0
- package/dist/tsup/sandbox/providers/modal.cjs +3 -0
- package/dist/tsup/sandbox/providers/modal.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/modal.d.cts +1 -0
- package/dist/tsup/sandbox/providers/modal.d.ts +1 -0
- package/dist/tsup/sandbox/providers/modal.js +3 -0
- package/dist/tsup/sandbox/providers/modal.js.map +1 -0
- package/dist/tsup/sandbox/providers/vercel.cjs +3 -0
- package/dist/tsup/sandbox/providers/vercel.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/vercel.d.cts +1 -0
- package/dist/tsup/sandbox/providers/vercel.d.ts +1 -0
- package/dist/tsup/sandbox/providers/vercel.js +3 -0
- package/dist/tsup/sandbox/providers/vercel.js.map +1 -0
- package/dist/tsup/serve-test-suite/mod.cjs +451 -327
- package/dist/tsup/serve-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/serve-test-suite/mod.js +362 -238
- package/dist/tsup/serve-test-suite/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +17 -14
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +4 -4
- package/dist/tsup/test/mod.d.ts +4 -4
- package/dist/tsup/test/mod.js +14 -11
- package/dist/tsup/test/mod.js.map +1 -1
- package/dist/tsup/utils.cjs +3 -3
- package/dist/tsup/utils.js +2 -2
- package/dist/tsup/workflow/mod.cjs +6 -6
- package/dist/tsup/workflow/mod.d.cts +13 -9
- package/dist/tsup/workflow/mod.d.ts +13 -9
- package/dist/tsup/workflow/mod.js +5 -5
- package/package.json +113 -14
- package/src/actor/config.ts +94 -88
- package/src/actor/conn/drivers/websocket.ts +2 -1
- package/src/actor/contexts/base/actor.ts +27 -4
- package/src/actor/database.ts +6 -1
- package/src/actor/driver.ts +27 -8
- package/src/actor/errors.ts +10 -5
- package/src/actor/instance/connection-manager.ts +4 -3
- package/src/actor/instance/kv.ts +52 -9
- package/src/actor/instance/mod.ts +135 -84
- package/src/actor/instance/queue-manager.ts +2 -5
- package/src/actor/instance/queue.ts +31 -29
- package/src/actor/instance/state-manager.ts +7 -1
- package/src/actor/instance/traces-driver.ts +34 -36
- package/src/actor/metrics.ts +137 -0
- package/src/actor/protocol/old.ts +9 -12
- package/src/actor/router-websocket-endpoints.ts +12 -6
- package/src/actor/router.ts +46 -9
- package/src/actor/schema.ts +14 -22
- package/src/client/actor-common.ts +65 -0
- package/src/client/actor-conn.ts +71 -9
- package/src/client/actor-handle.ts +22 -5
- package/src/client/client.ts +32 -6
- package/src/client/config.ts +18 -21
- package/src/client/mod.ts +1 -0
- package/src/client/queue.ts +8 -6
- package/src/common/inline-websocket-adapter.ts +8 -2
- package/src/common/router.ts +1 -4
- package/src/common/utils.ts +2 -5
- package/src/db/config.ts +10 -5
- package/src/db/drizzle/mod.ts +51 -41
- package/src/db/mod.ts +54 -29
- package/src/db/shared.ts +42 -8
- package/src/driver-helpers/mod.ts +2 -1
- package/src/driver-helpers/sqlite-pool.ts +42 -0
- package/src/driver-helpers/utils.ts +0 -20
- package/src/driver-test-suite/mod.ts +11 -1
- package/src/driver-test-suite/tests/access-control.ts +19 -12
- package/src/driver-test-suite/tests/action-features.ts +20 -8
- package/src/driver-test-suite/tests/actor-conn.ts +94 -8
- package/src/driver-test-suite/tests/actor-db-kv-stats.ts +282 -0
- package/src/driver-test-suite/tests/actor-db-raw.ts +6 -2
- package/src/driver-test-suite/tests/actor-db.ts +101 -31
- package/src/driver-test-suite/tests/actor-inspector.ts +174 -32
- package/src/driver-test-suite/tests/actor-kv.ts +79 -33
- package/src/driver-test-suite/tests/actor-lifecycle.ts +4 -12
- package/src/driver-test-suite/tests/actor-queue.ts +125 -17
- package/src/driver-test-suite/tests/actor-run.ts +59 -55
- package/src/driver-test-suite/tests/actor-sandbox.ts +78 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +1 -4
- package/src/driver-test-suite/tests/actor-sleep.ts +111 -0
- package/src/driver-test-suite/tests/actor-workflow.ts +387 -3
- package/src/driver-test-suite/tests/conn-error-serialization.ts +3 -1
- package/src/driver-test-suite/tests/raw-websocket.ts +5 -1
- package/src/drivers/default.ts +1 -3
- package/src/drivers/engine/actor-driver.ts +94 -21
- package/src/drivers/engine/config.ts +4 -12
- package/src/drivers/engine/mod.ts +1 -5
- package/src/drivers/file-system/actor.ts +43 -8
- package/src/drivers/file-system/global-state.ts +180 -64
- package/src/drivers/file-system/kv-limits.ts +1 -1
- package/src/drivers/file-system/sqlite-runtime.ts +13 -4
- package/src/engine-process/mod.ts +5 -1
- package/src/inspector/actor-inspector.ts +47 -21
- package/src/inspector/config.ts +1 -4
- package/src/inspector/mod.browser.ts +2 -2
- package/src/inspector/mod.ts +4 -1
- package/src/inspector/serve-ui.ts +0 -1
- package/src/inspector/workflow-history-json.ts +309 -0
- package/src/manager/gateway.ts +6 -2
- package/src/manager/router.ts +3 -3
- package/src/registry/config/index.ts +65 -12
- package/src/registry/config/runner.ts +19 -4
- package/src/registry/index.ts +42 -89
- package/src/sandbox/actor/db.ts +36 -0
- package/src/sandbox/actor/index.ts +476 -0
- package/src/sandbox/actor/session.ts +350 -0
- package/src/sandbox/actor.test.ts +36 -0
- package/src/sandbox/client.test.ts +484 -0
- package/src/sandbox/client.ts +707 -0
- package/src/sandbox/config.ts +151 -0
- package/src/sandbox/index.ts +41 -0
- package/src/sandbox/providers/computesdk.ts +1 -0
- package/src/sandbox/providers/daytona.ts +1 -0
- package/src/sandbox/providers/docker.ts +1 -0
- package/src/sandbox/providers/e2b.ts +1 -0
- package/src/sandbox/providers/local.ts +1 -0
- package/src/sandbox/providers/modal.ts +1 -0
- package/src/sandbox/providers/vercel.ts +1 -0
- package/src/sandbox/session-persist-driver.ts +180 -0
- package/src/sandbox/types.ts +138 -0
- package/src/serverless/configure.ts +5 -3
- package/src/serverless/router.test.ts +17 -9
- package/src/serverless/router.ts +20 -13
- package/src/test/mod.ts +3 -4
- package/src/utils/endpoint-parser.test.ts +6 -2
- package/src/utils/endpoint-parser.ts +6 -2
- package/src/utils/env-vars.ts +0 -2
- package/src/utils/node.ts +1 -1
- package/src/utils/serve.ts +10 -5
- package/src/utils.ts +6 -1
- package/src/workflow/constants.ts +1 -2
- package/src/workflow/context.ts +42 -9
- package/src/workflow/driver.ts +57 -23
- package/src/workflow/inspector.ts +7 -13
- package/src/workflow/mod.ts +91 -4
- package/dist/tsup/chunk-3B6PCYJB.cjs.map +0 -1
- package/dist/tsup/chunk-3GTO6H3E.js.map +0 -1
- package/dist/tsup/chunk-4KSHPFXF.cjs.map +0 -1
- package/dist/tsup/chunk-6LJAZ5R4.cjs +0 -96
- package/dist/tsup/chunk-6LJAZ5R4.cjs.map +0 -1
- package/dist/tsup/chunk-7HTNH26M.js.map +0 -1
- package/dist/tsup/chunk-ANKZ2FS6.js.map +0 -1
- package/dist/tsup/chunk-DZXDUGLL.js.map +0 -1
- package/dist/tsup/chunk-GXRVSSVD.cjs.map +0 -1
- package/dist/tsup/chunk-H5TSEPN4.cjs +0 -645
- package/dist/tsup/chunk-H5TSEPN4.cjs.map +0 -1
- package/dist/tsup/chunk-HKOSZKKZ.cjs.map +0 -1
- package/dist/tsup/chunk-I6PL6QIY.js.map +0 -1
- package/dist/tsup/chunk-KJSYAUOM.js.map +0 -1
- package/dist/tsup/chunk-KTWY3K6Z.js.map +0 -1
- package/dist/tsup/chunk-L47L3ZWJ.cjs.map +0 -1
- package/dist/tsup/chunk-LK36OGGO.cjs.map +0 -1
- package/dist/tsup/chunk-M6H4XIF4.js.map +0 -1
- package/dist/tsup/chunk-N4KRDJ56.js.map +0 -1
- package/dist/tsup/chunk-SR3KQE7Q.cjs.map +0 -1
- package/dist/tsup/chunk-TEFYRRAK.js +0 -645
- package/dist/tsup/chunk-TEFYRRAK.js.map +0 -1
- package/dist/tsup/chunk-TEUL4UYN.cjs.map +0 -1
- package/dist/tsup/chunk-UDMRZR6A.js.map +0 -1
- package/dist/tsup/chunk-UWAGLDT6.cjs.map +0 -1
- package/dist/tsup/chunk-VKVNIQRQ.js.map +0 -1
- package/dist/tsup/chunk-ZFY5J2EP.cjs.map +0 -1
- package/src/db/sqlite-vfs.ts +0 -12
- /package/dist/tsup/{chunk-HBYEYBIC.js.map → chunk-EONWXYMN.js.map} +0 -0
- /package/dist/tsup/{chunk-5UEFNG7P.js.map → chunk-I5I6OALK.js.map} +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
1
|
+
import { describe, expect, test, vi } from "vitest";
|
|
2
|
+
import type { ActorError } from "@/client/mod";
|
|
2
3
|
import {
|
|
4
|
+
WORKFLOW_NESTED_QUEUE_NAME,
|
|
3
5
|
WORKFLOW_QUEUE_NAME,
|
|
4
6
|
} from "../../../fixtures/driver-test-suite/workflow";
|
|
5
7
|
import type { DriverTestConfig } from "../mod";
|
|
@@ -32,7 +34,9 @@ export function runActorWorkflowTests(driverTestConfig: DriverTestConfig) {
|
|
|
32
34
|
|
|
33
35
|
test("consumes queue messages via workflow queue.next", async (c) => {
|
|
34
36
|
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
35
|
-
const actor = client.workflowQueueActor.getOrCreate([
|
|
37
|
+
const actor = client.workflowQueueActor.getOrCreate([
|
|
38
|
+
"workflow-queue",
|
|
39
|
+
]);
|
|
36
40
|
|
|
37
41
|
await actor.send(WORKFLOW_QUEUE_NAME, {
|
|
38
42
|
hello: "world",
|
|
@@ -56,6 +60,143 @@ export function runActorWorkflowTests(driverTestConfig: DriverTestConfig) {
|
|
|
56
60
|
});
|
|
57
61
|
});
|
|
58
62
|
|
|
63
|
+
for (const testCase of [
|
|
64
|
+
{
|
|
65
|
+
name: "nested loops",
|
|
66
|
+
key: "loop" as const,
|
|
67
|
+
getActor: (
|
|
68
|
+
client: Awaited<
|
|
69
|
+
ReturnType<typeof setupDriverTest>
|
|
70
|
+
>["client"],
|
|
71
|
+
) => client.workflowNestedLoopActor,
|
|
72
|
+
firstItems: ["a", "b"],
|
|
73
|
+
secondItems: ["c"],
|
|
74
|
+
expected: ["a", "b", "c"],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "nested joins",
|
|
78
|
+
key: "join" as const,
|
|
79
|
+
getActor: (
|
|
80
|
+
client: Awaited<
|
|
81
|
+
ReturnType<typeof setupDriverTest>
|
|
82
|
+
>["client"],
|
|
83
|
+
) => client.workflowNestedJoinActor,
|
|
84
|
+
firstItems: ["a", "b"],
|
|
85
|
+
secondItems: ["c"],
|
|
86
|
+
expected: ["a", "b", "c"],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "nested races",
|
|
90
|
+
key: "race" as const,
|
|
91
|
+
getActor: (
|
|
92
|
+
client: Awaited<
|
|
93
|
+
ReturnType<typeof setupDriverTest>
|
|
94
|
+
>["client"],
|
|
95
|
+
) => client.workflowNestedRaceActor,
|
|
96
|
+
firstItems: ["a"],
|
|
97
|
+
secondItems: ["b"],
|
|
98
|
+
expected: ["a", "b"],
|
|
99
|
+
},
|
|
100
|
+
]) {
|
|
101
|
+
test(
|
|
102
|
+
`replays ${testCase.name} across workflow queue iterations`,
|
|
103
|
+
async (c) => {
|
|
104
|
+
const { client } = await setupDriverTest(
|
|
105
|
+
c,
|
|
106
|
+
driverTestConfig,
|
|
107
|
+
);
|
|
108
|
+
const actor = testCase.getActor(client).getOrCreate([
|
|
109
|
+
`workflow-nested-${testCase.key}`,
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
const first = await actor.send(
|
|
113
|
+
WORKFLOW_NESTED_QUEUE_NAME,
|
|
114
|
+
{
|
|
115
|
+
items: testCase.firstItems,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
wait: true,
|
|
119
|
+
timeout: 1_000,
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
expect(first).toEqual({
|
|
123
|
+
status: "completed",
|
|
124
|
+
response: {
|
|
125
|
+
processed: testCase.firstItems.length,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const second = await actor.send(
|
|
130
|
+
WORKFLOW_NESTED_QUEUE_NAME,
|
|
131
|
+
{
|
|
132
|
+
items: testCase.secondItems,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
wait: true,
|
|
136
|
+
timeout: 1_000,
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
expect(second).toEqual({
|
|
140
|
+
status: "completed",
|
|
141
|
+
response: {
|
|
142
|
+
processed: testCase.secondItems.length,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const state = await actor.getState();
|
|
147
|
+
expect(state.processed).toEqual(testCase.expected);
|
|
148
|
+
},
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
test(
|
|
153
|
+
"starts child workflows created inside workflow steps",
|
|
154
|
+
async (c) => {
|
|
155
|
+
const { client } = await setupDriverTest(
|
|
156
|
+
c,
|
|
157
|
+
driverTestConfig,
|
|
158
|
+
);
|
|
159
|
+
const parent = client.workflowSpawnParentActor.getOrCreate([
|
|
160
|
+
"workflow-spawn-parent",
|
|
161
|
+
]);
|
|
162
|
+
|
|
163
|
+
expect(await parent.triggerSpawn("child-1")).toEqual({
|
|
164
|
+
queued: true,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
let parentState = await parent.getState();
|
|
168
|
+
for (
|
|
169
|
+
let i = 0;
|
|
170
|
+
i < 30 && parentState.results.length === 0;
|
|
171
|
+
i++
|
|
172
|
+
) {
|
|
173
|
+
await waitFor(driverTestConfig, 100);
|
|
174
|
+
parentState = await parent.getState();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
expect(parentState.results).toEqual([
|
|
178
|
+
{
|
|
179
|
+
key: "child-1",
|
|
180
|
+
result: {
|
|
181
|
+
status: "completed",
|
|
182
|
+
response: { ok: true },
|
|
183
|
+
},
|
|
184
|
+
error: null,
|
|
185
|
+
},
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
const child = client.workflowSpawnChildActor.getOrCreate([
|
|
189
|
+
"child-1",
|
|
190
|
+
]);
|
|
191
|
+
const childState = await child.getState();
|
|
192
|
+
expect(childState).toEqual({
|
|
193
|
+
label: "child-1",
|
|
194
|
+
started: true,
|
|
195
|
+
processed: ["hello"],
|
|
196
|
+
});
|
|
197
|
+
},
|
|
198
|
+
);
|
|
199
|
+
|
|
59
200
|
test("db and client are step-only in workflow context", async (c) => {
|
|
60
201
|
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
61
202
|
const actor = client.workflowAccessActor.getOrCreate([
|
|
@@ -80,7 +221,9 @@ export function runActorWorkflowTests(driverTestConfig: DriverTestConfig) {
|
|
|
80
221
|
|
|
81
222
|
test("sleeps and resumes between ticks", async (c) => {
|
|
82
223
|
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
83
|
-
const actor = client.workflowSleepActor.getOrCreate([
|
|
224
|
+
const actor = client.workflowSleepActor.getOrCreate([
|
|
225
|
+
"workflow-sleep",
|
|
226
|
+
]);
|
|
84
227
|
|
|
85
228
|
const initial = await actor.getState();
|
|
86
229
|
await waitFor(driverTestConfig, 200);
|
|
@@ -89,6 +232,247 @@ export function runActorWorkflowTests(driverTestConfig: DriverTestConfig) {
|
|
|
89
232
|
expect(next.ticks).toBeGreaterThan(initial.ticks);
|
|
90
233
|
});
|
|
91
234
|
|
|
235
|
+
test("workflow onError reports retry metadata", async (c) => {
|
|
236
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
237
|
+
const actor = client.workflowErrorHookActor.getOrCreate([
|
|
238
|
+
"workflow-error-hook",
|
|
239
|
+
]);
|
|
240
|
+
|
|
241
|
+
let state = await actor.getErrorState();
|
|
242
|
+
for (
|
|
243
|
+
let i = 0;
|
|
244
|
+
i < 80 && (state.attempts < 2 || state.events.length === 0);
|
|
245
|
+
i++
|
|
246
|
+
) {
|
|
247
|
+
await waitFor(driverTestConfig, 50);
|
|
248
|
+
state = await actor.getErrorState();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
expect(state.attempts).toBe(2);
|
|
252
|
+
expect(state.events).toHaveLength(1);
|
|
253
|
+
expect(state.events[0]).toEqual(
|
|
254
|
+
expect.objectContaining({
|
|
255
|
+
step: expect.objectContaining({
|
|
256
|
+
stepName: "flaky",
|
|
257
|
+
attempt: 1,
|
|
258
|
+
willRetry: true,
|
|
259
|
+
retryDelay: 1,
|
|
260
|
+
error: expect.objectContaining({
|
|
261
|
+
name: "Error",
|
|
262
|
+
message: "workflow hook failed",
|
|
263
|
+
}),
|
|
264
|
+
}),
|
|
265
|
+
}),
|
|
266
|
+
);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test("workflow onError can update actor state", async (c) => {
|
|
270
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
271
|
+
const actor = client.workflowErrorHookEffectsActor.getOrCreate([
|
|
272
|
+
"workflow-error-state",
|
|
273
|
+
]);
|
|
274
|
+
|
|
275
|
+
await actor.startWorkflow();
|
|
276
|
+
|
|
277
|
+
let state = await actor.getErrorState();
|
|
278
|
+
for (
|
|
279
|
+
let i = 0;
|
|
280
|
+
i < 80 &&
|
|
281
|
+
(state.attempts < 2 ||
|
|
282
|
+
state.lastError === null ||
|
|
283
|
+
state.errorCount === 0);
|
|
284
|
+
i++
|
|
285
|
+
) {
|
|
286
|
+
await waitFor(driverTestConfig, 50);
|
|
287
|
+
state = await actor.getErrorState();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
expect(state.attempts).toBe(2);
|
|
291
|
+
expect(state.errorCount).toBe(1);
|
|
292
|
+
expect(state.lastError).toEqual(
|
|
293
|
+
expect.objectContaining({
|
|
294
|
+
step: expect.objectContaining({
|
|
295
|
+
stepName: "flaky",
|
|
296
|
+
attempt: 1,
|
|
297
|
+
willRetry: true,
|
|
298
|
+
retryDelay: 1,
|
|
299
|
+
error: expect.objectContaining({
|
|
300
|
+
name: "Error",
|
|
301
|
+
message: "workflow hook failed",
|
|
302
|
+
}),
|
|
303
|
+
}),
|
|
304
|
+
}),
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
test("workflow onError can broadcast actor events", async (c) => {
|
|
309
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
310
|
+
const actor = client.workflowErrorHookEffectsActor
|
|
311
|
+
.getOrCreate(["workflow-error-broadcast"])
|
|
312
|
+
.connect();
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
const eventPromise = new Promise((resolve) => {
|
|
316
|
+
actor.once("workflowError", resolve);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
await actor.startWorkflow();
|
|
320
|
+
|
|
321
|
+
const event = await eventPromise;
|
|
322
|
+
expect(event).toEqual(
|
|
323
|
+
expect.objectContaining({
|
|
324
|
+
step: expect.objectContaining({
|
|
325
|
+
stepName: "flaky",
|
|
326
|
+
attempt: 1,
|
|
327
|
+
willRetry: true,
|
|
328
|
+
retryDelay: 1,
|
|
329
|
+
error: expect.objectContaining({
|
|
330
|
+
name: "Error",
|
|
331
|
+
message: "workflow hook failed",
|
|
332
|
+
}),
|
|
333
|
+
}),
|
|
334
|
+
}),
|
|
335
|
+
);
|
|
336
|
+
} finally {
|
|
337
|
+
await actor.dispose();
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test("workflow onError can enqueue actor messages", async (c) => {
|
|
342
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
343
|
+
const actor = client.workflowErrorHookEffectsActor.getOrCreate([
|
|
344
|
+
"workflow-error-queue",
|
|
345
|
+
]);
|
|
346
|
+
|
|
347
|
+
await actor.startWorkflow();
|
|
348
|
+
|
|
349
|
+
const queuedError = await actor.receiveQueuedError();
|
|
350
|
+
expect(queuedError).toEqual(
|
|
351
|
+
expect.objectContaining({
|
|
352
|
+
step: expect.objectContaining({
|
|
353
|
+
stepName: "flaky",
|
|
354
|
+
attempt: 1,
|
|
355
|
+
willRetry: true,
|
|
356
|
+
retryDelay: 1,
|
|
357
|
+
error: expect.objectContaining({
|
|
358
|
+
name: "Error",
|
|
359
|
+
message: "workflow hook failed",
|
|
360
|
+
}),
|
|
361
|
+
}),
|
|
362
|
+
}),
|
|
363
|
+
);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
test.skipIf(driverTestConfig.skip?.sleep)(
|
|
367
|
+
"completed workflows sleep instead of destroying the actor",
|
|
368
|
+
async (c) => {
|
|
369
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
370
|
+
const actor = client.workflowCompleteActor.getOrCreate([
|
|
371
|
+
"workflow-complete",
|
|
372
|
+
]);
|
|
373
|
+
|
|
374
|
+
let state = await actor.getState();
|
|
375
|
+
for (let i = 0; i < 10 && state.sleepCount === 0; i++) {
|
|
376
|
+
await waitFor(driverTestConfig, 100);
|
|
377
|
+
state = await actor.getState();
|
|
378
|
+
}
|
|
379
|
+
expect(state.runCount).toBeGreaterThan(0);
|
|
380
|
+
expect(state.sleepCount).toBeGreaterThan(0);
|
|
381
|
+
expect(state.startCount).toBeGreaterThan(1);
|
|
382
|
+
},
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
test("workflow steps can destroy the actor", async (c) => {
|
|
386
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
387
|
+
const actorKey = "workflow-destroy";
|
|
388
|
+
const observer = client.destroyObserver.getOrCreate(["observer"]);
|
|
389
|
+
await observer.reset();
|
|
390
|
+
|
|
391
|
+
const actor = client.workflowDestroyActor.getOrCreate([actorKey]);
|
|
392
|
+
const actorId = await actor.resolve();
|
|
393
|
+
|
|
394
|
+
await vi.waitFor(async () => {
|
|
395
|
+
const wasDestroyed = await observer.wasDestroyed(actorKey);
|
|
396
|
+
expect(wasDestroyed, "actor onDestroy not called").toBeTruthy();
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
await vi.waitFor(async () => {
|
|
400
|
+
let actorRunning = false;
|
|
401
|
+
try {
|
|
402
|
+
await client.workflowDestroyActor.getForId(actorId).resolve();
|
|
403
|
+
actorRunning = true;
|
|
404
|
+
} catch (err) {
|
|
405
|
+
expect((err as ActorError).group).toBe("actor");
|
|
406
|
+
expect((err as ActorError).code).toBe("not_found");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
expect(actorRunning, "actor still running").toBeFalsy();
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test.skipIf(driverTestConfig.skip?.sleep)(
|
|
414
|
+
"failed workflow steps sleep instead of surfacing as run errors",
|
|
415
|
+
async (c) => {
|
|
416
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
417
|
+
const actor = client.workflowFailedStepActor.getOrCreate([
|
|
418
|
+
"workflow-failed-step",
|
|
419
|
+
]);
|
|
420
|
+
|
|
421
|
+
let state = await actor.getState();
|
|
422
|
+
for (let i = 0; i < 10 && state.sleepCount === 0; i++) {
|
|
423
|
+
await waitFor(driverTestConfig, 100);
|
|
424
|
+
state = await actor.getState();
|
|
425
|
+
}
|
|
426
|
+
expect(state.runCount).toBeGreaterThan(0);
|
|
427
|
+
expect(state.sleepCount).toBeGreaterThan(0);
|
|
428
|
+
expect(state.startCount).toBeGreaterThan(1);
|
|
429
|
+
},
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
test.skipIf(driverTestConfig.skip?.sleep)(
|
|
433
|
+
"workflow onError is not reported again after sleep and wake",
|
|
434
|
+
async (c) => {
|
|
435
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
436
|
+
const actor = client.workflowErrorHookSleepActor.getOrCreate([
|
|
437
|
+
"workflow-error-hook-sleep",
|
|
438
|
+
]);
|
|
439
|
+
|
|
440
|
+
let state = await actor.getErrorState();
|
|
441
|
+
for (
|
|
442
|
+
let i = 0;
|
|
443
|
+
i < 80 &&
|
|
444
|
+
(state.attempts < 2 || state.events.length === 0);
|
|
445
|
+
i++
|
|
446
|
+
) {
|
|
447
|
+
await waitFor(driverTestConfig, 50);
|
|
448
|
+
state = await actor.getErrorState();
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
expect(state.attempts).toBe(2);
|
|
452
|
+
expect(state.events).toHaveLength(1);
|
|
453
|
+
expect(state.wakeCount).toBe(1);
|
|
454
|
+
|
|
455
|
+
await actor.triggerSleep();
|
|
456
|
+
await waitFor(driverTestConfig, 250);
|
|
457
|
+
|
|
458
|
+
let resumedState = await actor.getErrorState();
|
|
459
|
+
for (
|
|
460
|
+
let i = 0;
|
|
461
|
+
i < 40 &&
|
|
462
|
+
(resumedState.wakeCount < 2 || resumedState.sleepCount < 1);
|
|
463
|
+
i++
|
|
464
|
+
) {
|
|
465
|
+
await waitFor(driverTestConfig, 50);
|
|
466
|
+
resumedState = await actor.getErrorState();
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
expect(resumedState.sleepCount).toBeGreaterThanOrEqual(1);
|
|
470
|
+
expect(resumedState.wakeCount).toBeGreaterThanOrEqual(2);
|
|
471
|
+
expect(resumedState.attempts).toBe(2);
|
|
472
|
+
expect(resumedState.events).toHaveLength(1);
|
|
473
|
+
},
|
|
474
|
+
);
|
|
475
|
+
|
|
92
476
|
test.skipIf(driverTestConfig.skip?.sleep)(
|
|
93
477
|
"workflow run teardown does not wait for runStopTimeout",
|
|
94
478
|
async (c) => {
|
|
@@ -2,7 +2,9 @@ import { describe, expect, test } from "vitest";
|
|
|
2
2
|
import type { DriverTestConfig } from "../mod";
|
|
3
3
|
import { setupDriverTest } from "../utils";
|
|
4
4
|
|
|
5
|
-
export function runConnErrorSerializationTests(
|
|
5
|
+
export function runConnErrorSerializationTests(
|
|
6
|
+
driverTestConfig: DriverTestConfig,
|
|
7
|
+
) {
|
|
6
8
|
describe("Connection Error Serialization Tests", () => {
|
|
7
9
|
test("error thrown in createConnState preserves group and code through WebSocket serialization", async (c) => {
|
|
8
10
|
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
@@ -484,7 +484,11 @@ export function runRawWebSocketTests(driverTestConfig: DriverTestConfig) {
|
|
|
484
484
|
ws.addEventListener("open", () => resolve(), { once: true });
|
|
485
485
|
ws.addEventListener("error", reject);
|
|
486
486
|
ws.addEventListener("close", (evt: any) => {
|
|
487
|
-
reject(
|
|
487
|
+
reject(
|
|
488
|
+
new Error(
|
|
489
|
+
`WebSocket closed: code=${evt.code} reason=${evt.reason}`,
|
|
490
|
+
),
|
|
491
|
+
);
|
|
488
492
|
});
|
|
489
493
|
});
|
|
490
494
|
|
package/src/drivers/default.ts
CHANGED
|
@@ -7,9 +7,7 @@ import { DriverConfig, RegistryConfig } from "@/registry/config";
|
|
|
7
7
|
/**
|
|
8
8
|
* Chooses the appropriate driver based on the run configuration.
|
|
9
9
|
*/
|
|
10
|
-
export function chooseDefaultDriver(
|
|
11
|
-
config: RegistryConfig,
|
|
12
|
-
): DriverConfig {
|
|
10
|
+
export function chooseDefaultDriver(config: RegistryConfig): DriverConfig {
|
|
13
11
|
if (config.endpoint && config.driver) {
|
|
14
12
|
throw new UserError(
|
|
15
13
|
"Cannot specify both 'endpoint' and 'driver' in configuration",
|
|
@@ -3,7 +3,8 @@ import type {
|
|
|
3
3
|
RunnerConfig as EngineRunnerConfig,
|
|
4
4
|
HibernatingWebSocketMetadata,
|
|
5
5
|
} from "@rivetkit/engine-runner";
|
|
6
|
-
import type {
|
|
6
|
+
import type { ISqliteVfs } from "@rivetkit/sqlite-vfs";
|
|
7
|
+
import { SqliteVfsPoolManager } from "@/driver-helpers/sqlite-pool";
|
|
7
8
|
import { idToStr, Runner } from "@rivetkit/engine-runner";
|
|
8
9
|
import * as cbor from "cbor-x";
|
|
9
10
|
import type { Context as HonoContext } from "hono";
|
|
@@ -84,9 +85,22 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
84
85
|
#runner: Runner;
|
|
85
86
|
#actors: Map<string, ActorHandler> = new Map();
|
|
86
87
|
#actorRouter: ActorRouter;
|
|
88
|
+
#sqlitePool: SqliteVfsPoolManager;
|
|
87
89
|
|
|
88
|
-
#runnerStarted: PromiseWithResolvers<undefined> = promiseWithResolvers(
|
|
89
|
-
|
|
90
|
+
#runnerStarted: PromiseWithResolvers<undefined> = promiseWithResolvers(
|
|
91
|
+
(reason) =>
|
|
92
|
+
logger().warn({
|
|
93
|
+
msg: "unhandled runner started promise rejection",
|
|
94
|
+
reason,
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
#runnerStopped: PromiseWithResolvers<undefined> = promiseWithResolvers(
|
|
98
|
+
(reason) =>
|
|
99
|
+
logger().warn({
|
|
100
|
+
msg: "unhandled runner stopped promise rejection",
|
|
101
|
+
reason,
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
90
104
|
#isRunnerStopped: boolean = false;
|
|
91
105
|
|
|
92
106
|
// HACK: Track actor stop intent locally since the runner protocol doesn't
|
|
@@ -124,6 +138,7 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
124
138
|
this.#config = config;
|
|
125
139
|
this.#managerDriver = managerDriver;
|
|
126
140
|
this.#inlineClient = inlineClient;
|
|
141
|
+
this.#sqlitePool = new SqliteVfsPoolManager(config);
|
|
127
142
|
|
|
128
143
|
// HACK: Override inspector token (which are likely to be
|
|
129
144
|
// removed later on) with token from x-rivet-token header
|
|
@@ -148,7 +163,6 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
148
163
|
namespace: config.namespace,
|
|
149
164
|
totalSlots: config.runner.totalSlots,
|
|
150
165
|
runnerName: config.runner.runnerName,
|
|
151
|
-
runnerKey: config.runner.runnerKey ?? crypto.randomUUID(),
|
|
152
166
|
metadata: {
|
|
153
167
|
rivetkit: { version: VERSION },
|
|
154
168
|
},
|
|
@@ -169,6 +183,9 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
169
183
|
onActorStart: this.#runnerOnActorStart.bind(this),
|
|
170
184
|
onActorStop: this.#runnerOnActorStop.bind(this),
|
|
171
185
|
logger: getLogger("engine-runner"),
|
|
186
|
+
debugLatencyMs: process.env._RIVET_DEBUG_LATENCY_MS
|
|
187
|
+
? Number.parseInt(process.env._RIVET_DEBUG_LATENCY_MS, 10)
|
|
188
|
+
: undefined,
|
|
172
189
|
};
|
|
173
190
|
|
|
174
191
|
// Create and start runner
|
|
@@ -257,6 +274,14 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
257
274
|
await this.#runner.kvDelete(actorId, keys);
|
|
258
275
|
}
|
|
259
276
|
|
|
277
|
+
async kvDeleteRange(
|
|
278
|
+
actorId: string,
|
|
279
|
+
start: Uint8Array,
|
|
280
|
+
end: Uint8Array,
|
|
281
|
+
): Promise<void> {
|
|
282
|
+
await this.#runner.kvDeleteRange(actorId, start, end);
|
|
283
|
+
}
|
|
284
|
+
|
|
260
285
|
async kvList(actorId: string): Promise<Uint8Array[]> {
|
|
261
286
|
const entries = await this.#runner.kvListPrefix(
|
|
262
287
|
actorId,
|
|
@@ -275,8 +300,16 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
275
300
|
async kvListPrefix(
|
|
276
301
|
actorId: string,
|
|
277
302
|
prefix: Uint8Array,
|
|
303
|
+
options?: {
|
|
304
|
+
reverse?: boolean;
|
|
305
|
+
limit?: number;
|
|
306
|
+
},
|
|
278
307
|
): Promise<[Uint8Array, Uint8Array][]> {
|
|
279
|
-
const result = await this.#runner.kvListPrefix(
|
|
308
|
+
const result = await this.#runner.kvListPrefix(
|
|
309
|
+
actorId,
|
|
310
|
+
prefix,
|
|
311
|
+
options,
|
|
312
|
+
);
|
|
280
313
|
logger().info({
|
|
281
314
|
msg: "kvListPrefix called",
|
|
282
315
|
actorId,
|
|
@@ -287,14 +320,27 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
287
320
|
return result;
|
|
288
321
|
}
|
|
289
322
|
|
|
323
|
+
async kvListRange(
|
|
324
|
+
actorId: string,
|
|
325
|
+
start: Uint8Array,
|
|
326
|
+
end: Uint8Array,
|
|
327
|
+
options?: {
|
|
328
|
+
reverse?: boolean;
|
|
329
|
+
limit?: number;
|
|
330
|
+
},
|
|
331
|
+
): Promise<[Uint8Array, Uint8Array][]> {
|
|
332
|
+
return await this.#runner.kvListRange(
|
|
333
|
+
actorId,
|
|
334
|
+
start,
|
|
335
|
+
end,
|
|
336
|
+
true,
|
|
337
|
+
options,
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
290
341
|
/** Creates a SQLite VFS instance for creating KV-backed databases */
|
|
291
|
-
async createSqliteVfs(): Promise<
|
|
292
|
-
|
|
293
|
-
// Returning a fresh SqliteVfs gives each actor an isolated sqlite module
|
|
294
|
-
// instance, avoiding async re-entrancy across actors.
|
|
295
|
-
const specifier = "@rivetkit/" + "sqlite-vfs";
|
|
296
|
-
const { SqliteVfs } = await import(specifier);
|
|
297
|
-
return new SqliteVfs();
|
|
342
|
+
async createSqliteVfs(actorId: string): Promise<ISqliteVfs> {
|
|
343
|
+
return await this.#sqlitePool.acquire(actorId);
|
|
298
344
|
}
|
|
299
345
|
|
|
300
346
|
// MARK: - Actor Lifecycle
|
|
@@ -364,11 +410,16 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
364
410
|
await Promise.all(stopPromises);
|
|
365
411
|
logger().debug({ msg: "all actors stopped" });
|
|
366
412
|
|
|
413
|
+
await this.#sqlitePool.shutdown();
|
|
414
|
+
|
|
367
415
|
try {
|
|
368
416
|
await this.#runner.shutdown(immediate);
|
|
369
417
|
} catch (error) {
|
|
370
|
-
const message =
|
|
371
|
-
|
|
418
|
+
const message =
|
|
419
|
+
error instanceof Error ? error.message : String(error);
|
|
420
|
+
if (
|
|
421
|
+
message.includes("WebSocket connection closed during shutdown")
|
|
422
|
+
) {
|
|
372
423
|
logger().debug({
|
|
373
424
|
msg: "ignoring shutdown websocket close race",
|
|
374
425
|
error: message,
|
|
@@ -465,7 +516,12 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
465
516
|
// async operations to avoid race conditions where multiple calls might try to
|
|
466
517
|
// create the same handler simultaneously.
|
|
467
518
|
handler = {
|
|
468
|
-
actorStartPromise: promiseWithResolvers((reason) =>
|
|
519
|
+
actorStartPromise: promiseWithResolvers((reason) =>
|
|
520
|
+
logger().warn({
|
|
521
|
+
msg: "unhandled actor start promise rejection",
|
|
522
|
+
reason,
|
|
523
|
+
}),
|
|
524
|
+
),
|
|
469
525
|
};
|
|
470
526
|
this.#actors.set(actorId, handler);
|
|
471
527
|
}
|
|
@@ -508,12 +564,19 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
508
564
|
protocolMetadata,
|
|
509
565
|
});
|
|
510
566
|
|
|
511
|
-
const stopThresholdMax = Math.max(
|
|
567
|
+
const stopThresholdMax = Math.max(
|
|
568
|
+
Number(protocolMetadata.actorStopThreshold) - 1000,
|
|
569
|
+
0,
|
|
570
|
+
);
|
|
512
571
|
handler.actor.overrides.onSleepTimeout = stopThresholdMax;
|
|
513
572
|
handler.actor.overrides.onDestroyTimeout = stopThresholdMax;
|
|
514
573
|
|
|
515
574
|
if (protocolMetadata.serverlessDrainGracePeriod) {
|
|
516
|
-
const drainMax = Math.max(
|
|
575
|
+
const drainMax = Math.max(
|
|
576
|
+
Number(protocolMetadata.serverlessDrainGracePeriod) -
|
|
577
|
+
1000,
|
|
578
|
+
0,
|
|
579
|
+
);
|
|
517
580
|
handler.actor.overrides.runStopTimeout = drainMax;
|
|
518
581
|
handler.actor.overrides.waitUntilTimeout = drainMax;
|
|
519
582
|
}
|
|
@@ -537,7 +600,9 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
537
600
|
`Failed to start actor ${actorId}: ${innerError.message}`,
|
|
538
601
|
{ cause: innerError },
|
|
539
602
|
)
|
|
540
|
-
: new Error(
|
|
603
|
+
: new Error(
|
|
604
|
+
`Failed to start actor ${actorId}: ${String(innerError)}`,
|
|
605
|
+
);
|
|
541
606
|
handler.actor = undefined;
|
|
542
607
|
handler.actorStartError = error;
|
|
543
608
|
handler.actorStartPromise?.reject(error);
|
|
@@ -580,13 +645,21 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
580
645
|
|
|
581
646
|
const handler = this.#actors.get(actorId);
|
|
582
647
|
if (!handler) {
|
|
583
|
-
logger().debug({
|
|
648
|
+
logger().debug({
|
|
649
|
+
msg: "no runner actor handler to stop",
|
|
650
|
+
actorId,
|
|
651
|
+
reason,
|
|
652
|
+
});
|
|
584
653
|
return;
|
|
585
654
|
}
|
|
586
655
|
|
|
587
656
|
if (handler.actorStartPromise) {
|
|
588
657
|
try {
|
|
589
|
-
logger().debug({
|
|
658
|
+
logger().debug({
|
|
659
|
+
msg: "runner actor stopping before it started, waiting",
|
|
660
|
+
actorId,
|
|
661
|
+
generation,
|
|
662
|
+
});
|
|
590
663
|
await handler.actorStartPromise.promise;
|
|
591
664
|
} catch (err) {
|
|
592
665
|
// Start failed, but we still want to clean up the handler
|
|
@@ -1056,4 +1129,4 @@ export class EngineActorDriver implements ActorDriver {
|
|
|
1056
1129
|
entry.bufferedMessageSize = 0;
|
|
1057
1130
|
}
|
|
1058
1131
|
}
|
|
1059
|
-
}
|
|
1132
|
+
}
|