rivetkit 2.0.42 → 2.1.0-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/{tsup/config-CLnylLYY.d.ts → browser/client.d.ts} +2127 -1910
- package/dist/browser/client.js +5182 -0
- package/dist/browser/client.js.map +1 -0
- package/dist/browser/inspector/client.d.ts +130 -0
- package/dist/browser/inspector/client.js +2854 -0
- package/dist/browser/inspector/client.js.map +1 -0
- package/dist/browser/v3-DnYObHH3.d.ts +279 -0
- package/dist/schemas/actor-inspector/v2.ts +796 -0
- package/dist/schemas/actor-inspector/v3.ts +899 -0
- package/dist/schemas/actor-persist/v4.ts +406 -0
- package/dist/schemas/client-protocol/v3.ts +554 -0
- package/dist/schemas/persist/v1.ts +781 -0
- package/dist/schemas/transport/v1.ts +697 -0
- package/dist/tsup/actor/errors.cjs +27 -3
- package/dist/tsup/actor/errors.cjs.map +1 -1
- package/dist/tsup/actor/errors.d.cts +37 -1
- package/dist/tsup/actor/errors.d.ts +37 -1
- package/dist/tsup/actor/errors.js +26 -1
- package/dist/tsup/{actor-router-consts-DzI2szci.d.cts → actor-router-consts-D29T1Z-K.d.cts} +1 -1
- package/dist/tsup/{actor-router-consts-DzI2szci.d.ts → actor-router-consts-D29T1Z-K.d.ts} +1 -1
- package/dist/tsup/chunk-424PT5DM.js +23 -0
- package/dist/tsup/chunk-424PT5DM.js.map +1 -0
- package/dist/tsup/{chunk-JDAD2YFA.js → chunk-5ESWDTHJ.js} +148 -273
- package/dist/tsup/chunk-5ESWDTHJ.js.map +1 -0
- package/dist/tsup/{chunk-FJ3KTN4V.js → chunk-6LIBPELE.js} +119 -11
- package/dist/tsup/chunk-6LIBPELE.js.map +1 -0
- package/dist/tsup/chunk-6LJAZ5R4.cjs +96 -0
- package/dist/tsup/chunk-6LJAZ5R4.cjs.map +1 -0
- package/dist/tsup/{chunk-LFVF5SCU.js → chunk-7HTNH26M.js} +126 -1
- package/dist/tsup/chunk-7HTNH26M.js.map +1 -0
- package/dist/tsup/chunk-7K4CYDGD.js +630 -0
- package/dist/tsup/chunk-7K4CYDGD.js.map +1 -0
- package/dist/tsup/{chunk-XXGJCOL6.js → chunk-A6YIZWTK.js} +2 -2
- package/dist/tsup/chunk-AIYEYMX5.cjs +630 -0
- package/dist/tsup/chunk-AIYEYMX5.cjs.map +1 -0
- package/dist/tsup/{chunk-Q6W7RJJP.js → chunk-DIGBC2VI.js} +211 -2316
- package/dist/tsup/chunk-DIGBC2VI.js.map +1 -0
- package/dist/tsup/{chunk-RZW2DNND.cjs → chunk-F6JYU5IK.cjs} +1957 -1039
- package/dist/tsup/chunk-F6JYU5IK.cjs.map +1 -0
- package/dist/tsup/chunk-HAZL2EPK.cjs +534 -0
- package/dist/tsup/chunk-HAZL2EPK.cjs.map +1 -0
- package/dist/tsup/chunk-HDQ2JUQT.cjs +23 -0
- package/dist/tsup/chunk-HDQ2JUQT.cjs.map +1 -0
- package/dist/tsup/chunk-HIDX4C5Y.cjs +1036 -0
- package/dist/tsup/chunk-HIDX4C5Y.cjs.map +1 -0
- package/dist/tsup/chunk-IVG73YCW.js +534 -0
- package/dist/tsup/chunk-IVG73YCW.js.map +1 -0
- package/dist/tsup/chunk-KJSYAUOM.js +96 -0
- package/dist/tsup/chunk-KJSYAUOM.js.map +1 -0
- package/dist/tsup/{chunk-2XQS746M.cjs → chunk-L47L3ZWJ.cjs} +127 -2
- package/dist/tsup/chunk-L47L3ZWJ.cjs.map +1 -0
- package/dist/tsup/{chunk-H4TB4X25.cjs → chunk-LW6KLR7A.cjs} +126 -18
- package/dist/tsup/chunk-LW6KLR7A.cjs.map +1 -0
- package/dist/tsup/chunk-LXUQ667X.js +2006 -0
- package/dist/tsup/chunk-LXUQ667X.js.map +1 -0
- package/dist/tsup/{chunk-GMAVRZSF.js → chunk-M2T62AZQ.js} +1790 -872
- package/dist/tsup/chunk-M2T62AZQ.js.map +1 -0
- package/dist/tsup/chunk-MZ37VV3P.js +5974 -0
- package/dist/tsup/chunk-MZ37VV3P.js.map +1 -0
- package/dist/tsup/chunk-N4KRDJ56.js +72 -0
- package/dist/tsup/chunk-N4KRDJ56.js.map +1 -0
- package/dist/tsup/chunk-NIYZDWMW.cjs +2006 -0
- package/dist/tsup/chunk-NIYZDWMW.cjs.map +1 -0
- package/dist/tsup/chunk-OMEPCQK2.js +649 -0
- package/dist/tsup/chunk-OMEPCQK2.js.map +1 -0
- package/dist/tsup/chunk-SR3KQE7Q.cjs +72 -0
- package/dist/tsup/chunk-SR3KQE7Q.cjs.map +1 -0
- package/dist/tsup/chunk-SSEP6DHP.cjs +2657 -0
- package/dist/tsup/chunk-SSEP6DHP.cjs.map +1 -0
- package/dist/tsup/chunk-T5YCUGVS.js +1036 -0
- package/dist/tsup/chunk-T5YCUGVS.js.map +1 -0
- package/dist/tsup/{chunk-EJVBH5VF.cjs → chunk-TPGXWFQT.cjs} +3 -3
- package/dist/tsup/{chunk-EJVBH5VF.cjs.map → chunk-TPGXWFQT.cjs.map} +1 -1
- package/dist/tsup/{chunk-X35U3YNX.cjs → chunk-TYLXNCA5.cjs} +214 -339
- package/dist/tsup/chunk-TYLXNCA5.cjs.map +1 -0
- package/dist/tsup/chunk-VKVNIQRQ.js +257 -0
- package/dist/tsup/chunk-VKVNIQRQ.js.map +1 -0
- package/dist/tsup/chunk-XWBAQO5H.cjs +649 -0
- package/dist/tsup/chunk-XWBAQO5H.cjs.map +1 -0
- package/dist/tsup/chunk-YQ4LDVD6.cjs +5974 -0
- package/dist/tsup/chunk-YQ4LDVD6.cjs.map +1 -0
- package/dist/tsup/chunk-ZFY5J2EP.cjs +257 -0
- package/dist/tsup/chunk-ZFY5J2EP.cjs.map +1 -0
- package/dist/tsup/client/mod.cjs +9 -10
- package/dist/tsup/client/mod.cjs.map +1 -1
- package/dist/tsup/client/mod.d.cts +11 -5
- package/dist/tsup/client/mod.d.ts +11 -5
- package/dist/tsup/client/mod.js +8 -8
- package/dist/tsup/common/log.cjs +4 -4
- package/dist/tsup/common/log.d.cts +2 -2
- package/dist/tsup/common/log.d.ts +2 -2
- package/dist/tsup/common/log.js +3 -2
- package/dist/tsup/common/websocket.cjs +5 -5
- package/dist/tsup/common/websocket.js +4 -3
- package/dist/tsup/config-BFqid9Gr.d.ts +2574 -0
- package/dist/tsup/config-BiNoIHRs.d.cts +80 -0
- package/dist/tsup/config-BiNoIHRs.d.ts +80 -0
- package/dist/tsup/{config-CZB2-W8x.d.cts → config-CAZphOS1.d.cts} +681 -355
- package/dist/tsup/db/drizzle/mod.cjs +49 -0
- package/dist/tsup/db/drizzle/mod.cjs.map +1 -0
- package/dist/tsup/db/drizzle/mod.d.cts +17 -0
- package/dist/tsup/db/drizzle/mod.d.ts +17 -0
- package/dist/tsup/db/drizzle/mod.js +49 -0
- package/dist/tsup/db/drizzle/mod.js.map +1 -0
- package/dist/tsup/db/mod.cjs +9 -0
- package/dist/tsup/db/mod.cjs.map +1 -0
- package/dist/tsup/db/mod.d.cts +9 -0
- package/dist/tsup/db/mod.d.ts +9 -0
- package/dist/tsup/db/mod.js +9 -0
- package/dist/tsup/db/mod.js.map +1 -0
- package/dist/tsup/{driver-D0QX9M11.d.ts → driver-Bxv62E2p.d.ts} +2 -2
- package/dist/tsup/{driver-q-zqG7fc.d.cts → driver-DYXwJR5D.d.cts} +2 -2
- package/dist/tsup/driver-helpers/mod.cjs +12 -6
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +12 -5
- package/dist/tsup/driver-helpers/mod.d.ts +12 -5
- package/dist/tsup/driver-helpers/mod.js +12 -5
- package/dist/tsup/driver-test-suite/mod.cjs +1370 -116
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +10 -4
- package/dist/tsup/driver-test-suite/mod.d.ts +10 -4
- package/dist/tsup/driver-test-suite/mod.js +2093 -838
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +29 -3
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.d.cts +124 -3
- package/dist/tsup/inspector/mod.d.ts +124 -3
- package/dist/tsup/inspector/mod.js +72 -45
- package/dist/tsup/keys-CydblqMh.d.cts +13 -0
- package/dist/tsup/keys-CydblqMh.d.ts +13 -0
- package/dist/tsup/mod.cjs +16 -10
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +26 -14
- package/dist/tsup/mod.d.ts +26 -14
- package/dist/tsup/mod.js +20 -13
- package/dist/tsup/serve-test-suite/mod.cjs +1165 -83
- package/dist/tsup/serve-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/serve-test-suite/mod.js +1114 -29
- package/dist/tsup/serve-test-suite/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +84 -11
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +10 -5
- package/dist/tsup/test/mod.d.ts +10 -5
- package/dist/tsup/test/mod.js +85 -11
- package/dist/tsup/test/mod.js.map +1 -1
- package/dist/tsup/utils.cjs +10 -4
- package/dist/tsup/utils.cjs.map +1 -1
- package/dist/tsup/utils.d.cts +72 -2
- package/dist/tsup/utils.d.ts +72 -2
- package/dist/tsup/utils.js +9 -2
- package/dist/tsup/v3-DnYObHH3.d.cts +279 -0
- package/dist/tsup/v3-DnYObHH3.d.ts +279 -0
- package/dist/tsup/workflow/mod.cjs +16 -0
- package/dist/tsup/workflow/mod.cjs.map +1 -0
- package/dist/tsup/workflow/mod.d.cts +83 -0
- package/dist/tsup/workflow/mod.d.ts +83 -0
- package/dist/tsup/workflow/mod.js +16 -0
- package/dist/tsup/workflow/mod.js.map +1 -0
- package/package.json +62 -5
- package/src/actor/config.ts +478 -68
- package/src/actor/conn/mod.ts +68 -16
- package/src/actor/conn/state-manager.ts +2 -2
- package/src/actor/contexts/action.ts +20 -12
- package/src/actor/contexts/base/actor.ts +137 -7
- package/src/actor/contexts/base/conn-init.ts +27 -7
- package/src/actor/contexts/base/conn.ts +27 -18
- package/src/actor/contexts/before-action-response.ts +9 -2
- package/src/actor/contexts/before-connect.ts +7 -2
- package/src/actor/contexts/connect.ts +9 -2
- package/src/actor/contexts/create-conn-state.ts +7 -2
- package/src/actor/contexts/create-vars.ts +16 -3
- package/src/actor/contexts/create.ts +16 -3
- package/src/actor/contexts/destroy.ts +9 -3
- package/src/actor/contexts/disconnect.ts +10 -4
- package/src/actor/contexts/index.ts +4 -3
- package/src/actor/contexts/request.ts +23 -6
- package/src/actor/contexts/run.ts +47 -0
- package/src/actor/contexts/sleep.ts +9 -3
- package/src/actor/contexts/state-change.ts +9 -3
- package/src/actor/contexts/wake.ts +9 -3
- package/src/actor/contexts/websocket.ts +23 -6
- package/src/actor/database.ts +8 -18
- package/src/actor/definition.ts +20 -6
- package/src/actor/driver.ts +32 -3
- package/src/actor/errors.ts +127 -0
- package/src/actor/instance/connection-manager.ts +183 -80
- package/src/actor/instance/event-manager.ts +26 -15
- package/src/actor/instance/keys.ts +117 -0
- package/src/actor/instance/mod.ts +784 -174
- package/src/actor/instance/queue-manager.ts +603 -0
- package/src/actor/instance/queue.ts +287 -0
- package/src/actor/instance/schedule-manager.ts +49 -7
- package/src/actor/instance/state-manager.ts +35 -11
- package/src/actor/instance/traces-driver.ts +128 -0
- package/src/actor/mod.ts +26 -2
- package/src/actor/protocol/old.ts +28 -13
- package/src/actor/protocol/serde.ts +1 -1
- package/src/actor/router-endpoints.ts +177 -21
- package/src/actor/router-websocket-endpoints.ts +18 -29
- package/src/actor/router.ts +177 -0
- package/src/actor/schema.ts +291 -0
- package/src/actor/utils.ts +40 -0
- package/src/client/actor-common.ts +1 -1
- package/src/client/actor-conn.ts +100 -33
- package/src/client/actor-handle.ts +61 -33
- package/src/client/client.ts +2 -4
- package/src/client/config.ts +1 -1
- package/src/client/mod.browser.ts +2 -0
- package/src/client/mod.ts +1 -4
- package/src/client/queue.ts +146 -0
- package/src/client/utils.ts +1 -1
- package/src/common/log.ts +1 -1
- package/src/common/utils.ts +3 -3
- package/src/db/config.ts +100 -0
- package/src/db/drizzle/mod.ts +226 -0
- package/src/db/drizzle/sqlite-core.ts +22 -0
- package/src/db/mod.ts +125 -0
- package/src/db/shared.ts +92 -0
- package/src/db/sqlite-vfs.ts +12 -0
- package/src/driver-helpers/mod.ts +1 -0
- package/src/driver-test-suite/mod.ts +69 -43
- package/src/driver-test-suite/tests/access-control.ts +218 -0
- package/src/driver-test-suite/tests/actor-db-raw.ts +73 -0
- package/src/driver-test-suite/tests/actor-db.ts +394 -0
- package/src/driver-test-suite/tests/actor-inspector.ts +259 -358
- package/src/driver-test-suite/tests/actor-kv.ts +41 -20
- package/src/driver-test-suite/tests/actor-queue.ts +324 -0
- package/src/driver-test-suite/tests/actor-run.ts +181 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +5 -2
- package/src/driver-test-suite/tests/actor-sleep.ts +3 -3
- package/src/driver-test-suite/tests/actor-stateless.ts +70 -0
- package/src/driver-test-suite/tests/actor-workflow.ts +108 -0
- package/src/driver-test-suite/tests/manager-driver.ts +11 -0
- package/src/driver-test-suite/tests/raw-http-request-properties.ts +1 -1
- package/src/driver-test-suite/tests/raw-websocket.ts +12 -12
- package/src/drivers/default.ts +7 -2
- package/src/drivers/engine/actor-driver.ts +45 -37
- package/src/drivers/engine/config.ts +1 -1
- package/src/drivers/file-system/actor.ts +20 -2
- package/src/drivers/file-system/global-state.ts +569 -258
- package/src/drivers/file-system/kv-limits.ts +70 -0
- package/src/drivers/file-system/manager.ts +22 -6
- package/src/drivers/file-system/mod.ts +39 -16
- package/src/drivers/file-system/sqlite-runtime.ts +210 -0
- package/src/inspector/actor-inspector.ts +224 -102
- package/src/inspector/config.ts +1 -1
- package/src/inspector/handler.ts +102 -20
- package/src/inspector/mod.browser.ts +8 -0
- package/src/inspector/mod.ts +2 -0
- package/src/inspector/serve-ui.ts +40 -0
- package/src/inspector/transport.ts +18 -0
- package/src/inspector/utils.ts +5 -39
- package/src/manager/gateway.ts +1 -1
- package/src/manager/protocol/mod.ts +1 -1
- package/src/manager/protocol/query.ts +1 -1
- package/src/manager/router-schema.ts +1 -1
- package/src/manager/router.ts +38 -12
- package/src/manager-api/actors.ts +1 -1
- package/src/manager-api/common.ts +1 -1
- package/src/registry/config/driver.ts +1 -1
- package/src/registry/config/index.ts +212 -43
- package/src/registry/config/legacy-runner.ts +1 -1
- package/src/registry/config/runner.ts +1 -1
- package/src/registry/config/serverless.ts +1 -1
- package/src/registry/index.ts +7 -5
- package/src/remote-manager-driver/api-utils.ts +1 -1
- package/src/schemas/actor-inspector/mod.ts +1 -1
- package/src/schemas/actor-inspector/versioned.ts +195 -8
- package/src/schemas/actor-persist/versioned.ts +87 -7
- package/src/schemas/client-protocol/mod.ts +1 -1
- package/src/schemas/client-protocol/versioned.ts +127 -11
- package/src/schemas/client-protocol-zod/mod.ts +16 -1
- package/src/schemas/persist/mod.ts +1 -0
- package/src/schemas/transport/mod.ts +1 -0
- package/src/serde.ts +1 -1
- package/src/serve-test-suite/mod.ts +10 -9
- package/src/test/mod.ts +15 -56
- package/src/utils/endpoint-parser.test.ts +1 -1
- package/src/utils/endpoint-parser.ts +1 -1
- package/src/utils/env-vars.ts +12 -1
- package/src/utils/node.ts +15 -2
- package/src/utils.test.ts +34 -0
- package/src/utils.ts +140 -6
- package/src/workflow/constants.ts +2 -0
- package/src/workflow/context.ts +532 -0
- package/src/workflow/driver.ts +191 -0
- package/src/workflow/inspector.ts +268 -0
- package/src/workflow/mod.ts +122 -0
- package/dist/tsup/chunk-2IJTYN6K.cjs +0 -278
- package/dist/tsup/chunk-2IJTYN6K.cjs.map +0 -1
- package/dist/tsup/chunk-2XQS746M.cjs.map +0 -1
- package/dist/tsup/chunk-3VP5CSHV.cjs +0 -114
- package/dist/tsup/chunk-3VP5CSHV.cjs.map +0 -1
- package/dist/tsup/chunk-AQFSQMBG.js +0 -114
- package/dist/tsup/chunk-AQFSQMBG.js.map +0 -1
- package/dist/tsup/chunk-E6ZE2YEA.js +0 -664
- package/dist/tsup/chunk-E6ZE2YEA.js.map +0 -1
- package/dist/tsup/chunk-FJ3KTN4V.js.map +0 -1
- package/dist/tsup/chunk-GBENOENJ.cjs +0 -8
- package/dist/tsup/chunk-GBENOENJ.cjs.map +0 -1
- package/dist/tsup/chunk-GD7UXGOE.cjs +0 -4762
- package/dist/tsup/chunk-GD7UXGOE.cjs.map +0 -1
- package/dist/tsup/chunk-GMAVRZSF.js.map +0 -1
- package/dist/tsup/chunk-H4TB4X25.cjs.map +0 -1
- package/dist/tsup/chunk-JDAD2YFA.js.map +0 -1
- package/dist/tsup/chunk-KCOVZOPS.js +0 -1946
- package/dist/tsup/chunk-KCOVZOPS.js.map +0 -1
- package/dist/tsup/chunk-KDFWJKMJ.cjs +0 -664
- package/dist/tsup/chunk-KDFWJKMJ.cjs.map +0 -1
- package/dist/tsup/chunk-LFVF5SCU.js.map +0 -1
- package/dist/tsup/chunk-Q6W7RJJP.js.map +0 -1
- package/dist/tsup/chunk-RUW5CZ5Z.cjs +0 -1949
- package/dist/tsup/chunk-RUW5CZ5Z.cjs.map +0 -1
- package/dist/tsup/chunk-RZW2DNND.cjs.map +0 -1
- package/dist/tsup/chunk-TCOEBUUE.js +0 -278
- package/dist/tsup/chunk-TCOEBUUE.js.map +0 -1
- package/dist/tsup/chunk-X35U3YNX.cjs.map +0 -1
- package/dist/tsup/keys-Chhy4ylv.d.cts +0 -8
- package/dist/tsup/keys-Chhy4ylv.d.ts +0 -8
- package/dist/tsup/v1-Gq4avTK3.d.cts +0 -240
- package/dist/tsup/v1-Gq4avTK3.d.ts +0 -240
- /package/dist/tsup/{chunk-XXGJCOL6.js.map → chunk-A6YIZWTK.js.map} +0 -0
|
@@ -1,39 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
importWebSocket,
|
|
3
3
|
logger
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-A6YIZWTK.js";
|
|
5
5
|
import {
|
|
6
|
-
ACTOR_VERSIONED,
|
|
7
|
-
ActionContext,
|
|
8
|
-
ActorContext,
|
|
9
|
-
BeforeConnectContext,
|
|
10
|
-
CONN_CONNECTED_SYMBOL,
|
|
11
|
-
CONN_DRIVER_SYMBOL,
|
|
12
|
-
CONN_SEND_MESSAGE_SYMBOL,
|
|
13
|
-
CONN_SPEAKS_RIVETKIT_SYMBOL,
|
|
14
|
-
CONN_STATE_MANAGER_SYMBOL,
|
|
15
|
-
CONN_VERSIONED,
|
|
16
6
|
CURRENT_VERSION,
|
|
17
|
-
CURRENT_VERSION2,
|
|
18
|
-
CachedSerializer,
|
|
19
|
-
Conn,
|
|
20
|
-
ConnectContext,
|
|
21
|
-
CreateConnStateContext,
|
|
22
|
-
DeadlineError,
|
|
23
7
|
EncodingSchema,
|
|
24
8
|
HEADER_CONN_PARAMS,
|
|
25
9
|
HEADER_ENCODING,
|
|
26
10
|
HEADER_RIVET_TOKEN,
|
|
27
11
|
HTTP_ACTION_REQUEST_VERSIONED,
|
|
28
12
|
HTTP_ACTION_RESPONSE_VERSIONED,
|
|
13
|
+
HTTP_QUEUE_SEND_REQUEST_VERSIONED,
|
|
14
|
+
HTTP_QUEUE_SEND_RESPONSE_VERSIONED,
|
|
29
15
|
HTTP_RESPONSE_ERROR_VERSIONED,
|
|
30
16
|
HttpActionRequestSchema,
|
|
31
17
|
HttpActionResponseSchema,
|
|
18
|
+
HttpQueueSendRequestSchema,
|
|
19
|
+
HttpQueueSendResponseSchema,
|
|
32
20
|
HttpResponseErrorSchema,
|
|
33
|
-
KEYS,
|
|
34
21
|
PATH_CONNECT,
|
|
35
22
|
PATH_WEBSOCKET_PREFIX,
|
|
36
|
-
RequestContext,
|
|
37
23
|
TO_CLIENT_VERSIONED,
|
|
38
24
|
TO_SERVER_VERSIONED,
|
|
39
25
|
ToClientSchema,
|
|
@@ -41,36 +27,25 @@ import {
|
|
|
41
27
|
WS_PROTOCOL_CONN_PARAMS,
|
|
42
28
|
WS_PROTOCOL_ENCODING,
|
|
43
29
|
WS_PROTOCOL_STANDARD,
|
|
44
|
-
WebSocketContext,
|
|
45
|
-
assertUnreachable as assertUnreachable2,
|
|
46
30
|
contentTypeForEncoding,
|
|
47
|
-
createHttpDriver,
|
|
48
|
-
deadline,
|
|
49
31
|
deserializeActorKey,
|
|
50
32
|
deserializeWithEncoding,
|
|
51
|
-
generateSecureToken,
|
|
52
33
|
inputDataToBuffer,
|
|
53
|
-
isConnStatePath,
|
|
54
|
-
isStatePath,
|
|
55
34
|
jsonStringifyCompat,
|
|
56
|
-
makeConnKey,
|
|
57
|
-
processMessage,
|
|
58
35
|
serializeActorKey,
|
|
59
36
|
serializeWithEncoding,
|
|
60
37
|
tryParseEndpoint,
|
|
61
38
|
uint8ArrayToBase64
|
|
62
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-M2T62AZQ.js";
|
|
40
|
+
import {
|
|
41
|
+
assertUnreachable as assertUnreachable2
|
|
42
|
+
} from "./chunk-T5YCUGVS.js";
|
|
63
43
|
import {
|
|
64
|
-
EXTRA_ERROR_LOG,
|
|
65
|
-
SinglePromiseQueue,
|
|
66
44
|
VERSION,
|
|
67
|
-
arrayBuffersEqual,
|
|
68
45
|
assertUnreachable,
|
|
69
46
|
bufferToArrayBuffer,
|
|
70
47
|
combineUrlPath,
|
|
71
48
|
deconstructError,
|
|
72
|
-
getBaseLogger,
|
|
73
|
-
getIncludeTarget,
|
|
74
49
|
getLogMessage,
|
|
75
50
|
getLogger,
|
|
76
51
|
getNextPhase,
|
|
@@ -80,25 +55,14 @@ import {
|
|
|
80
55
|
getRivetRunner,
|
|
81
56
|
getRivetToken,
|
|
82
57
|
httpUserAgent,
|
|
83
|
-
isCborSerializable,
|
|
84
58
|
noopNext,
|
|
85
59
|
promiseWithResolvers,
|
|
86
60
|
stringifyError
|
|
87
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-6LIBPELE.js";
|
|
88
62
|
import {
|
|
89
|
-
ActionNotFound,
|
|
90
|
-
ActionTimedOut,
|
|
91
63
|
ActorNotFound,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
InvalidRequest,
|
|
95
|
-
InvalidRequestHandlerResponse,
|
|
96
|
-
InvalidStateType,
|
|
97
|
-
OutgoingMessageTooLong,
|
|
98
|
-
RequestHandlerNotDefined,
|
|
99
|
-
StateNotEnabled,
|
|
100
|
-
VarsNotEnabled
|
|
101
|
-
} from "./chunk-LFVF5SCU.js";
|
|
64
|
+
InvalidRequest
|
|
65
|
+
} from "./chunk-7HTNH26M.js";
|
|
102
66
|
|
|
103
67
|
// src/devtools-loader/log.ts
|
|
104
68
|
function logger2() {
|
|
@@ -129,7 +93,7 @@ import * as cbor2 from "cbor-x";
|
|
|
129
93
|
import invariant2 from "invariant";
|
|
130
94
|
|
|
131
95
|
// src/remote-manager-driver/api-utils.ts
|
|
132
|
-
import { z } from "zod";
|
|
96
|
+
import { z } from "zod/v4";
|
|
133
97
|
|
|
134
98
|
// src/client/utils.ts
|
|
135
99
|
import * as cbor from "cbor-x";
|
|
@@ -138,7 +102,7 @@ import invariant from "invariant";
|
|
|
138
102
|
// src/client/errors.ts
|
|
139
103
|
var ActorClientError = class extends Error {
|
|
140
104
|
};
|
|
141
|
-
var
|
|
105
|
+
var InternalError = class extends ActorClientError {
|
|
142
106
|
};
|
|
143
107
|
var ManagerError = class extends ActorClientError {
|
|
144
108
|
constructor(error, opts) {
|
|
@@ -976,7 +940,7 @@ function apiActorToOutput(actor) {
|
|
|
976
940
|
}
|
|
977
941
|
|
|
978
942
|
// src/client/actor-conn.ts
|
|
979
|
-
import * as
|
|
943
|
+
import * as cbor4 from "cbor-x";
|
|
980
944
|
import invariant3 from "invariant";
|
|
981
945
|
import pRetry2 from "p-retry";
|
|
982
946
|
|
|
@@ -1061,8 +1025,74 @@ async function checkForSchedulingError(group, code, actorId, query, driver) {
|
|
|
1061
1025
|
return null;
|
|
1062
1026
|
}
|
|
1063
1027
|
|
|
1028
|
+
// src/client/queue.ts
|
|
1029
|
+
import * as cbor3 from "cbor-x";
|
|
1030
|
+
function createQueueSender(senderOptions) {
|
|
1031
|
+
async function send(name, body, options) {
|
|
1032
|
+
const wait = (options == null ? void 0 : options.wait) ?? false;
|
|
1033
|
+
const timeout = options == null ? void 0 : options.timeout;
|
|
1034
|
+
const result = await sendHttpRequest({
|
|
1035
|
+
url: `http://actor/queue/${encodeURIComponent(name)}`,
|
|
1036
|
+
method: "POST",
|
|
1037
|
+
headers: {
|
|
1038
|
+
[HEADER_ENCODING]: senderOptions.encoding,
|
|
1039
|
+
...senderOptions.params !== void 0 ? {
|
|
1040
|
+
[HEADER_CONN_PARAMS]: JSON.stringify(
|
|
1041
|
+
senderOptions.params
|
|
1042
|
+
)
|
|
1043
|
+
} : {}
|
|
1044
|
+
},
|
|
1045
|
+
body: { body, wait, timeout },
|
|
1046
|
+
encoding: senderOptions.encoding,
|
|
1047
|
+
customFetch: senderOptions.customFetch,
|
|
1048
|
+
signal: options == null ? void 0 : options.signal,
|
|
1049
|
+
requestVersion: CURRENT_VERSION,
|
|
1050
|
+
requestVersionedDataHandler: HTTP_QUEUE_SEND_REQUEST_VERSIONED,
|
|
1051
|
+
responseVersion: CURRENT_VERSION,
|
|
1052
|
+
responseVersionedDataHandler: HTTP_QUEUE_SEND_RESPONSE_VERSIONED,
|
|
1053
|
+
requestZodSchema: HttpQueueSendRequestSchema,
|
|
1054
|
+
responseZodSchema: HttpQueueSendResponseSchema,
|
|
1055
|
+
requestToJson: (value) => ({
|
|
1056
|
+
...value,
|
|
1057
|
+
name
|
|
1058
|
+
}),
|
|
1059
|
+
requestToBare: (value) => ({
|
|
1060
|
+
name: value.name ?? name,
|
|
1061
|
+
body: bufferToArrayBuffer(cbor3.encode(value.body)),
|
|
1062
|
+
wait: value.wait ?? false,
|
|
1063
|
+
timeout: value.timeout !== void 0 ? BigInt(value.timeout) : null
|
|
1064
|
+
}),
|
|
1065
|
+
responseFromJson: (json) => {
|
|
1066
|
+
if (json.response === void 0) {
|
|
1067
|
+
return { status: json.status };
|
|
1068
|
+
}
|
|
1069
|
+
return {
|
|
1070
|
+
status: json.status,
|
|
1071
|
+
response: json.response
|
|
1072
|
+
};
|
|
1073
|
+
},
|
|
1074
|
+
responseFromBare: (bare) => {
|
|
1075
|
+
if (bare.response === null || bare.response === void 0) {
|
|
1076
|
+
return { status: bare.status };
|
|
1077
|
+
}
|
|
1078
|
+
return {
|
|
1079
|
+
status: bare.status,
|
|
1080
|
+
response: cbor3.decode(new Uint8Array(bare.response))
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
});
|
|
1084
|
+
if (wait) {
|
|
1085
|
+
return result;
|
|
1086
|
+
}
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
return {
|
|
1090
|
+
send
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1064
1094
|
// src/client/actor-conn.ts
|
|
1065
|
-
var CONNECT_SYMBOL = Symbol("connect");
|
|
1095
|
+
var CONNECT_SYMBOL = /* @__PURE__ */ Symbol("connect");
|
|
1066
1096
|
var ActorConnRaw = class {
|
|
1067
1097
|
#disposed = false;
|
|
1068
1098
|
/* Will be aborted on dispose. */
|
|
@@ -1076,9 +1106,11 @@ var ActorConnRaw = class {
|
|
|
1076
1106
|
#eventSubscriptions = /* @__PURE__ */ new Map();
|
|
1077
1107
|
#errorHandlers = /* @__PURE__ */ new Set();
|
|
1078
1108
|
#openHandlers = /* @__PURE__ */ new Set();
|
|
1109
|
+
#openScheduled = false;
|
|
1079
1110
|
#closeHandlers = /* @__PURE__ */ new Set();
|
|
1080
1111
|
#statusChangeHandlers = /* @__PURE__ */ new Set();
|
|
1081
1112
|
#actionIdCounter = 0;
|
|
1113
|
+
#queueSender;
|
|
1082
1114
|
/**
|
|
1083
1115
|
* Interval that keeps the NodeJS process alive if this is the only thing running.
|
|
1084
1116
|
*
|
|
@@ -1107,8 +1139,26 @@ var ActorConnRaw = class {
|
|
|
1107
1139
|
this.#params = params;
|
|
1108
1140
|
this.#encoding = encoding;
|
|
1109
1141
|
this.#actorQuery = actorQuery;
|
|
1142
|
+
this.#queueSender = createQueueSender({
|
|
1143
|
+
encoding: this.#encoding,
|
|
1144
|
+
params: this.#params,
|
|
1145
|
+
customFetch: async (request) => {
|
|
1146
|
+
if (!this.#actorId) {
|
|
1147
|
+
const { actorId } = await queryActor(
|
|
1148
|
+
void 0,
|
|
1149
|
+
this.#actorQuery,
|
|
1150
|
+
this.#driver
|
|
1151
|
+
);
|
|
1152
|
+
this.#actorId = actorId;
|
|
1153
|
+
}
|
|
1154
|
+
return this.#driver.sendRequest(this.#actorId, request);
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1110
1157
|
this.#keepNodeAliveInterval = setInterval(() => 6e4);
|
|
1111
1158
|
}
|
|
1159
|
+
send(name, body, options) {
|
|
1160
|
+
return this.#queueSender.send(name, body, options);
|
|
1161
|
+
}
|
|
1112
1162
|
/**
|
|
1113
1163
|
* Call a raw action connection. See {@link ActorConn} for type-safe action calls.
|
|
1114
1164
|
*
|
|
@@ -1123,7 +1173,7 @@ var ActorConnRaw = class {
|
|
|
1123
1173
|
logger().debug({ msg: "action", name: opts.name, args: opts.args });
|
|
1124
1174
|
const actionId = this.#actionIdCounter;
|
|
1125
1175
|
this.#actionIdCounter += 1;
|
|
1126
|
-
const { promise, resolve, reject } = promiseWithResolvers();
|
|
1176
|
+
const { promise, resolve, reject } = promiseWithResolvers((reason) => logger().warn({ msg: "unhandled action promise rejection", reason }));
|
|
1127
1177
|
this.#actionsInFlight.set(actionId, {
|
|
1128
1178
|
name: opts.name,
|
|
1129
1179
|
resolve,
|
|
@@ -1153,12 +1203,11 @@ var ActorConnRaw = class {
|
|
|
1153
1203
|
return output;
|
|
1154
1204
|
}
|
|
1155
1205
|
/**
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
*/
|
|
1206
|
+
* Do not call this directly.
|
|
1207
|
+
* Establishes a connection to the server using the specified endpoint & encoding & driver.
|
|
1208
|
+
*
|
|
1209
|
+
* @protected
|
|
1210
|
+
*/
|
|
1162
1211
|
[CONNECT_SYMBOL]() {
|
|
1163
1212
|
this.#connectWithRetry();
|
|
1164
1213
|
}
|
|
@@ -1231,7 +1280,7 @@ var ActorConnRaw = class {
|
|
|
1231
1280
|
try {
|
|
1232
1281
|
if (this.#onOpenPromise)
|
|
1233
1282
|
throw new Error("#onOpenPromise already defined");
|
|
1234
|
-
this.#onOpenPromise = promiseWithResolvers();
|
|
1283
|
+
this.#onOpenPromise = promiseWithResolvers((reason) => logger().warn({ msg: "unhandled open promise rejection", reason }));
|
|
1235
1284
|
await this.#connectWebSocket();
|
|
1236
1285
|
await this.#onOpenPromise.promise;
|
|
1237
1286
|
} finally {
|
|
@@ -1307,29 +1356,46 @@ var ActorConnRaw = class {
|
|
|
1307
1356
|
}
|
|
1308
1357
|
return;
|
|
1309
1358
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
messageQueueLength: this.#messageQueue.length,
|
|
1313
|
-
connId: this.#connId
|
|
1314
|
-
});
|
|
1315
|
-
this.#setConnStatus("connected");
|
|
1316
|
-
if (this.#onOpenPromise) {
|
|
1317
|
-
this.#onOpenPromise.resolve(void 0);
|
|
1318
|
-
} else {
|
|
1319
|
-
logger().warn({ msg: "#onOpenPromise is undefined" });
|
|
1320
|
-
}
|
|
1321
|
-
for (const eventName of this.#eventSubscriptions.keys()) {
|
|
1322
|
-
this.#sendSubscription(eventName, true);
|
|
1359
|
+
if (this.#connStatus === "connected" || this.#openScheduled) {
|
|
1360
|
+
return;
|
|
1323
1361
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1362
|
+
this.#openScheduled = true;
|
|
1363
|
+
queueMicrotask(() => {
|
|
1364
|
+
this.#openScheduled = false;
|
|
1365
|
+
if (this.#disposed) {
|
|
1366
|
+
logger().debug({
|
|
1367
|
+
msg: "handleOnOpen scheduled after dispose, closing websocket"
|
|
1368
|
+
});
|
|
1369
|
+
if (this.#websocket) {
|
|
1370
|
+
this.#websocket.close(1e3, "Disposed");
|
|
1371
|
+
this.#websocket = void 0;
|
|
1372
|
+
}
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
logger().debug({
|
|
1376
|
+
msg: "socket open",
|
|
1377
|
+
messageQueueLength: this.#messageQueue.length,
|
|
1378
|
+
connId: this.#connId
|
|
1379
|
+
});
|
|
1380
|
+
this.#setConnStatus("connected");
|
|
1381
|
+
if (this.#onOpenPromise) {
|
|
1382
|
+
this.#onOpenPromise.resolve(void 0);
|
|
1383
|
+
} else {
|
|
1384
|
+
logger().warn({ msg: "#onOpenPromise is undefined" });
|
|
1385
|
+
}
|
|
1386
|
+
for (const eventName of this.#eventSubscriptions.keys()) {
|
|
1387
|
+
this.#sendSubscription(eventName, true);
|
|
1388
|
+
}
|
|
1389
|
+
const queue = this.#messageQueue;
|
|
1390
|
+
this.#messageQueue = [];
|
|
1391
|
+
logger().debug({
|
|
1392
|
+
msg: "flushing message queue",
|
|
1393
|
+
queueLength: queue.length
|
|
1394
|
+
});
|
|
1395
|
+
for (const msg of queue) {
|
|
1396
|
+
this.#sendMessage(msg);
|
|
1397
|
+
}
|
|
1329
1398
|
});
|
|
1330
|
-
for (const msg of queue) {
|
|
1331
|
-
this.#sendMessage(msg);
|
|
1332
|
-
}
|
|
1333
1399
|
}
|
|
1334
1400
|
/** Called by the onmessage event from drivers. */
|
|
1335
1401
|
async #handleOnMessage(data) {
|
|
@@ -1531,7 +1597,7 @@ var ActorConnRaw = class {
|
|
|
1531
1597
|
name: action.name
|
|
1532
1598
|
}))
|
|
1533
1599
|
});
|
|
1534
|
-
throw new
|
|
1600
|
+
throw new InternalError(`No in flight response for ${id}`);
|
|
1535
1601
|
}
|
|
1536
1602
|
this.#actionsInFlight.delete(id);
|
|
1537
1603
|
logger().debug({
|
|
@@ -1707,7 +1773,14 @@ var ActorConnRaw = class {
|
|
|
1707
1773
|
messageType: message.body.tag,
|
|
1708
1774
|
actionName: (_a = message.body.val) == null ? void 0 : _a.name
|
|
1709
1775
|
});
|
|
1710
|
-
if (
|
|
1776
|
+
if (this.#connStatus !== "connected") {
|
|
1777
|
+
logger().debug({
|
|
1778
|
+
msg: "websocket init pending, queueing message",
|
|
1779
|
+
connStatus: this.#connStatus,
|
|
1780
|
+
messageType: message.body.tag
|
|
1781
|
+
});
|
|
1782
|
+
queueMessage = true;
|
|
1783
|
+
} else if (readyState === 1) {
|
|
1711
1784
|
try {
|
|
1712
1785
|
const messageSerialized = serializeWithEncoding(
|
|
1713
1786
|
this.#encoding,
|
|
@@ -1727,7 +1800,7 @@ var ActorConnRaw = class {
|
|
|
1727
1800
|
id: msg.body.val.id,
|
|
1728
1801
|
name: msg.body.val.name,
|
|
1729
1802
|
args: bufferToArrayBuffer(
|
|
1730
|
-
|
|
1803
|
+
cbor4.encode(msg.body.val.args)
|
|
1731
1804
|
)
|
|
1732
1805
|
}
|
|
1733
1806
|
}
|
|
@@ -1792,7 +1865,7 @@ var ActorConnRaw = class {
|
|
|
1792
1865
|
group: msg.body.val.group,
|
|
1793
1866
|
code: msg.body.val.code,
|
|
1794
1867
|
message: msg.body.val.message,
|
|
1795
|
-
metadata: msg.body.val.metadata ?
|
|
1868
|
+
metadata: msg.body.val.metadata ? cbor4.decode(
|
|
1796
1869
|
new Uint8Array(
|
|
1797
1870
|
msg.body.val.metadata
|
|
1798
1871
|
)
|
|
@@ -1807,7 +1880,7 @@ var ActorConnRaw = class {
|
|
|
1807
1880
|
tag: "ActionResponse",
|
|
1808
1881
|
val: {
|
|
1809
1882
|
id: msg.body.val.id,
|
|
1810
|
-
output:
|
|
1883
|
+
output: cbor4.decode(
|
|
1811
1884
|
new Uint8Array(msg.body.val.output)
|
|
1812
1885
|
)
|
|
1813
1886
|
}
|
|
@@ -1819,7 +1892,7 @@ var ActorConnRaw = class {
|
|
|
1819
1892
|
tag: "Event",
|
|
1820
1893
|
val: {
|
|
1821
1894
|
name: msg.body.val.name,
|
|
1822
|
-
args:
|
|
1895
|
+
args: cbor4.decode(
|
|
1823
1896
|
new Uint8Array(msg.body.val.args)
|
|
1824
1897
|
)
|
|
1825
1898
|
}
|
|
@@ -1872,7 +1945,7 @@ var ActorConnRaw = class {
|
|
|
1872
1945
|
if (this.#websocket) {
|
|
1873
1946
|
const ws = this.#websocket;
|
|
1874
1947
|
if (ws.readyState !== 2 && ws.readyState !== 3) {
|
|
1875
|
-
const { promise, resolve } = promiseWithResolvers();
|
|
1948
|
+
const { promise, resolve } = promiseWithResolvers((reason) => logger().warn({ msg: "unhandled websocket close promise rejection", reason }));
|
|
1876
1949
|
ws.addEventListener("close", () => resolve(void 0));
|
|
1877
1950
|
ws.close(1e3, "Disposed");
|
|
1878
1951
|
await promise;
|
|
@@ -1899,7 +1972,7 @@ var ActorConnRaw = class {
|
|
|
1899
1972
|
};
|
|
1900
1973
|
|
|
1901
1974
|
// src/client/actor-handle.ts
|
|
1902
|
-
import * as
|
|
1975
|
+
import * as cbor5 from "cbor-x";
|
|
1903
1976
|
import invariant5 from "invariant";
|
|
1904
1977
|
|
|
1905
1978
|
// src/client/raw-utils.ts
|
|
@@ -2004,6 +2077,7 @@ var ActorHandleRaw = class {
|
|
|
2004
2077
|
#encoding;
|
|
2005
2078
|
#actorQuery;
|
|
2006
2079
|
#params;
|
|
2080
|
+
#queueSender;
|
|
2007
2081
|
/**
|
|
2008
2082
|
* Do not call this directly.
|
|
2009
2083
|
*
|
|
@@ -2017,6 +2091,21 @@ var ActorHandleRaw = class {
|
|
|
2017
2091
|
this.#encoding = encoding;
|
|
2018
2092
|
this.#actorQuery = actorQuery;
|
|
2019
2093
|
this.#params = params;
|
|
2094
|
+
this.#queueSender = createQueueSender({
|
|
2095
|
+
encoding: this.#encoding,
|
|
2096
|
+
params: this.#params,
|
|
2097
|
+
customFetch: async (request) => {
|
|
2098
|
+
const { actorId } = await queryActor(
|
|
2099
|
+
void 0,
|
|
2100
|
+
this.#actorQuery,
|
|
2101
|
+
this.#driver
|
|
2102
|
+
);
|
|
2103
|
+
return this.#driver.sendRequest(actorId, request);
|
|
2104
|
+
}
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
send(name, body, options) {
|
|
2108
|
+
return this.#queueSender.send(name, body, options);
|
|
2020
2109
|
}
|
|
2021
2110
|
/**
|
|
2022
2111
|
* Call a raw action. This method sends an HTTP request to invoke the named action.
|
|
@@ -2067,12 +2156,12 @@ var ActorHandleRaw = class {
|
|
|
2067
2156
|
}),
|
|
2068
2157
|
// BARE Request: args needs to be CBOR-encoded
|
|
2069
2158
|
requestToBare: (args) => ({
|
|
2070
|
-
args: bufferToArrayBuffer(
|
|
2159
|
+
args: bufferToArrayBuffer(cbor5.encode(args))
|
|
2071
2160
|
}),
|
|
2072
2161
|
// JSON Response: output is the raw value
|
|
2073
2162
|
responseFromJson: (json) => json.output,
|
|
2074
2163
|
// BARE Response: output is ArrayBuffer that needs CBOR-decoding
|
|
2075
|
-
responseFromBare: (bare) =>
|
|
2164
|
+
responseFromBare: (bare) => cbor5.decode(new Uint8Array(bare.output))
|
|
2076
2165
|
});
|
|
2077
2166
|
return responseData;
|
|
2078
2167
|
} catch (err) {
|
|
@@ -2120,13 +2209,10 @@ var ActorHandleRaw = class {
|
|
|
2120
2209
|
);
|
|
2121
2210
|
}
|
|
2122
2211
|
/**
|
|
2123
|
-
*
|
|
2124
|
-
*
|
|
2125
|
-
* @param input - The URL, path, or Request object
|
|
2126
|
-
* @param init - Standard fetch RequestInit options
|
|
2127
|
-
* @returns Promise<Response> - The raw HTTP response
|
|
2212
|
+
* Fetches a resource from this actor via the /request endpoint. This is a
|
|
2213
|
+
* convenience wrapper around the raw HTTP API.
|
|
2128
2214
|
*/
|
|
2129
|
-
|
|
2215
|
+
fetch(input, init) {
|
|
2130
2216
|
return rawHttpFetch(
|
|
2131
2217
|
this.#driver,
|
|
2132
2218
|
this.#actorQuery,
|
|
@@ -2136,13 +2222,9 @@ var ActorHandleRaw = class {
|
|
|
2136
2222
|
);
|
|
2137
2223
|
}
|
|
2138
2224
|
/**
|
|
2139
|
-
*
|
|
2140
|
-
*
|
|
2141
|
-
* @param path - The path for the WebSocket connection (e.g., "stream")
|
|
2142
|
-
* @param protocols - Optional WebSocket subprotocols
|
|
2143
|
-
* @returns WebSocket - A raw WebSocket connection
|
|
2225
|
+
* Opens a raw WebSocket connection to this actor.
|
|
2144
2226
|
*/
|
|
2145
|
-
|
|
2227
|
+
webSocket(path, protocols) {
|
|
2146
2228
|
return rawWebSocket(
|
|
2147
2229
|
this.#driver,
|
|
2148
2230
|
this.#actorQuery,
|
|
@@ -2154,16 +2236,18 @@ var ActorHandleRaw = class {
|
|
|
2154
2236
|
/**
|
|
2155
2237
|
* Resolves the actor to get its unique actor ID.
|
|
2156
2238
|
*/
|
|
2157
|
-
async resolve(
|
|
2158
|
-
if ("getForKey" in this.#actorQuery
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2239
|
+
async resolve() {
|
|
2240
|
+
if ("getForKey" in this.#actorQuery) {
|
|
2241
|
+
const name = this.#actorQuery.getForKey.name;
|
|
2242
|
+
const { actorId } = await queryActor(
|
|
2243
|
+
void 0,
|
|
2244
|
+
this.#actorQuery,
|
|
2245
|
+
this.#driver
|
|
2246
|
+
);
|
|
2247
|
+
this.#actorQuery = { getForId: { actorId, name } };
|
|
2248
|
+
return actorId;
|
|
2249
|
+
} else if ("getOrCreateForKey" in this.#actorQuery) {
|
|
2250
|
+
const name = this.#actorQuery.getOrCreateForKey.name;
|
|
2167
2251
|
const { actorId } = await queryActor(
|
|
2168
2252
|
void 0,
|
|
2169
2253
|
this.#actorQuery,
|
|
@@ -2193,8 +2277,8 @@ var ActorHandleRaw = class {
|
|
|
2193
2277
|
};
|
|
2194
2278
|
|
|
2195
2279
|
// src/client/client.ts
|
|
2196
|
-
var ACTOR_CONNS_SYMBOL = Symbol("actorConns");
|
|
2197
|
-
var CREATE_ACTOR_CONN_PROXY = Symbol("createActorConnProxy");
|
|
2280
|
+
var ACTOR_CONNS_SYMBOL = /* @__PURE__ */ Symbol("actorConns");
|
|
2281
|
+
var CREATE_ACTOR_CONN_PROXY = /* @__PURE__ */ Symbol("createActorConnProxy");
|
|
2198
2282
|
var ClientRaw = class {
|
|
2199
2283
|
#disposed = false;
|
|
2200
2284
|
[ACTOR_CONNS_SYMBOL] = /* @__PURE__ */ new Set();
|
|
@@ -2426,9 +2510,7 @@ function createActorProxy(handle) {
|
|
|
2426
2510
|
},
|
|
2427
2511
|
// Support for 'in' operator
|
|
2428
2512
|
has(target, prop) {
|
|
2429
|
-
if (typeof prop === "string")
|
|
2430
|
-
return true;
|
|
2431
|
-
}
|
|
2513
|
+
if (typeof prop === "string") return true;
|
|
2432
2514
|
return Reflect.has(target, prop);
|
|
2433
2515
|
},
|
|
2434
2516
|
// Support instanceof checks
|
|
@@ -2462,7 +2544,7 @@ function createActorProxy(handle) {
|
|
|
2462
2544
|
}
|
|
2463
2545
|
|
|
2464
2546
|
// src/client/config.ts
|
|
2465
|
-
import z2 from "zod";
|
|
2547
|
+
import z2 from "zod/v4";
|
|
2466
2548
|
function getDefaultEndpoint() {
|
|
2467
2549
|
var _a;
|
|
2468
2550
|
if (typeof window !== "undefined" && ((_a = window.location) == null ? void 0 : _a.origin)) {
|
|
@@ -2541,2207 +2623,20 @@ function convertRegistryConfigToClientConfig(config) {
|
|
|
2541
2623
|
};
|
|
2542
2624
|
}
|
|
2543
2625
|
|
|
2544
|
-
// src/
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
constructor(actor) {
|
|
2552
|
-
this.actor = actor;
|
|
2553
|
-
this.emitter.on("eventFired", (event) => {
|
|
2554
|
-
const commonParams = {
|
|
2555
|
-
id: crypto.randomUUID(),
|
|
2556
|
-
timestamp: BigInt(Date.now())
|
|
2557
|
-
};
|
|
2558
|
-
this.#lastEvents.push({
|
|
2559
|
-
...commonParams,
|
|
2560
|
-
...transformEvent(event)
|
|
2561
|
-
});
|
|
2562
|
-
if (this.#lastEvents.length > 100) {
|
|
2563
|
-
this.#lastEvents = this.#lastEvents.slice(-100);
|
|
2564
|
-
}
|
|
2565
|
-
});
|
|
2566
|
-
}
|
|
2567
|
-
emitter = createNanoEvents();
|
|
2568
|
-
#lastEvents = [];
|
|
2569
|
-
getLastEvents() {
|
|
2570
|
-
return this.#lastEvents;
|
|
2571
|
-
}
|
|
2572
|
-
clearEvents() {
|
|
2573
|
-
this.#lastEvents = [];
|
|
2574
|
-
this.emitter.emit("eventsChanged");
|
|
2575
|
-
}
|
|
2576
|
-
// actor accessor methods
|
|
2577
|
-
isDatabaseEnabled() {
|
|
2578
|
-
try {
|
|
2579
|
-
return this.actor.db !== void 0;
|
|
2580
|
-
} catch {
|
|
2581
|
-
return false;
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
|
-
isStateEnabled() {
|
|
2585
|
-
return this.actor.stateEnabled;
|
|
2586
|
-
}
|
|
2587
|
-
getState() {
|
|
2588
|
-
if (!this.actor.stateEnabled) {
|
|
2589
|
-
throw new StateNotEnabled();
|
|
2590
|
-
}
|
|
2591
|
-
return bufferToArrayBuffer(
|
|
2592
|
-
cbor5.encode(this.actor.stateManager.persistRaw.state)
|
|
2593
|
-
);
|
|
2594
|
-
}
|
|
2595
|
-
getRpcs() {
|
|
2596
|
-
return this.actor.actions;
|
|
2597
|
-
}
|
|
2598
|
-
getConnections() {
|
|
2599
|
-
return Array.from(
|
|
2600
|
-
this.actor.connectionManager.connections.entries()
|
|
2601
|
-
).map(([id, conn]) => {
|
|
2602
|
-
var _a, _b;
|
|
2603
|
-
const connStateManager = conn[CONN_STATE_MANAGER_SYMBOL];
|
|
2604
|
-
return {
|
|
2605
|
-
type: (_a = conn[CONN_DRIVER_SYMBOL]) == null ? void 0 : _a.type,
|
|
2606
|
-
id,
|
|
2607
|
-
details: bufferToArrayBuffer(
|
|
2608
|
-
cbor5.encode({
|
|
2609
|
-
type: (_b = conn[CONN_DRIVER_SYMBOL]) == null ? void 0 : _b.type,
|
|
2610
|
-
params: conn.params,
|
|
2611
|
-
stateEnabled: connStateManager.stateEnabled,
|
|
2612
|
-
state: connStateManager.stateEnabled ? connStateManager.state : void 0,
|
|
2613
|
-
subscriptions: conn.subscriptions.size,
|
|
2614
|
-
isHibernatable: conn.isHibernatable
|
|
2615
|
-
// TODO: Include underlying hibernatable metadata +
|
|
2616
|
-
// path + headers
|
|
2617
|
-
})
|
|
2618
|
-
)
|
|
2619
|
-
};
|
|
2620
|
-
});
|
|
2621
|
-
}
|
|
2622
|
-
async setState(state) {
|
|
2623
|
-
if (!this.actor.stateEnabled) {
|
|
2624
|
-
throw new StateNotEnabled();
|
|
2625
|
-
}
|
|
2626
|
-
this.actor.stateManager.state = cbor5.decode(Buffer.from(state));
|
|
2627
|
-
await this.actor.stateManager.saveState({ immediate: true });
|
|
2628
|
-
}
|
|
2629
|
-
async executeAction(name, params) {
|
|
2630
|
-
const conn = await this.actor.connectionManager.prepareAndConnectConn(
|
|
2631
|
-
createHttpDriver(),
|
|
2632
|
-
// TODO: This may cause issues
|
|
2633
|
-
void 0,
|
|
2634
|
-
void 0,
|
|
2635
|
-
void 0,
|
|
2636
|
-
void 0
|
|
2637
|
-
);
|
|
2638
|
-
try {
|
|
2639
|
-
return bufferToArrayBuffer(
|
|
2640
|
-
cbor5.encode(
|
|
2641
|
-
await this.actor.executeAction(
|
|
2642
|
-
new ActionContext(this.actor, conn),
|
|
2643
|
-
name,
|
|
2644
|
-
cbor5.decode(Buffer.from(params))
|
|
2645
|
-
)
|
|
2646
|
-
)
|
|
2647
|
-
);
|
|
2648
|
-
} finally {
|
|
2649
|
-
conn.disconnect();
|
|
2650
|
-
}
|
|
2651
|
-
}
|
|
2652
|
-
};
|
|
2653
|
-
function transformEvent(event) {
|
|
2654
|
-
if (event.type === "action") {
|
|
2655
|
-
return {
|
|
2656
|
-
body: {
|
|
2657
|
-
tag: "ActionEvent",
|
|
2658
|
-
val: {
|
|
2659
|
-
name: event.name,
|
|
2660
|
-
args: bufferToArrayBuffer(cbor5.encode(event.args)),
|
|
2661
|
-
connId: event.connId
|
|
2662
|
-
}
|
|
2663
|
-
}
|
|
2664
|
-
};
|
|
2665
|
-
} else if (event.type === "subscribe") {
|
|
2666
|
-
return {
|
|
2667
|
-
body: {
|
|
2668
|
-
tag: "SubscribeEvent",
|
|
2669
|
-
val: {
|
|
2670
|
-
eventName: event.eventName,
|
|
2671
|
-
connId: event.connId
|
|
2672
|
-
}
|
|
2673
|
-
}
|
|
2674
|
-
};
|
|
2675
|
-
} else if (event.type === "unsubscribe") {
|
|
2676
|
-
return {
|
|
2677
|
-
body: {
|
|
2678
|
-
tag: "UnSubscribeEvent",
|
|
2679
|
-
val: {
|
|
2680
|
-
eventName: event.eventName,
|
|
2681
|
-
connId: event.connId
|
|
2682
|
-
}
|
|
2683
|
-
}
|
|
2684
|
-
};
|
|
2685
|
-
} else if (event.type === "event") {
|
|
2686
|
-
return {
|
|
2687
|
-
body: {
|
|
2688
|
-
tag: "FiredEvent",
|
|
2689
|
-
val: {
|
|
2690
|
-
eventName: event.eventName,
|
|
2691
|
-
args: bufferToArrayBuffer(cbor5.encode(event.args)),
|
|
2692
|
-
connId: event.connId
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
};
|
|
2696
|
-
} else if (event.type === "broadcast") {
|
|
2697
|
-
return {
|
|
2698
|
-
body: {
|
|
2699
|
-
tag: "BroadcastEvent",
|
|
2700
|
-
val: {
|
|
2701
|
-
eventName: event.eventName,
|
|
2702
|
-
args: bufferToArrayBuffer(cbor5.encode(event.args))
|
|
2703
|
-
}
|
|
2704
|
-
}
|
|
2705
|
-
};
|
|
2706
|
-
} else {
|
|
2707
|
-
assertUnreachable(event);
|
|
2626
|
+
// src/client/mod.ts
|
|
2627
|
+
function createClient(endpointOrConfig) {
|
|
2628
|
+
const configInput = endpointOrConfig === void 0 ? {} : typeof endpointOrConfig === "string" ? { endpoint: endpointOrConfig } : endpointOrConfig;
|
|
2629
|
+
const config = ClientConfigSchema.parse(configInput);
|
|
2630
|
+
const driver = new RemoteManagerDriver(config);
|
|
2631
|
+
if (config.devtools) {
|
|
2632
|
+
injectDevtools(config);
|
|
2708
2633
|
}
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
// src/actor/conn/persisted.ts
|
|
2712
|
-
import * as cbor6 from "cbor-x";
|
|
2713
|
-
function convertConnToBarePersistedConn(persist) {
|
|
2714
|
-
return {
|
|
2715
|
-
id: persist.id,
|
|
2716
|
-
parameters: bufferToArrayBuffer(cbor6.encode(persist.parameters)),
|
|
2717
|
-
state: bufferToArrayBuffer(cbor6.encode(persist.state)),
|
|
2718
|
-
subscriptions: persist.subscriptions.map((sub) => ({
|
|
2719
|
-
eventName: sub.eventName
|
|
2720
|
-
})),
|
|
2721
|
-
gatewayId: persist.gatewayId,
|
|
2722
|
-
requestId: persist.requestId,
|
|
2723
|
-
serverMessageIndex: persist.serverMessageIndex,
|
|
2724
|
-
clientMessageIndex: persist.clientMessageIndex,
|
|
2725
|
-
requestPath: persist.requestPath,
|
|
2726
|
-
requestHeaders: new Map(Object.entries(persist.requestHeaders))
|
|
2727
|
-
};
|
|
2728
|
-
}
|
|
2729
|
-
function convertConnFromBarePersistedConn(bareData) {
|
|
2730
|
-
return {
|
|
2731
|
-
id: bareData.id,
|
|
2732
|
-
parameters: cbor6.decode(new Uint8Array(bareData.parameters)),
|
|
2733
|
-
state: cbor6.decode(new Uint8Array(bareData.state)),
|
|
2734
|
-
subscriptions: bareData.subscriptions.map((sub) => ({
|
|
2735
|
-
eventName: sub.eventName
|
|
2736
|
-
})),
|
|
2737
|
-
gatewayId: bareData.gatewayId,
|
|
2738
|
-
requestId: bareData.requestId,
|
|
2739
|
-
serverMessageIndex: bareData.serverMessageIndex,
|
|
2740
|
-
clientMessageIndex: bareData.clientMessageIndex,
|
|
2741
|
-
requestPath: bareData.requestPath,
|
|
2742
|
-
requestHeaders: Object.fromEntries(bareData.requestHeaders)
|
|
2743
|
-
};
|
|
2744
|
-
}
|
|
2745
|
-
|
|
2746
|
-
// src/actor/schedule.ts
|
|
2747
|
-
var Schedule = class {
|
|
2748
|
-
#actor;
|
|
2749
|
-
constructor(actor) {
|
|
2750
|
-
this.#actor = actor;
|
|
2751
|
-
}
|
|
2752
|
-
async after(duration, fn, ...args) {
|
|
2753
|
-
await this.#actor.scheduleEvent(Date.now() + duration, fn, args);
|
|
2754
|
-
}
|
|
2755
|
-
async at(timestamp, fn, ...args) {
|
|
2756
|
-
await this.#actor.scheduleEvent(timestamp, fn, args);
|
|
2757
|
-
}
|
|
2758
|
-
};
|
|
2759
|
-
|
|
2760
|
-
// src/actor/instance/connection-manager.ts
|
|
2761
|
-
import invariant6 from "invariant";
|
|
2762
|
-
var ConnectionManager = class {
|
|
2763
|
-
#actor;
|
|
2764
|
-
#connections = /* @__PURE__ */ new Map();
|
|
2765
|
-
/** Connections that have had their state changed and need to be persisted. */
|
|
2766
|
-
#connsWithPersistChanged = /* @__PURE__ */ new Set();
|
|
2767
|
-
constructor(actor) {
|
|
2768
|
-
this.#actor = actor;
|
|
2769
|
-
}
|
|
2770
|
-
get connections() {
|
|
2771
|
-
return this.#connections;
|
|
2772
|
-
}
|
|
2773
|
-
getConnForId(id) {
|
|
2774
|
-
return this.#connections.get(id);
|
|
2775
|
-
}
|
|
2776
|
-
get connsWithPersistChanged() {
|
|
2777
|
-
return this.#connsWithPersistChanged;
|
|
2778
|
-
}
|
|
2779
|
-
clearConnWithPersistChanged() {
|
|
2780
|
-
this.#connsWithPersistChanged.clear();
|
|
2781
|
-
}
|
|
2782
|
-
markConnWithPersistChanged(conn) {
|
|
2783
|
-
invariant6(
|
|
2784
|
-
conn.isHibernatable,
|
|
2785
|
-
"cannot mark non-hibernatable conn for persist"
|
|
2786
|
-
);
|
|
2787
|
-
this.#actor.rLog.debug({
|
|
2788
|
-
msg: "marked connection as changed",
|
|
2789
|
-
connId: conn.id,
|
|
2790
|
-
totalChanged: this.#connsWithPersistChanged.size
|
|
2791
|
-
});
|
|
2792
|
-
this.#connsWithPersistChanged.add(conn.id);
|
|
2793
|
-
this.#actor.stateManager.savePersistThrottled();
|
|
2794
|
-
}
|
|
2795
|
-
// MARK: - Connection Lifecycle
|
|
2796
|
-
/**
|
|
2797
|
-
* Handles pre-connection logic (i.e. auth & create state) before actually connecting the connection.
|
|
2798
|
-
*/
|
|
2799
|
-
async prepareConn(driver, params, request, requestPath, requestHeaders, isHibernatable, isRestoringHibernatable) {
|
|
2800
|
-
this.#actor.assertReady();
|
|
2801
|
-
if (isRestoringHibernatable) {
|
|
2802
|
-
return this.#reconnectHibernatableConn(driver);
|
|
2803
|
-
}
|
|
2804
|
-
if (this.#actor.config.onBeforeConnect) {
|
|
2805
|
-
const ctx = new BeforeConnectContext(this.#actor, request);
|
|
2806
|
-
await this.#actor.config.onBeforeConnect(ctx, params);
|
|
2807
|
-
}
|
|
2808
|
-
let connState;
|
|
2809
|
-
if (this.#actor.connStateEnabled) {
|
|
2810
|
-
connState = await this.#createConnState(params, request);
|
|
2811
|
-
}
|
|
2812
|
-
let connData;
|
|
2813
|
-
if (isHibernatable) {
|
|
2814
|
-
const hibernatable = driver.hibernatable;
|
|
2815
|
-
invariant6(hibernatable, "must have hibernatable");
|
|
2816
|
-
invariant6(requestPath, "missing requestPath for hibernatable ws");
|
|
2817
|
-
invariant6(
|
|
2818
|
-
requestHeaders,
|
|
2819
|
-
"missing requestHeaders for hibernatable ws"
|
|
2820
|
-
);
|
|
2821
|
-
connData = {
|
|
2822
|
-
hibernatable: {
|
|
2823
|
-
id: crypto.randomUUID(),
|
|
2824
|
-
parameters: params,
|
|
2825
|
-
state: connState,
|
|
2826
|
-
subscriptions: [],
|
|
2827
|
-
gatewayId: hibernatable.gatewayId,
|
|
2828
|
-
requestId: hibernatable.requestId,
|
|
2829
|
-
clientMessageIndex: 0,
|
|
2830
|
-
// First message index will be 1, so we start at 0
|
|
2831
|
-
serverMessageIndex: 0,
|
|
2832
|
-
requestPath,
|
|
2833
|
-
requestHeaders
|
|
2834
|
-
}
|
|
2835
|
-
};
|
|
2836
|
-
} else {
|
|
2837
|
-
connData = {
|
|
2838
|
-
ephemeral: {
|
|
2839
|
-
id: crypto.randomUUID(),
|
|
2840
|
-
parameters: params,
|
|
2841
|
-
state: connState
|
|
2842
|
-
}
|
|
2843
|
-
};
|
|
2844
|
-
}
|
|
2845
|
-
const conn = new Conn(this.#actor, connData);
|
|
2846
|
-
conn[CONN_DRIVER_SYMBOL] = driver;
|
|
2847
|
-
return conn;
|
|
2848
|
-
}
|
|
2849
|
-
/**
|
|
2850
|
-
* Adds a connection form prepareConn to the actor and calls onConnect.
|
|
2851
|
-
*
|
|
2852
|
-
* This method is intentionally not async since it needs to be called in
|
|
2853
|
-
* `onOpen` for WebSockets. If this is async, the order of open events will
|
|
2854
|
-
* be messed up and cause race conditions that can drop WebSocket messages.
|
|
2855
|
-
* So all async work in prepareConn.
|
|
2856
|
-
*/
|
|
2857
|
-
connectConn(conn) {
|
|
2858
|
-
invariant6(!this.#connections.has(conn.id), "conn already connected");
|
|
2859
|
-
this.#connections.set(conn.id, conn);
|
|
2860
|
-
if (this.#actor.driver.onCreateConn) {
|
|
2861
|
-
this.#actor.driver.onCreateConn(conn);
|
|
2862
|
-
}
|
|
2863
|
-
if (conn.isHibernatable) {
|
|
2864
|
-
this.markConnWithPersistChanged(conn);
|
|
2865
|
-
}
|
|
2866
|
-
this.#callOnConnect(conn);
|
|
2867
|
-
this.#actor.inspector.emitter.emit("connectionsUpdated");
|
|
2868
|
-
this.#actor.resetSleepTimer();
|
|
2869
|
-
conn[CONN_CONNECTED_SYMBOL] = true;
|
|
2870
|
-
if (conn[CONN_SPEAKS_RIVETKIT_SYMBOL]) {
|
|
2871
|
-
const initData = { actorId: this.#actor.id, connectionId: conn.id };
|
|
2872
|
-
conn[CONN_SEND_MESSAGE_SYMBOL](
|
|
2873
|
-
new CachedSerializer(
|
|
2874
|
-
initData,
|
|
2875
|
-
TO_CLIENT_VERSIONED,
|
|
2876
|
-
CURRENT_VERSION,
|
|
2877
|
-
ToClientSchema,
|
|
2878
|
-
// JSON: identity conversion (no nested data to encode)
|
|
2879
|
-
(value) => ({
|
|
2880
|
-
body: {
|
|
2881
|
-
tag: "Init",
|
|
2882
|
-
val: value
|
|
2883
|
-
}
|
|
2884
|
-
}),
|
|
2885
|
-
// BARE/CBOR: identity conversion (no nested data to encode)
|
|
2886
|
-
(value) => ({
|
|
2887
|
-
body: {
|
|
2888
|
-
tag: "Init",
|
|
2889
|
-
val: value
|
|
2890
|
-
}
|
|
2891
|
-
})
|
|
2892
|
-
)
|
|
2893
|
-
);
|
|
2894
|
-
}
|
|
2895
|
-
}
|
|
2896
|
-
#reconnectHibernatableConn(driver) {
|
|
2897
|
-
invariant6(driver.hibernatable, "missing requestIdBuf");
|
|
2898
|
-
const existingConn = this.findHibernatableConn(
|
|
2899
|
-
driver.hibernatable.gatewayId,
|
|
2900
|
-
driver.hibernatable.requestId
|
|
2901
|
-
);
|
|
2902
|
-
invariant6(
|
|
2903
|
-
existingConn,
|
|
2904
|
-
"cannot find connection for restoring connection"
|
|
2905
|
-
);
|
|
2906
|
-
this.#actor.rLog.debug({
|
|
2907
|
-
msg: "reconnecting hibernatable websocket connection",
|
|
2908
|
-
connectionId: existingConn.id
|
|
2909
|
-
});
|
|
2910
|
-
if (existingConn[CONN_DRIVER_SYMBOL]) {
|
|
2911
|
-
this.#disconnectExistingDriver(existingConn);
|
|
2912
|
-
}
|
|
2913
|
-
existingConn[CONN_DRIVER_SYMBOL] = driver;
|
|
2914
|
-
this.#actor.resetSleepTimer();
|
|
2915
|
-
existingConn[CONN_CONNECTED_SYMBOL] = true;
|
|
2916
|
-
this.#actor.inspector.emitter.emit("connectionsUpdated");
|
|
2917
|
-
return existingConn;
|
|
2918
|
-
}
|
|
2919
|
-
#disconnectExistingDriver(conn) {
|
|
2920
|
-
const driver = conn[CONN_DRIVER_SYMBOL];
|
|
2921
|
-
if (driver == null ? void 0 : driver.disconnect) {
|
|
2922
|
-
driver.disconnect(
|
|
2923
|
-
this.#actor,
|
|
2924
|
-
conn,
|
|
2925
|
-
"Reconnecting hibernatable websocket with new driver state"
|
|
2926
|
-
);
|
|
2927
|
-
}
|
|
2928
|
-
}
|
|
2929
|
-
/**
|
|
2930
|
-
* Handle connection disconnection.
|
|
2931
|
-
*
|
|
2932
|
-
* This is called by `Conn.disconnect`. This should not call `Conn.disconnect.`
|
|
2933
|
-
*/
|
|
2934
|
-
async connDisconnected(conn) {
|
|
2935
|
-
this.#connections.delete(conn.id);
|
|
2936
|
-
this.#actor.rLog.debug({ msg: "removed conn", connId: conn.id });
|
|
2937
|
-
if (this.#actor.driver.onDestroyConn) {
|
|
2938
|
-
this.#actor.driver.onDestroyConn(conn);
|
|
2939
|
-
}
|
|
2940
|
-
for (const eventName of [...conn.subscriptions.values()]) {
|
|
2941
|
-
this.#actor.eventManager.removeSubscription(eventName, conn, true);
|
|
2942
|
-
}
|
|
2943
|
-
this.#actor.resetSleepTimer();
|
|
2944
|
-
this.#actor.inspector.emitter.emit("connectionsUpdated");
|
|
2945
|
-
if (this.#actor.config.onDisconnect) {
|
|
2946
|
-
try {
|
|
2947
|
-
const result = this.#actor.config.onDisconnect(
|
|
2948
|
-
this.#actor.actorContext,
|
|
2949
|
-
conn
|
|
2950
|
-
);
|
|
2951
|
-
if (result instanceof Promise) {
|
|
2952
|
-
result.catch((error) => {
|
|
2953
|
-
this.#actor.rLog.error({
|
|
2954
|
-
msg: "error in `onDisconnect`",
|
|
2955
|
-
error: stringifyError(error)
|
|
2956
|
-
});
|
|
2957
|
-
});
|
|
2958
|
-
}
|
|
2959
|
-
} catch (error) {
|
|
2960
|
-
this.#actor.rLog.error({
|
|
2961
|
-
msg: "error in `onDisconnect`",
|
|
2962
|
-
error: stringifyError(error)
|
|
2963
|
-
});
|
|
2964
|
-
}
|
|
2965
|
-
}
|
|
2966
|
-
this.#connsWithPersistChanged.delete(conn.id);
|
|
2967
|
-
if (conn.isHibernatable) {
|
|
2968
|
-
const key = makeConnKey(conn.id);
|
|
2969
|
-
try {
|
|
2970
|
-
await this.#actor.driver.kvBatchDelete(this.#actor.id, [key]);
|
|
2971
|
-
this.#actor.rLog.debug({
|
|
2972
|
-
msg: "removed connection from KV",
|
|
2973
|
-
connId: conn.id
|
|
2974
|
-
});
|
|
2975
|
-
} catch (err) {
|
|
2976
|
-
this.#actor.rLog.error({
|
|
2977
|
-
msg: "kvBatchDelete failed for conn",
|
|
2978
|
-
err: stringifyError(err)
|
|
2979
|
-
});
|
|
2980
|
-
}
|
|
2981
|
-
}
|
|
2982
|
-
}
|
|
2983
|
-
/**
|
|
2984
|
-
* Utilify function for call sites that don't need a separate prepare and connect phase.
|
|
2985
|
-
*/
|
|
2986
|
-
async prepareAndConnectConn(driver, params, request, requestPath, requestHeaders) {
|
|
2987
|
-
const conn = await this.prepareConn(
|
|
2988
|
-
driver,
|
|
2989
|
-
params,
|
|
2990
|
-
request,
|
|
2991
|
-
requestPath,
|
|
2992
|
-
requestHeaders,
|
|
2993
|
-
false,
|
|
2994
|
-
false
|
|
2995
|
-
);
|
|
2996
|
-
this.connectConn(conn);
|
|
2997
|
-
return conn;
|
|
2998
|
-
}
|
|
2999
|
-
// MARK: - Persistence
|
|
3000
|
-
/**
|
|
3001
|
-
* Restores connections from persisted data during actor initialization.
|
|
3002
|
-
*/
|
|
3003
|
-
restoreConnections(connections) {
|
|
3004
|
-
for (const connPersist of connections) {
|
|
3005
|
-
const conn = new Conn(this.#actor, {
|
|
3006
|
-
hibernatable: connPersist
|
|
3007
|
-
});
|
|
3008
|
-
this.#connections.set(conn.id, conn);
|
|
3009
|
-
if (this.#actor.driver.onCreateConn) {
|
|
3010
|
-
this.#actor.driver.onCreateConn(conn);
|
|
3011
|
-
}
|
|
3012
|
-
for (const sub of connPersist.subscriptions) {
|
|
3013
|
-
this.#actor.eventManager.addSubscription(
|
|
3014
|
-
sub.eventName,
|
|
3015
|
-
conn,
|
|
3016
|
-
true
|
|
3017
|
-
);
|
|
3018
|
-
}
|
|
3019
|
-
}
|
|
3020
|
-
}
|
|
3021
|
-
// MARK: - Private Helpers
|
|
3022
|
-
findHibernatableConn(gatewayIdBuf, requestIdBuf) {
|
|
3023
|
-
return Array.from(this.#connections.values()).find((conn) => {
|
|
3024
|
-
const connStateManager = conn[CONN_STATE_MANAGER_SYMBOL];
|
|
3025
|
-
const h = connStateManager.hibernatableDataRaw;
|
|
3026
|
-
return h && arrayBuffersEqual(h.gatewayId, gatewayIdBuf) && arrayBuffersEqual(h.requestId, requestIdBuf);
|
|
3027
|
-
});
|
|
3028
|
-
}
|
|
3029
|
-
async #createConnState(params, request) {
|
|
3030
|
-
if ("createConnState" in this.#actor.config) {
|
|
3031
|
-
const ctx = new CreateConnStateContext(this.#actor, request);
|
|
3032
|
-
const dataOrPromise = this.#actor.config.createConnState(
|
|
3033
|
-
ctx,
|
|
3034
|
-
params
|
|
3035
|
-
);
|
|
3036
|
-
if (dataOrPromise instanceof Promise) {
|
|
3037
|
-
return await deadline(
|
|
3038
|
-
dataOrPromise,
|
|
3039
|
-
this.#actor.config.options.createConnStateTimeout
|
|
3040
|
-
);
|
|
3041
|
-
}
|
|
3042
|
-
return dataOrPromise;
|
|
3043
|
-
} else if ("connState" in this.#actor.config) {
|
|
3044
|
-
return structuredClone(this.#actor.config.connState);
|
|
3045
|
-
}
|
|
3046
|
-
throw new Error(
|
|
3047
|
-
"Could not create connection state from 'createConnState' or 'connState'"
|
|
3048
|
-
);
|
|
3049
|
-
}
|
|
3050
|
-
#callOnConnect(conn) {
|
|
3051
|
-
if (this.#actor.config.onConnect) {
|
|
3052
|
-
try {
|
|
3053
|
-
const ctx = new ConnectContext(this.#actor, conn);
|
|
3054
|
-
const result = this.#actor.config.onConnect(ctx, conn);
|
|
3055
|
-
if (result instanceof Promise) {
|
|
3056
|
-
deadline(
|
|
3057
|
-
result,
|
|
3058
|
-
this.#actor.config.options.onConnectTimeout
|
|
3059
|
-
).catch((error) => {
|
|
3060
|
-
this.#actor.rLog.error({
|
|
3061
|
-
msg: "error in `onConnect`, closing socket",
|
|
3062
|
-
error
|
|
3063
|
-
});
|
|
3064
|
-
conn == null ? void 0 : conn.disconnect("`onConnect` failed");
|
|
3065
|
-
});
|
|
3066
|
-
}
|
|
3067
|
-
} catch (error) {
|
|
3068
|
-
this.#actor.rLog.error({
|
|
3069
|
-
msg: "error in `onConnect`",
|
|
3070
|
-
error: stringifyError(error)
|
|
3071
|
-
});
|
|
3072
|
-
conn == null ? void 0 : conn.disconnect("`onConnect` failed");
|
|
3073
|
-
}
|
|
3074
|
-
}
|
|
3075
|
-
}
|
|
3076
|
-
};
|
|
3077
|
-
|
|
3078
|
-
// src/actor/instance/event-manager.ts
|
|
3079
|
-
import * as cbor7 from "cbor-x";
|
|
3080
|
-
var EventManager = class {
|
|
3081
|
-
#actor;
|
|
3082
|
-
#subscriptionIndex = /* @__PURE__ */ new Map();
|
|
3083
|
-
constructor(actor) {
|
|
3084
|
-
this.#actor = actor;
|
|
3085
|
-
}
|
|
3086
|
-
// MARK: - Public API
|
|
3087
|
-
/**
|
|
3088
|
-
* Adds a subscription for a connection to an event.
|
|
3089
|
-
*
|
|
3090
|
-
* @param eventName - The name of the event to subscribe to
|
|
3091
|
-
* @param connection - The connection subscribing to the event
|
|
3092
|
-
* @param fromPersist - Whether this subscription is being restored from persistence
|
|
3093
|
-
*/
|
|
3094
|
-
addSubscription(eventName, connection, fromPersist) {
|
|
3095
|
-
if (connection.subscriptions.has(eventName)) {
|
|
3096
|
-
this.#actor.rLog.debug({
|
|
3097
|
-
msg: "connection already has subscription",
|
|
3098
|
-
eventName,
|
|
3099
|
-
connId: connection.id
|
|
3100
|
-
});
|
|
3101
|
-
return;
|
|
3102
|
-
}
|
|
3103
|
-
connection.subscriptions.add(eventName);
|
|
3104
|
-
let subscribers = this.#subscriptionIndex.get(eventName);
|
|
3105
|
-
if (!subscribers) {
|
|
3106
|
-
subscribers = /* @__PURE__ */ new Set();
|
|
3107
|
-
this.#subscriptionIndex.set(eventName, subscribers);
|
|
3108
|
-
}
|
|
3109
|
-
subscribers.add(connection);
|
|
3110
|
-
if (!fromPersist) {
|
|
3111
|
-
connection[CONN_STATE_MANAGER_SYMBOL].addSubscription({
|
|
3112
|
-
eventName
|
|
3113
|
-
});
|
|
3114
|
-
this.#actor.stateManager.saveState({ immediate: true });
|
|
3115
|
-
}
|
|
3116
|
-
this.#actor.rLog.debug({
|
|
3117
|
-
msg: "subscription added",
|
|
3118
|
-
eventName,
|
|
3119
|
-
connId: connection.id,
|
|
3120
|
-
totalSubscribers: subscribers.size
|
|
3121
|
-
});
|
|
3122
|
-
}
|
|
3123
|
-
/**
|
|
3124
|
-
* Removes a subscription for a connection from an event.
|
|
3125
|
-
*
|
|
3126
|
-
* @param eventName - The name of the event to unsubscribe from
|
|
3127
|
-
* @param connection - The connection unsubscribing from the event
|
|
3128
|
-
* @param fromRemoveConn - Whether this is being called as part of connection removal
|
|
3129
|
-
*/
|
|
3130
|
-
removeSubscription(eventName, connection, fromRemoveConn) {
|
|
3131
|
-
if (!connection.subscriptions.has(eventName)) {
|
|
3132
|
-
this.#actor.rLog.warn({
|
|
3133
|
-
msg: "connection does not have subscription",
|
|
3134
|
-
eventName,
|
|
3135
|
-
connId: connection.id
|
|
3136
|
-
});
|
|
3137
|
-
return;
|
|
3138
|
-
}
|
|
3139
|
-
connection.subscriptions.delete(eventName);
|
|
3140
|
-
const subscribers = this.#subscriptionIndex.get(eventName);
|
|
3141
|
-
if (subscribers) {
|
|
3142
|
-
subscribers.delete(connection);
|
|
3143
|
-
if (subscribers.size === 0) {
|
|
3144
|
-
this.#subscriptionIndex.delete(eventName);
|
|
3145
|
-
}
|
|
3146
|
-
}
|
|
3147
|
-
if (!fromRemoveConn) {
|
|
3148
|
-
const removed = connection[CONN_STATE_MANAGER_SYMBOL].removeSubscription({ eventName });
|
|
3149
|
-
if (!removed) {
|
|
3150
|
-
this.#actor.rLog.warn({
|
|
3151
|
-
msg: "subscription does not exist in persist",
|
|
3152
|
-
eventName,
|
|
3153
|
-
connId: connection.id
|
|
3154
|
-
});
|
|
3155
|
-
}
|
|
3156
|
-
this.#actor.stateManager.saveState({ immediate: true });
|
|
3157
|
-
}
|
|
3158
|
-
this.#actor.rLog.debug({
|
|
3159
|
-
msg: "subscription removed",
|
|
3160
|
-
eventName,
|
|
3161
|
-
connId: connection.id,
|
|
3162
|
-
remainingSubscribers: (subscribers == null ? void 0 : subscribers.size) || 0
|
|
3163
|
-
});
|
|
3164
|
-
}
|
|
3165
|
-
/**
|
|
3166
|
-
* Broadcasts an event to all subscribed connections.
|
|
3167
|
-
*
|
|
3168
|
-
* @param name - The name of the event to broadcast
|
|
3169
|
-
* @param args - The arguments to send with the event
|
|
3170
|
-
*/
|
|
3171
|
-
broadcast(name, ...args) {
|
|
3172
|
-
this.#actor.assertReady();
|
|
3173
|
-
this.#actor.inspector.emitter.emit("eventFired", {
|
|
3174
|
-
type: "broadcast",
|
|
3175
|
-
eventName: name,
|
|
3176
|
-
args
|
|
3177
|
-
});
|
|
3178
|
-
const subscribers = this.#subscriptionIndex.get(name);
|
|
3179
|
-
if (!subscribers || subscribers.size === 0) {
|
|
3180
|
-
this.#actor.rLog.debug({
|
|
3181
|
-
msg: "no subscribers for event",
|
|
3182
|
-
eventName: name
|
|
3183
|
-
});
|
|
3184
|
-
return;
|
|
3185
|
-
}
|
|
3186
|
-
const eventData = { name, args };
|
|
3187
|
-
const toClientSerializer = new CachedSerializer(
|
|
3188
|
-
eventData,
|
|
3189
|
-
TO_CLIENT_VERSIONED,
|
|
3190
|
-
CURRENT_VERSION,
|
|
3191
|
-
ToClientSchema,
|
|
3192
|
-
// JSON: args is the raw value (array of arguments)
|
|
3193
|
-
(value) => ({
|
|
3194
|
-
body: {
|
|
3195
|
-
tag: "Event",
|
|
3196
|
-
val: {
|
|
3197
|
-
name: value.name,
|
|
3198
|
-
args: value.args
|
|
3199
|
-
}
|
|
3200
|
-
}
|
|
3201
|
-
}),
|
|
3202
|
-
// BARE/CBOR: args needs to be CBOR-encoded to ArrayBuffer
|
|
3203
|
-
(value) => ({
|
|
3204
|
-
body: {
|
|
3205
|
-
tag: "Event",
|
|
3206
|
-
val: {
|
|
3207
|
-
name: value.name,
|
|
3208
|
-
args: bufferToArrayBuffer(cbor7.encode(value.args))
|
|
3209
|
-
}
|
|
3210
|
-
}
|
|
3211
|
-
})
|
|
3212
|
-
);
|
|
3213
|
-
let sentCount = 0;
|
|
3214
|
-
for (const connection of subscribers) {
|
|
3215
|
-
if (connection[CONN_SPEAKS_RIVETKIT_SYMBOL]) {
|
|
3216
|
-
try {
|
|
3217
|
-
connection[CONN_SEND_MESSAGE_SYMBOL](toClientSerializer);
|
|
3218
|
-
sentCount++;
|
|
3219
|
-
} catch (error) {
|
|
3220
|
-
if (error instanceof OutgoingMessageTooLong) {
|
|
3221
|
-
throw error;
|
|
3222
|
-
}
|
|
3223
|
-
this.#actor.rLog.error({
|
|
3224
|
-
msg: "failed to send event to connection",
|
|
3225
|
-
eventName: name,
|
|
3226
|
-
connId: connection.id,
|
|
3227
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3228
|
-
});
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
}
|
|
3232
|
-
this.#actor.rLog.debug({
|
|
3233
|
-
msg: "event broadcasted",
|
|
3234
|
-
eventName: name,
|
|
3235
|
-
subscriberCount: subscribers.size,
|
|
3236
|
-
sentCount
|
|
3237
|
-
});
|
|
3238
|
-
}
|
|
3239
|
-
/**
|
|
3240
|
-
* Gets all subscribers for a specific event.
|
|
3241
|
-
*
|
|
3242
|
-
* @param eventName - The name of the event
|
|
3243
|
-
* @returns Set of connections subscribed to the event, or undefined if no subscribers
|
|
3244
|
-
*/
|
|
3245
|
-
getSubscribers(eventName) {
|
|
3246
|
-
return this.#subscriptionIndex.get(eventName);
|
|
3247
|
-
}
|
|
3248
|
-
/**
|
|
3249
|
-
* Gets all events and their subscriber counts.
|
|
3250
|
-
*
|
|
3251
|
-
* @returns Map of event names to subscriber counts
|
|
3252
|
-
*/
|
|
3253
|
-
getEventStats() {
|
|
3254
|
-
const stats = /* @__PURE__ */ new Map();
|
|
3255
|
-
for (const [eventName, subscribers] of this.#subscriptionIndex) {
|
|
3256
|
-
stats.set(eventName, subscribers.size);
|
|
3257
|
-
}
|
|
3258
|
-
return stats;
|
|
3259
|
-
}
|
|
3260
|
-
/**
|
|
3261
|
-
* Clears all subscriptions for a connection.
|
|
3262
|
-
* Used during connection cleanup.
|
|
3263
|
-
*
|
|
3264
|
-
* @param connection - The connection to clear subscriptions for
|
|
3265
|
-
*/
|
|
3266
|
-
clearConnectionSubscriptions(connection) {
|
|
3267
|
-
for (const eventName of [...connection.subscriptions.values()]) {
|
|
3268
|
-
this.removeSubscription(eventName, connection, true);
|
|
3269
|
-
}
|
|
3270
|
-
}
|
|
3271
|
-
/**
|
|
3272
|
-
* Gets the total number of unique events being subscribed to.
|
|
3273
|
-
*/
|
|
3274
|
-
get eventCount() {
|
|
3275
|
-
return this.#subscriptionIndex.size;
|
|
3276
|
-
}
|
|
3277
|
-
/**
|
|
3278
|
-
* Gets the total number of subscriptions across all events.
|
|
3279
|
-
*/
|
|
3280
|
-
get totalSubscriptionCount() {
|
|
3281
|
-
let total = 0;
|
|
3282
|
-
for (const subscribers of this.#subscriptionIndex.values()) {
|
|
3283
|
-
total += subscribers.size;
|
|
3284
|
-
}
|
|
3285
|
-
return total;
|
|
3286
|
-
}
|
|
3287
|
-
/**
|
|
3288
|
-
* Checks if an event has any subscribers.
|
|
3289
|
-
*
|
|
3290
|
-
* @param eventName - The name of the event to check
|
|
3291
|
-
* @returns True if the event has at least one subscriber
|
|
3292
|
-
*/
|
|
3293
|
-
hasSubscribers(eventName) {
|
|
3294
|
-
const subscribers = this.#subscriptionIndex.get(eventName);
|
|
3295
|
-
return subscribers !== void 0 && subscribers.size > 0;
|
|
3296
|
-
}
|
|
3297
|
-
};
|
|
3298
|
-
|
|
3299
|
-
// src/actor/instance/persisted.ts
|
|
3300
|
-
import * as cbor8 from "cbor-x";
|
|
3301
|
-
function convertActorToBarePersisted(persist) {
|
|
3302
|
-
return {
|
|
3303
|
-
input: persist.input !== void 0 ? bufferToArrayBuffer(cbor8.encode(persist.input)) : null,
|
|
3304
|
-
hasInitialized: persist.hasInitialized,
|
|
3305
|
-
state: bufferToArrayBuffer(cbor8.encode(persist.state)),
|
|
3306
|
-
scheduledEvents: persist.scheduledEvents.map((event) => ({
|
|
3307
|
-
eventId: event.eventId,
|
|
3308
|
-
timestamp: BigInt(event.timestamp),
|
|
3309
|
-
action: event.action,
|
|
3310
|
-
args: event.args ?? null
|
|
3311
|
-
}))
|
|
3312
|
-
};
|
|
3313
|
-
}
|
|
3314
|
-
function convertActorFromBarePersisted(bareData) {
|
|
3315
|
-
return {
|
|
3316
|
-
input: bareData.input ? cbor8.decode(new Uint8Array(bareData.input)) : void 0,
|
|
3317
|
-
hasInitialized: bareData.hasInitialized,
|
|
3318
|
-
state: cbor8.decode(new Uint8Array(bareData.state)),
|
|
3319
|
-
scheduledEvents: bareData.scheduledEvents.map((event) => ({
|
|
3320
|
-
eventId: event.eventId,
|
|
3321
|
-
timestamp: Number(event.timestamp),
|
|
3322
|
-
action: event.action,
|
|
3323
|
-
args: event.args ?? void 0
|
|
3324
|
-
}))
|
|
3325
|
-
};
|
|
3326
|
-
}
|
|
3327
|
-
|
|
3328
|
-
// src/actor/instance/schedule-manager.ts
|
|
3329
|
-
import * as cbor9 from "cbor-x";
|
|
3330
|
-
var ScheduleManager = class {
|
|
3331
|
-
#actor;
|
|
3332
|
-
#actorDriver;
|
|
3333
|
-
#alarmWriteQueue = new SinglePromiseQueue();
|
|
3334
|
-
#config;
|
|
3335
|
-
// ActorConfig type
|
|
3336
|
-
#persist;
|
|
3337
|
-
// Reference to PersistedActor
|
|
3338
|
-
constructor(actor, actorDriver, config) {
|
|
3339
|
-
this.#actor = actor;
|
|
3340
|
-
this.#actorDriver = actorDriver;
|
|
3341
|
-
this.#config = config;
|
|
3342
|
-
}
|
|
3343
|
-
// MARK: - Public API
|
|
3344
|
-
/**
|
|
3345
|
-
* Sets the persist object reference.
|
|
3346
|
-
* Called after StateManager initializes the persist proxy.
|
|
3347
|
-
*/
|
|
3348
|
-
setPersist(persist) {
|
|
3349
|
-
this.#persist = persist;
|
|
3350
|
-
}
|
|
3351
|
-
/**
|
|
3352
|
-
* Schedules an event to be executed at a specific timestamp.
|
|
3353
|
-
*
|
|
3354
|
-
* @param timestamp - Unix timestamp in milliseconds when the event should fire
|
|
3355
|
-
* @param action - The name of the action to execute
|
|
3356
|
-
* @param args - Arguments to pass to the action
|
|
3357
|
-
*/
|
|
3358
|
-
async scheduleEvent(timestamp, action, args) {
|
|
3359
|
-
const newEvent = {
|
|
3360
|
-
eventId: crypto.randomUUID(),
|
|
3361
|
-
timestamp,
|
|
3362
|
-
action,
|
|
3363
|
-
args: bufferToArrayBuffer(cbor9.encode(args))
|
|
3364
|
-
};
|
|
3365
|
-
await this.#scheduleEventInner(newEvent);
|
|
3366
|
-
}
|
|
3367
|
-
/**
|
|
3368
|
-
* Triggers any pending alarms that are due.
|
|
3369
|
-
* This method is idempotent and safe to call multiple times.
|
|
3370
|
-
*/
|
|
3371
|
-
async onAlarm() {
|
|
3372
|
-
var _a, _b, _c;
|
|
3373
|
-
const now = Date.now();
|
|
3374
|
-
this.#actor.log.debug({
|
|
3375
|
-
msg: "alarm triggered",
|
|
3376
|
-
now,
|
|
3377
|
-
events: ((_b = (_a = this.#persist) == null ? void 0 : _a.scheduledEvents) == null ? void 0 : _b.length) || 0
|
|
3378
|
-
});
|
|
3379
|
-
if (!((_c = this.#persist) == null ? void 0 : _c.scheduledEvents)) {
|
|
3380
|
-
this.#actor.rLog.debug({ msg: "no scheduled events" });
|
|
3381
|
-
return;
|
|
3382
|
-
}
|
|
3383
|
-
const dueIndex = this.#persist.scheduledEvents.findIndex(
|
|
3384
|
-
(x) => x.timestamp <= now
|
|
3385
|
-
);
|
|
3386
|
-
if (dueIndex === -1) {
|
|
3387
|
-
this.#actor.rLog.debug({ msg: "no events are due yet" });
|
|
3388
|
-
if (this.#persist.scheduledEvents.length > 0) {
|
|
3389
|
-
const nextTs = this.#persist.scheduledEvents[0].timestamp;
|
|
3390
|
-
this.#actor.log.debug({
|
|
3391
|
-
msg: "alarm fired early, rescheduling for next event",
|
|
3392
|
-
now,
|
|
3393
|
-
nextTs,
|
|
3394
|
-
delta: nextTs - now
|
|
3395
|
-
});
|
|
3396
|
-
await this.#queueSetAlarm(nextTs);
|
|
3397
|
-
}
|
|
3398
|
-
return;
|
|
3399
|
-
}
|
|
3400
|
-
const dueEvents = this.#persist.scheduledEvents.splice(0, dueIndex + 1);
|
|
3401
|
-
this.#actor.log.debug({
|
|
3402
|
-
msg: "running events",
|
|
3403
|
-
count: dueEvents.length
|
|
3404
|
-
});
|
|
3405
|
-
if (this.#persist.scheduledEvents.length > 0) {
|
|
3406
|
-
const nextTs = this.#persist.scheduledEvents[0].timestamp;
|
|
3407
|
-
this.#actor.log.info({
|
|
3408
|
-
msg: "setting next alarm",
|
|
3409
|
-
nextTs,
|
|
3410
|
-
remainingEvents: this.#persist.scheduledEvents.length
|
|
3411
|
-
});
|
|
3412
|
-
await this.#queueSetAlarm(nextTs);
|
|
3413
|
-
}
|
|
3414
|
-
await this.#executeDueEvents(dueEvents);
|
|
3415
|
-
}
|
|
3416
|
-
/**
|
|
3417
|
-
* Initializes alarms on actor startup.
|
|
3418
|
-
* Sets the alarm for the next scheduled event if any exist.
|
|
3419
|
-
*/
|
|
3420
|
-
async initializeAlarms() {
|
|
3421
|
-
var _a, _b;
|
|
3422
|
-
if (((_b = (_a = this.#persist) == null ? void 0 : _a.scheduledEvents) == null ? void 0 : _b.length) > 0) {
|
|
3423
|
-
await this.#queueSetAlarm(
|
|
3424
|
-
this.#persist.scheduledEvents[0].timestamp
|
|
3425
|
-
);
|
|
3426
|
-
}
|
|
3427
|
-
}
|
|
3428
|
-
/**
|
|
3429
|
-
* Waits for any pending alarm write operations to complete.
|
|
3430
|
-
*/
|
|
3431
|
-
async waitForPendingAlarmWrites() {
|
|
3432
|
-
if (this.#alarmWriteQueue.runningDrainLoop) {
|
|
3433
|
-
await this.#alarmWriteQueue.runningDrainLoop;
|
|
3434
|
-
}
|
|
3435
|
-
}
|
|
3436
|
-
/**
|
|
3437
|
-
* Gets statistics about scheduled events.
|
|
3438
|
-
*/
|
|
3439
|
-
getScheduleStats() {
|
|
3440
|
-
var _a;
|
|
3441
|
-
if (!((_a = this.#persist) == null ? void 0 : _a.scheduledEvents)) {
|
|
3442
|
-
return {
|
|
3443
|
-
totalEvents: 0,
|
|
3444
|
-
nextEventTime: null,
|
|
3445
|
-
overdueCount: 0
|
|
3446
|
-
};
|
|
3447
|
-
}
|
|
3448
|
-
const now = Date.now();
|
|
3449
|
-
const events = this.#persist.scheduledEvents;
|
|
3450
|
-
return {
|
|
3451
|
-
totalEvents: events.length,
|
|
3452
|
-
nextEventTime: events.length > 0 ? events[0].timestamp : null,
|
|
3453
|
-
overdueCount: events.filter(
|
|
3454
|
-
(e) => e.timestamp <= now
|
|
3455
|
-
).length
|
|
3456
|
-
};
|
|
3457
|
-
}
|
|
3458
|
-
/**
|
|
3459
|
-
* Cancels a scheduled event by its ID.
|
|
3460
|
-
*
|
|
3461
|
-
* @param eventId - The ID of the event to cancel
|
|
3462
|
-
* @returns True if the event was found and cancelled
|
|
3463
|
-
*/
|
|
3464
|
-
async cancelEvent(eventId) {
|
|
3465
|
-
var _a;
|
|
3466
|
-
if (!((_a = this.#persist) == null ? void 0 : _a.scheduledEvents)) {
|
|
3467
|
-
return false;
|
|
3468
|
-
}
|
|
3469
|
-
const index = this.#persist.scheduledEvents.findIndex(
|
|
3470
|
-
(e) => e.eventId === eventId
|
|
3471
|
-
);
|
|
3472
|
-
if (index === -1) {
|
|
3473
|
-
return false;
|
|
3474
|
-
}
|
|
3475
|
-
const wasFirst = index === 0;
|
|
3476
|
-
this.#persist.scheduledEvents.splice(index, 1);
|
|
3477
|
-
if (wasFirst && this.#persist.scheduledEvents.length > 0) {
|
|
3478
|
-
await this.#queueSetAlarm(
|
|
3479
|
-
this.#persist.scheduledEvents[0].timestamp
|
|
3480
|
-
);
|
|
3481
|
-
}
|
|
3482
|
-
this.#actor.log.info({
|
|
3483
|
-
msg: "cancelled scheduled event",
|
|
3484
|
-
eventId,
|
|
3485
|
-
remainingEvents: this.#persist.scheduledEvents.length
|
|
3486
|
-
});
|
|
3487
|
-
return true;
|
|
3488
|
-
}
|
|
3489
|
-
// MARK: - Private Helpers
|
|
3490
|
-
async #scheduleEventInner(newEvent) {
|
|
3491
|
-
var _a;
|
|
3492
|
-
this.#actor.log.info({
|
|
3493
|
-
msg: "scheduling event",
|
|
3494
|
-
eventId: newEvent.eventId,
|
|
3495
|
-
timestamp: newEvent.timestamp,
|
|
3496
|
-
action: newEvent.action
|
|
3497
|
-
});
|
|
3498
|
-
if (!((_a = this.#persist) == null ? void 0 : _a.scheduledEvents)) {
|
|
3499
|
-
throw new Error("Persist not initialized");
|
|
3500
|
-
}
|
|
3501
|
-
const insertIndex = this.#persist.scheduledEvents.findIndex(
|
|
3502
|
-
(x) => x.timestamp > newEvent.timestamp
|
|
3503
|
-
);
|
|
3504
|
-
if (insertIndex === -1) {
|
|
3505
|
-
this.#persist.scheduledEvents.push(newEvent);
|
|
3506
|
-
} else {
|
|
3507
|
-
this.#persist.scheduledEvents.splice(insertIndex, 0, newEvent);
|
|
3508
|
-
}
|
|
3509
|
-
if (insertIndex === 0 || this.#persist.scheduledEvents.length === 1) {
|
|
3510
|
-
this.#actor.log.info({
|
|
3511
|
-
msg: "setting alarm for new event",
|
|
3512
|
-
timestamp: newEvent.timestamp,
|
|
3513
|
-
eventCount: this.#persist.scheduledEvents.length
|
|
3514
|
-
});
|
|
3515
|
-
await this.#queueSetAlarm(newEvent.timestamp);
|
|
3516
|
-
}
|
|
3517
|
-
}
|
|
3518
|
-
async #executeDueEvents(events) {
|
|
3519
|
-
for (const event of events) {
|
|
3520
|
-
try {
|
|
3521
|
-
this.#actor.log.info({
|
|
3522
|
-
msg: "executing scheduled event",
|
|
3523
|
-
eventId: event.eventId,
|
|
3524
|
-
timestamp: event.timestamp,
|
|
3525
|
-
action: event.action
|
|
3526
|
-
});
|
|
3527
|
-
const actions = this.#config.actions ?? {};
|
|
3528
|
-
const fn = actions[event.action];
|
|
3529
|
-
if (!fn) {
|
|
3530
|
-
throw new Error(
|
|
3531
|
-
`Missing action for scheduled event: ${event.action}`
|
|
3532
|
-
);
|
|
3533
|
-
}
|
|
3534
|
-
if (typeof fn !== "function") {
|
|
3535
|
-
throw new Error(
|
|
3536
|
-
`Scheduled event action ${event.action} is not a function (got ${typeof fn})`
|
|
3537
|
-
);
|
|
3538
|
-
}
|
|
3539
|
-
const args = event.args ? cbor9.decode(new Uint8Array(event.args)) : [];
|
|
3540
|
-
const result = fn.call(
|
|
3541
|
-
void 0,
|
|
3542
|
-
this.#actor.actorContext,
|
|
3543
|
-
...args
|
|
3544
|
-
);
|
|
3545
|
-
if (result instanceof Promise) {
|
|
3546
|
-
await result;
|
|
3547
|
-
}
|
|
3548
|
-
this.#actor.log.debug({
|
|
3549
|
-
msg: "scheduled event completed",
|
|
3550
|
-
eventId: event.eventId,
|
|
3551
|
-
action: event.action
|
|
3552
|
-
});
|
|
3553
|
-
} catch (error) {
|
|
3554
|
-
this.#actor.log.error({
|
|
3555
|
-
msg: "error executing scheduled event",
|
|
3556
|
-
error: stringifyError(error),
|
|
3557
|
-
eventId: event.eventId,
|
|
3558
|
-
timestamp: event.timestamp,
|
|
3559
|
-
action: event.action
|
|
3560
|
-
});
|
|
3561
|
-
}
|
|
3562
|
-
}
|
|
3563
|
-
}
|
|
3564
|
-
async #queueSetAlarm(timestamp) {
|
|
3565
|
-
await this.#alarmWriteQueue.enqueue(async () => {
|
|
3566
|
-
await this.#actorDriver.setAlarm(this.#actor, timestamp);
|
|
3567
|
-
});
|
|
3568
|
-
}
|
|
3569
|
-
/**
|
|
3570
|
-
* Gets the next scheduled event, if any.
|
|
3571
|
-
*/
|
|
3572
|
-
getNextEvent() {
|
|
3573
|
-
var _a;
|
|
3574
|
-
if (!((_a = this.#persist) == null ? void 0 : _a.scheduledEvents) || this.#persist.scheduledEvents.length === 0) {
|
|
3575
|
-
return null;
|
|
3576
|
-
}
|
|
3577
|
-
return this.#persist.scheduledEvents[0];
|
|
3578
|
-
}
|
|
3579
|
-
/**
|
|
3580
|
-
* Gets all scheduled events.
|
|
3581
|
-
*/
|
|
3582
|
-
getAllEvents() {
|
|
3583
|
-
var _a;
|
|
3584
|
-
return ((_a = this.#persist) == null ? void 0 : _a.scheduledEvents) || [];
|
|
3585
|
-
}
|
|
3586
|
-
/**
|
|
3587
|
-
* Clears all scheduled events.
|
|
3588
|
-
* Use with caution - this removes all pending scheduled events.
|
|
3589
|
-
*/
|
|
3590
|
-
clearAllEvents() {
|
|
3591
|
-
var _a;
|
|
3592
|
-
if ((_a = this.#persist) == null ? void 0 : _a.scheduledEvents) {
|
|
3593
|
-
this.#persist.scheduledEvents = [];
|
|
3594
|
-
this.#actor.log.warn({ msg: "cleared all scheduled events" });
|
|
3595
|
-
}
|
|
3596
|
-
}
|
|
3597
|
-
};
|
|
3598
|
-
|
|
3599
|
-
// src/actor/instance/state-manager.ts
|
|
3600
|
-
import { idToStr } from "@rivetkit/engine-runner";
|
|
3601
|
-
import onChange from "@rivetkit/on-change";
|
|
3602
|
-
var StateManager = class {
|
|
3603
|
-
#actor;
|
|
3604
|
-
#actorDriver;
|
|
3605
|
-
// State tracking
|
|
3606
|
-
#persist;
|
|
3607
|
-
#persistRaw;
|
|
3608
|
-
#persistChanged = false;
|
|
3609
|
-
#isInOnStateChange = false;
|
|
3610
|
-
// Save management
|
|
3611
|
-
#persistWriteQueue = new SinglePromiseQueue();
|
|
3612
|
-
#lastSaveTime = 0;
|
|
3613
|
-
#pendingSaveTimeout;
|
|
3614
|
-
#pendingSaveScheduledTimestamp;
|
|
3615
|
-
#onPersistSavedPromise;
|
|
3616
|
-
// Configuration
|
|
3617
|
-
#config;
|
|
3618
|
-
// ActorConfig type
|
|
3619
|
-
#stateSaveInterval;
|
|
3620
|
-
constructor(actor, actorDriver, config) {
|
|
3621
|
-
this.#actor = actor;
|
|
3622
|
-
this.#actorDriver = actorDriver;
|
|
3623
|
-
this.#config = config;
|
|
3624
|
-
this.#stateSaveInterval = config.options.stateSaveInterval || 100;
|
|
3625
|
-
}
|
|
3626
|
-
// MARK: - Public API
|
|
3627
|
-
get persist() {
|
|
3628
|
-
return this.#persist;
|
|
3629
|
-
}
|
|
3630
|
-
get persistRaw() {
|
|
3631
|
-
return this.#persistRaw;
|
|
3632
|
-
}
|
|
3633
|
-
get persistChanged() {
|
|
3634
|
-
return this.#persistChanged;
|
|
3635
|
-
}
|
|
3636
|
-
get state() {
|
|
3637
|
-
this.#validateStateEnabled();
|
|
3638
|
-
return this.#persist.state;
|
|
3639
|
-
}
|
|
3640
|
-
set state(value) {
|
|
3641
|
-
this.#validateStateEnabled();
|
|
3642
|
-
this.#persist.state = value;
|
|
3643
|
-
}
|
|
3644
|
-
get stateEnabled() {
|
|
3645
|
-
return "createState" in this.#config || "state" in this.#config;
|
|
3646
|
-
}
|
|
3647
|
-
// MARK: - Initialization
|
|
3648
|
-
/**
|
|
3649
|
-
* Initializes state from persisted data or creates new state.
|
|
3650
|
-
*/
|
|
3651
|
-
async initializeState(persistData) {
|
|
3652
|
-
if (!persistData.hasInitialized) {
|
|
3653
|
-
let stateData;
|
|
3654
|
-
if (this.stateEnabled) {
|
|
3655
|
-
this.#actor.rLog.info({ msg: "actor state initializing" });
|
|
3656
|
-
if ("createState" in this.#config) {
|
|
3657
|
-
stateData = await this.#config.createState(
|
|
3658
|
-
this.#actor.actorContext,
|
|
3659
|
-
persistData.input
|
|
3660
|
-
);
|
|
3661
|
-
} else if ("state" in this.#config) {
|
|
3662
|
-
stateData = structuredClone(this.#config.state);
|
|
3663
|
-
} else {
|
|
3664
|
-
throw new Error(
|
|
3665
|
-
"Both 'createState' or 'state' were not defined"
|
|
3666
|
-
);
|
|
3667
|
-
}
|
|
3668
|
-
} else {
|
|
3669
|
-
this.#actor.rLog.debug({ msg: "state not enabled" });
|
|
3670
|
-
}
|
|
3671
|
-
persistData.state = stateData;
|
|
3672
|
-
persistData.hasInitialized = true;
|
|
3673
|
-
const bareData = convertActorToBarePersisted(persistData);
|
|
3674
|
-
await this.#actorDriver.kvBatchPut(this.#actor.id, [
|
|
3675
|
-
[
|
|
3676
|
-
KEYS.PERSIST_DATA,
|
|
3677
|
-
ACTOR_VERSIONED.serializeWithEmbeddedVersion(
|
|
3678
|
-
bareData,
|
|
3679
|
-
CURRENT_VERSION2
|
|
3680
|
-
)
|
|
3681
|
-
]
|
|
3682
|
-
]);
|
|
3683
|
-
}
|
|
3684
|
-
this.initPersistProxy(persistData);
|
|
3685
|
-
}
|
|
3686
|
-
/**
|
|
3687
|
-
* Creates proxy for persist object that handles automatic state change detection.
|
|
3688
|
-
*/
|
|
3689
|
-
initPersistProxy(target) {
|
|
3690
|
-
this.#persistRaw = target;
|
|
3691
|
-
if (target === null || typeof target !== "object") {
|
|
3692
|
-
let invalidPath = "";
|
|
3693
|
-
if (!isCborSerializable(
|
|
3694
|
-
target,
|
|
3695
|
-
(path) => {
|
|
3696
|
-
invalidPath = path;
|
|
3697
|
-
},
|
|
3698
|
-
""
|
|
3699
|
-
)) {
|
|
3700
|
-
throw new InvalidStateType({ path: invalidPath });
|
|
3701
|
-
}
|
|
3702
|
-
return target;
|
|
3703
|
-
}
|
|
3704
|
-
if (this.#persist) {
|
|
3705
|
-
onChange.unsubscribe(this.#persist);
|
|
3706
|
-
}
|
|
3707
|
-
this.#persist = onChange(
|
|
3708
|
-
target,
|
|
3709
|
-
(path, value, _previousValue, _applyData) => {
|
|
3710
|
-
this.#handleStateChange(path, value);
|
|
3711
|
-
},
|
|
3712
|
-
{ ignoreDetached: true }
|
|
3713
|
-
);
|
|
3714
|
-
}
|
|
3715
|
-
// MARK: - State Persistence
|
|
3716
|
-
/**
|
|
3717
|
-
* Forces the state to get saved.
|
|
3718
|
-
*/
|
|
3719
|
-
async saveState(opts) {
|
|
3720
|
-
var _a;
|
|
3721
|
-
this.#actor.assertReady(opts.allowStoppingState);
|
|
3722
|
-
if (this.#persistChanged) {
|
|
3723
|
-
if (opts.immediate) {
|
|
3724
|
-
await this.#savePersistInner();
|
|
3725
|
-
} else {
|
|
3726
|
-
if (!this.#onPersistSavedPromise) {
|
|
3727
|
-
this.#onPersistSavedPromise = promiseWithResolvers();
|
|
3728
|
-
}
|
|
3729
|
-
this.savePersistThrottled(opts.maxWait);
|
|
3730
|
-
await ((_a = this.#onPersistSavedPromise) == null ? void 0 : _a.promise);
|
|
3731
|
-
}
|
|
3732
|
-
}
|
|
3733
|
-
}
|
|
3734
|
-
/**
|
|
3735
|
-
* Throttled save state method. Used to write to KV at a reasonable cadence.
|
|
3736
|
-
*
|
|
3737
|
-
* Passing a maxWait will override the stateSaveInterval with the min
|
|
3738
|
-
* between that and the maxWait.
|
|
3739
|
-
*/
|
|
3740
|
-
savePersistThrottled(maxWait) {
|
|
3741
|
-
const now = Date.now();
|
|
3742
|
-
const timeSinceLastSave = now - this.#lastSaveTime;
|
|
3743
|
-
let saveDelay = Math.max(
|
|
3744
|
-
0,
|
|
3745
|
-
this.#stateSaveInterval - timeSinceLastSave
|
|
3746
|
-
);
|
|
3747
|
-
if (maxWait !== void 0) {
|
|
3748
|
-
saveDelay = Math.min(saveDelay, maxWait);
|
|
3749
|
-
}
|
|
3750
|
-
if (this.#pendingSaveTimeout !== void 0 && this.#pendingSaveScheduledTimestamp !== void 0) {
|
|
3751
|
-
const newScheduledTimestamp = now + saveDelay;
|
|
3752
|
-
if (newScheduledTimestamp < this.#pendingSaveScheduledTimestamp) {
|
|
3753
|
-
clearTimeout(this.#pendingSaveTimeout);
|
|
3754
|
-
this.#pendingSaveTimeout = void 0;
|
|
3755
|
-
this.#pendingSaveScheduledTimestamp = void 0;
|
|
3756
|
-
} else {
|
|
3757
|
-
return;
|
|
3758
|
-
}
|
|
3759
|
-
}
|
|
3760
|
-
if (saveDelay > 0) {
|
|
3761
|
-
this.#pendingSaveScheduledTimestamp = now + saveDelay;
|
|
3762
|
-
this.#pendingSaveTimeout = setTimeout(() => {
|
|
3763
|
-
this.#pendingSaveTimeout = void 0;
|
|
3764
|
-
this.#pendingSaveScheduledTimestamp = void 0;
|
|
3765
|
-
this.#savePersistInner().catch((error) => {
|
|
3766
|
-
this.#actor.rLog.error({
|
|
3767
|
-
msg: "error saving persist data in scheduled save",
|
|
3768
|
-
error: stringifyError(error)
|
|
3769
|
-
});
|
|
3770
|
-
});
|
|
3771
|
-
}, saveDelay);
|
|
3772
|
-
} else {
|
|
3773
|
-
this.#savePersistInner().catch((error) => {
|
|
3774
|
-
this.#actor.rLog.error({
|
|
3775
|
-
msg: "error saving persist data immediately",
|
|
3776
|
-
error: stringifyError(error)
|
|
3777
|
-
});
|
|
3778
|
-
});
|
|
3779
|
-
}
|
|
3780
|
-
}
|
|
3781
|
-
/**
|
|
3782
|
-
* Clears any pending save timeout.
|
|
3783
|
-
*/
|
|
3784
|
-
clearPendingSaveTimeout() {
|
|
3785
|
-
if (this.#pendingSaveTimeout) {
|
|
3786
|
-
clearTimeout(this.#pendingSaveTimeout);
|
|
3787
|
-
this.#pendingSaveTimeout = void 0;
|
|
3788
|
-
this.#pendingSaveScheduledTimestamp = void 0;
|
|
3789
|
-
}
|
|
3790
|
-
}
|
|
3791
|
-
/**
|
|
3792
|
-
* Waits for any pending write operations to complete.
|
|
3793
|
-
*/
|
|
3794
|
-
async waitForPendingWrites() {
|
|
3795
|
-
if (this.#persistWriteQueue.runningDrainLoop) {
|
|
3796
|
-
await this.#persistWriteQueue.runningDrainLoop;
|
|
3797
|
-
}
|
|
3798
|
-
}
|
|
3799
|
-
// MARK: - Private Helpers
|
|
3800
|
-
#validateStateEnabled() {
|
|
3801
|
-
if (!this.stateEnabled) {
|
|
3802
|
-
throw new StateNotEnabled();
|
|
3803
|
-
}
|
|
3804
|
-
}
|
|
3805
|
-
#handleStateChange(path, value) {
|
|
3806
|
-
const actorStatePath = isStatePath(path);
|
|
3807
|
-
const connStatePath = isConnStatePath(path);
|
|
3808
|
-
if (actorStatePath || connStatePath) {
|
|
3809
|
-
let invalidPath = "";
|
|
3810
|
-
if (!isCborSerializable(
|
|
3811
|
-
value,
|
|
3812
|
-
(invalidPathPart) => {
|
|
3813
|
-
invalidPath = invalidPathPart;
|
|
3814
|
-
},
|
|
3815
|
-
""
|
|
3816
|
-
)) {
|
|
3817
|
-
throw new InvalidStateType({
|
|
3818
|
-
path: path + (invalidPath ? `.${invalidPath}` : "")
|
|
3819
|
-
});
|
|
3820
|
-
}
|
|
3821
|
-
}
|
|
3822
|
-
this.#actor.rLog.debug({
|
|
3823
|
-
msg: "onChange triggered, setting persistChanged=true",
|
|
3824
|
-
path
|
|
3825
|
-
});
|
|
3826
|
-
this.#persistChanged = true;
|
|
3827
|
-
if (actorStatePath) {
|
|
3828
|
-
this.#actor.inspector.emitter.emit(
|
|
3829
|
-
"stateUpdated",
|
|
3830
|
-
this.#persist.state
|
|
3831
|
-
);
|
|
3832
|
-
}
|
|
3833
|
-
if (actorStatePath && this.#config.onStateChange && this.#actor.isReady() && !this.#isInOnStateChange) {
|
|
3834
|
-
try {
|
|
3835
|
-
this.#isInOnStateChange = true;
|
|
3836
|
-
this.#config.onStateChange(
|
|
3837
|
-
this.#actor.actorContext,
|
|
3838
|
-
this.#persistRaw.state
|
|
3839
|
-
);
|
|
3840
|
-
} catch (error) {
|
|
3841
|
-
this.#actor.rLog.error({
|
|
3842
|
-
msg: "error in `_onStateChange`",
|
|
3843
|
-
error: stringifyError(error)
|
|
3844
|
-
});
|
|
3845
|
-
} finally {
|
|
3846
|
-
this.#isInOnStateChange = false;
|
|
3847
|
-
}
|
|
3848
|
-
}
|
|
3849
|
-
}
|
|
3850
|
-
async #savePersistInner() {
|
|
3851
|
-
var _a, _b;
|
|
3852
|
-
this.#actor.rLog.info({
|
|
3853
|
-
msg: "savePersistInner called",
|
|
3854
|
-
persistChanged: this.#persistChanged,
|
|
3855
|
-
connsWithPersistChangedSize: this.#actor.connectionManager.connsWithPersistChanged.size,
|
|
3856
|
-
connsWithPersistChangedIds: Array.from(
|
|
3857
|
-
this.#actor.connectionManager.connsWithPersistChanged
|
|
3858
|
-
)
|
|
3859
|
-
});
|
|
3860
|
-
try {
|
|
3861
|
-
this.#lastSaveTime = Date.now();
|
|
3862
|
-
const hasChanges = this.#persistChanged || this.#actor.connectionManager.connsWithPersistChanged.size > 0;
|
|
3863
|
-
if (hasChanges) {
|
|
3864
|
-
await this.#persistWriteQueue.enqueue(async () => {
|
|
3865
|
-
this.#actor.rLog.debug({
|
|
3866
|
-
msg: "saving persist",
|
|
3867
|
-
actorChanged: this.#persistChanged,
|
|
3868
|
-
connectionsChanged: this.#actor.connectionManager.connsWithPersistChanged.size
|
|
3869
|
-
});
|
|
3870
|
-
const entries = [];
|
|
3871
|
-
if (this.#persistChanged) {
|
|
3872
|
-
this.#persistChanged = false;
|
|
3873
|
-
const bareData = convertActorToBarePersisted(
|
|
3874
|
-
this.#persistRaw
|
|
3875
|
-
);
|
|
3876
|
-
entries.push([
|
|
3877
|
-
KEYS.PERSIST_DATA,
|
|
3878
|
-
ACTOR_VERSIONED.serializeWithEmbeddedVersion(
|
|
3879
|
-
bareData,
|
|
3880
|
-
CURRENT_VERSION2
|
|
3881
|
-
)
|
|
3882
|
-
]);
|
|
3883
|
-
}
|
|
3884
|
-
const connections = [];
|
|
3885
|
-
for (const connId of this.#actor.connectionManager.connsWithPersistChanged) {
|
|
3886
|
-
const conn = this.#actor.conns.get(connId);
|
|
3887
|
-
if (!conn) {
|
|
3888
|
-
this.#actor.rLog.warn({
|
|
3889
|
-
msg: "connection not found in conns map",
|
|
3890
|
-
connId
|
|
3891
|
-
});
|
|
3892
|
-
continue;
|
|
3893
|
-
}
|
|
3894
|
-
const connStateManager = conn[CONN_STATE_MANAGER_SYMBOL];
|
|
3895
|
-
const hibernatableDataRaw = connStateManager.hibernatableDataRaw;
|
|
3896
|
-
if (!hibernatableDataRaw) {
|
|
3897
|
-
this.#actor.log.warn({
|
|
3898
|
-
msg: "missing raw hibernatable data for conn in getChangedConnectionsData",
|
|
3899
|
-
connId: conn.id
|
|
3900
|
-
});
|
|
3901
|
-
continue;
|
|
3902
|
-
}
|
|
3903
|
-
this.#actor.rLog.info({
|
|
3904
|
-
msg: "persisting connection",
|
|
3905
|
-
connId,
|
|
3906
|
-
gatewayId: idToStr(hibernatableDataRaw.requestId),
|
|
3907
|
-
requestId: idToStr(hibernatableDataRaw.requestId),
|
|
3908
|
-
serverMessageIndex: hibernatableDataRaw.serverMessageIndex,
|
|
3909
|
-
clientMessageIndex: hibernatableDataRaw.clientMessageIndex,
|
|
3910
|
-
hasState: hibernatableDataRaw.state !== void 0
|
|
3911
|
-
});
|
|
3912
|
-
const bareData = convertConnToBarePersistedConn(
|
|
3913
|
-
hibernatableDataRaw
|
|
3914
|
-
);
|
|
3915
|
-
const connData = CONN_VERSIONED.serializeWithEmbeddedVersion(
|
|
3916
|
-
bareData,
|
|
3917
|
-
CURRENT_VERSION2
|
|
3918
|
-
);
|
|
3919
|
-
entries.push([makeConnKey(connId), connData]);
|
|
3920
|
-
connections.push(conn);
|
|
3921
|
-
}
|
|
3922
|
-
this.#actor.rLog.info({
|
|
3923
|
-
msg: "prepared entries for kvBatchPut",
|
|
3924
|
-
totalEntries: entries.length,
|
|
3925
|
-
connectionEntries: connections.length,
|
|
3926
|
-
connectionIds: connections.map((c) => c.id)
|
|
3927
|
-
});
|
|
3928
|
-
if (this.#actorDriver.onBeforePersistConn) {
|
|
3929
|
-
for (const conn of connections) {
|
|
3930
|
-
this.#actorDriver.onBeforePersistConn(conn);
|
|
3931
|
-
}
|
|
3932
|
-
}
|
|
3933
|
-
this.#actor.connectionManager.clearConnWithPersistChanged();
|
|
3934
|
-
this.#actor.rLog.info({
|
|
3935
|
-
msg: "calling kvBatchPut",
|
|
3936
|
-
actorId: this.#actor.id,
|
|
3937
|
-
entriesCount: entries.length
|
|
3938
|
-
});
|
|
3939
|
-
await this.#actorDriver.kvBatchPut(this.#actor.id, entries);
|
|
3940
|
-
this.#actor.rLog.info({
|
|
3941
|
-
msg: "kvBatchPut completed successfully"
|
|
3942
|
-
});
|
|
3943
|
-
if (this.#actorDriver.onAfterPersistConn) {
|
|
3944
|
-
for (const conn of connections) {
|
|
3945
|
-
this.#actorDriver.onAfterPersistConn(conn);
|
|
3946
|
-
}
|
|
3947
|
-
}
|
|
3948
|
-
this.#actor.rLog.debug({ msg: "persist saved" });
|
|
3949
|
-
});
|
|
3950
|
-
} else {
|
|
3951
|
-
this.#actor.rLog.info({
|
|
3952
|
-
msg: "savePersistInner skipped - no changes"
|
|
3953
|
-
});
|
|
3954
|
-
}
|
|
3955
|
-
(_a = this.#onPersistSavedPromise) == null ? void 0 : _a.resolve();
|
|
3956
|
-
} catch (error) {
|
|
3957
|
-
this.#actor.rLog.error({
|
|
3958
|
-
msg: "error saving persist",
|
|
3959
|
-
error: stringifyError(error)
|
|
3960
|
-
});
|
|
3961
|
-
(_b = this.#onPersistSavedPromise) == null ? void 0 : _b.reject(error);
|
|
3962
|
-
throw error;
|
|
3963
|
-
}
|
|
3964
|
-
}
|
|
3965
|
-
};
|
|
3966
|
-
|
|
3967
|
-
// src/actor/instance/mod.ts
|
|
3968
|
-
var CanSleep = /* @__PURE__ */ ((CanSleep2) => {
|
|
3969
|
-
CanSleep2[CanSleep2["Yes"] = 0] = "Yes";
|
|
3970
|
-
CanSleep2[CanSleep2["NotReady"] = 1] = "NotReady";
|
|
3971
|
-
CanSleep2[CanSleep2["NotStarted"] = 2] = "NotStarted";
|
|
3972
|
-
CanSleep2[CanSleep2["ActiveConns"] = 3] = "ActiveConns";
|
|
3973
|
-
CanSleep2[CanSleep2["ActiveHonoHttpRequests"] = 4] = "ActiveHonoHttpRequests";
|
|
3974
|
-
return CanSleep2;
|
|
3975
|
-
})(CanSleep || {});
|
|
3976
|
-
var ActorInstance = class {
|
|
3977
|
-
// MARK: - Core Properties
|
|
3978
|
-
actorContext;
|
|
3979
|
-
#config;
|
|
3980
|
-
driver;
|
|
3981
|
-
#inlineClient;
|
|
3982
|
-
#actorId;
|
|
3983
|
-
#name;
|
|
3984
|
-
#key;
|
|
3985
|
-
#region;
|
|
3986
|
-
// MARK: - Managers
|
|
3987
|
-
connectionManager;
|
|
3988
|
-
stateManager;
|
|
3989
|
-
eventManager;
|
|
3990
|
-
#scheduleManager;
|
|
3991
|
-
// MARK: - Logging
|
|
3992
|
-
#log;
|
|
3993
|
-
#rLog;
|
|
3994
|
-
// MARK: - Lifecycle State
|
|
3995
|
-
/**
|
|
3996
|
-
* If the core actor initiation has set up.
|
|
3997
|
-
*
|
|
3998
|
-
* Almost all actions on this actor will throw an error if false.
|
|
3999
|
-
**/
|
|
4000
|
-
#ready = false;
|
|
4001
|
-
/**
|
|
4002
|
-
* If the actor has fully started.
|
|
4003
|
-
*
|
|
4004
|
-
* The only purpose of this is to prevent sleeping until started.
|
|
4005
|
-
*/
|
|
4006
|
-
#started = false;
|
|
4007
|
-
#sleepCalled = false;
|
|
4008
|
-
#destroyCalled = false;
|
|
4009
|
-
#stopCalled = false;
|
|
4010
|
-
#sleepTimeout;
|
|
4011
|
-
#abortController = new AbortController();
|
|
4012
|
-
// MARK: - Variables & Database
|
|
4013
|
-
#vars;
|
|
4014
|
-
#db;
|
|
4015
|
-
// MARK: - Background Tasks
|
|
4016
|
-
#backgroundPromises = [];
|
|
4017
|
-
// MARK: - HTTP/WebSocket Tracking
|
|
4018
|
-
#activeHonoHttpRequests = 0;
|
|
4019
|
-
// MARK: - Deprecated (kept for compatibility)
|
|
4020
|
-
#schedule;
|
|
4021
|
-
// MARK: - Inspector
|
|
4022
|
-
#inspectorToken;
|
|
4023
|
-
#inspector = new ActorInspector(this);
|
|
4024
|
-
// MARK: - Constructor
|
|
4025
|
-
constructor(config) {
|
|
4026
|
-
this.#config = config;
|
|
4027
|
-
this.actorContext = new ActorContext(this);
|
|
4028
|
-
}
|
|
4029
|
-
// MARK: - Public Getters
|
|
4030
|
-
get log() {
|
|
4031
|
-
invariant7(this.#log, "log not configured");
|
|
4032
|
-
return this.#log;
|
|
4033
|
-
}
|
|
4034
|
-
get rLog() {
|
|
4035
|
-
invariant7(this.#rLog, "log not configured");
|
|
4036
|
-
return this.#rLog;
|
|
4037
|
-
}
|
|
4038
|
-
get isStopping() {
|
|
4039
|
-
return this.#stopCalled;
|
|
4040
|
-
}
|
|
4041
|
-
get id() {
|
|
4042
|
-
return this.#actorId;
|
|
4043
|
-
}
|
|
4044
|
-
get name() {
|
|
4045
|
-
return this.#name;
|
|
4046
|
-
}
|
|
4047
|
-
get key() {
|
|
4048
|
-
return this.#key;
|
|
4049
|
-
}
|
|
4050
|
-
get region() {
|
|
4051
|
-
return this.#region;
|
|
4052
|
-
}
|
|
4053
|
-
get inlineClient() {
|
|
4054
|
-
return this.#inlineClient;
|
|
4055
|
-
}
|
|
4056
|
-
get inspector() {
|
|
4057
|
-
return this.#inspector;
|
|
4058
|
-
}
|
|
4059
|
-
get inspectorToken() {
|
|
4060
|
-
return this.#inspectorToken;
|
|
4061
|
-
}
|
|
4062
|
-
get conns() {
|
|
4063
|
-
return this.connectionManager.connections;
|
|
4064
|
-
}
|
|
4065
|
-
get schedule() {
|
|
4066
|
-
return this.#schedule;
|
|
4067
|
-
}
|
|
4068
|
-
get abortSignal() {
|
|
4069
|
-
return this.#abortController.signal;
|
|
4070
|
-
}
|
|
4071
|
-
get actions() {
|
|
4072
|
-
return Object.keys(this.#config.actions ?? {});
|
|
4073
|
-
}
|
|
4074
|
-
get config() {
|
|
4075
|
-
return this.#config;
|
|
4076
|
-
}
|
|
4077
|
-
// MARK: - State Access
|
|
4078
|
-
get persist() {
|
|
4079
|
-
return this.stateManager.persist;
|
|
4080
|
-
}
|
|
4081
|
-
get state() {
|
|
4082
|
-
return this.stateManager.state;
|
|
4083
|
-
}
|
|
4084
|
-
set state(value) {
|
|
4085
|
-
this.stateManager.state = value;
|
|
4086
|
-
}
|
|
4087
|
-
get stateEnabled() {
|
|
4088
|
-
return this.stateManager.stateEnabled;
|
|
4089
|
-
}
|
|
4090
|
-
get connStateEnabled() {
|
|
4091
|
-
return "createConnState" in this.#config || "connState" in this.#config;
|
|
4092
|
-
}
|
|
4093
|
-
// MARK: - Variables & Database
|
|
4094
|
-
get vars() {
|
|
4095
|
-
this.#validateVarsEnabled();
|
|
4096
|
-
invariant7(this.#vars !== void 0, "vars not enabled");
|
|
4097
|
-
return this.#vars;
|
|
4098
|
-
}
|
|
4099
|
-
get db() {
|
|
4100
|
-
if (!this.#db) {
|
|
4101
|
-
throw new DatabaseNotEnabled();
|
|
4102
|
-
}
|
|
4103
|
-
return this.#db;
|
|
4104
|
-
}
|
|
4105
|
-
// MARK: - Initialization
|
|
4106
|
-
async start(actorDriver, inlineClient, actorId, name, key, region) {
|
|
4107
|
-
var _a, _b;
|
|
4108
|
-
this.driver = actorDriver;
|
|
4109
|
-
this.#inlineClient = inlineClient;
|
|
4110
|
-
this.#actorId = actorId;
|
|
4111
|
-
this.#name = name;
|
|
4112
|
-
this.#key = key;
|
|
4113
|
-
this.#region = region;
|
|
4114
|
-
this.#initializeLogging();
|
|
4115
|
-
this.connectionManager = new ConnectionManager(this);
|
|
4116
|
-
this.stateManager = new StateManager(this, actorDriver, this.#config);
|
|
4117
|
-
this.eventManager = new EventManager(this);
|
|
4118
|
-
this.#scheduleManager = new ScheduleManager(
|
|
4119
|
-
this,
|
|
4120
|
-
actorDriver,
|
|
4121
|
-
this.#config
|
|
4122
|
-
);
|
|
4123
|
-
this.#schedule = new Schedule(this);
|
|
4124
|
-
await this.#loadState();
|
|
4125
|
-
await this.#initializeInspectorToken();
|
|
4126
|
-
if (this.#varsEnabled) {
|
|
4127
|
-
await this.#initializeVars();
|
|
4128
|
-
}
|
|
4129
|
-
await this.#callOnStart();
|
|
4130
|
-
await this.#setupDatabase();
|
|
4131
|
-
await this.#scheduleManager.initializeAlarms();
|
|
4132
|
-
this.#ready = true;
|
|
4133
|
-
await ((_b = (_a = this.driver).onBeforeActorStart) == null ? void 0 : _b.call(_a, this));
|
|
4134
|
-
this.#started = true;
|
|
4135
|
-
this.#rLog.info({ msg: "actor started" });
|
|
4136
|
-
this.resetSleepTimer();
|
|
4137
|
-
await this.onAlarm();
|
|
4138
|
-
}
|
|
4139
|
-
// MARK: - Ready Check
|
|
4140
|
-
isReady() {
|
|
4141
|
-
return this.#ready;
|
|
4142
|
-
}
|
|
4143
|
-
assertReady(allowStoppingState = false) {
|
|
4144
|
-
if (!this.#ready) throw new InternalError("Actor not ready");
|
|
4145
|
-
if (!allowStoppingState && this.#stopCalled)
|
|
4146
|
-
throw new InternalError("Actor is stopping");
|
|
4147
|
-
}
|
|
4148
|
-
// MARK: - Stop
|
|
4149
|
-
async onStop(mode) {
|
|
4150
|
-
if (this.#stopCalled) {
|
|
4151
|
-
this.#rLog.warn({ msg: "already stopping actor" });
|
|
4152
|
-
return;
|
|
4153
|
-
}
|
|
4154
|
-
this.#stopCalled = true;
|
|
4155
|
-
this.#rLog.info({
|
|
4156
|
-
msg: "setting stopCalled=true",
|
|
4157
|
-
mode
|
|
4158
|
-
});
|
|
4159
|
-
if (this.#sleepTimeout) {
|
|
4160
|
-
clearTimeout(this.#sleepTimeout);
|
|
4161
|
-
this.#sleepTimeout = void 0;
|
|
4162
|
-
}
|
|
4163
|
-
try {
|
|
4164
|
-
this.#abortController.abort();
|
|
4165
|
-
} catch {
|
|
4166
|
-
}
|
|
4167
|
-
if (mode === "sleep") {
|
|
4168
|
-
await this.#callOnSleep();
|
|
4169
|
-
} else if (mode === "destroy") {
|
|
4170
|
-
await this.#callOnDestroy();
|
|
4171
|
-
} else {
|
|
4172
|
-
assertUnreachable2(mode);
|
|
4173
|
-
}
|
|
4174
|
-
await this.#disconnectConnections();
|
|
4175
|
-
await this.#waitBackgroundPromises(
|
|
4176
|
-
this.#config.options.waitUntilTimeout
|
|
4177
|
-
);
|
|
4178
|
-
this.#rLog.info({ msg: "clearing pending save timeouts" });
|
|
4179
|
-
this.stateManager.clearPendingSaveTimeout();
|
|
4180
|
-
this.#rLog.info({ msg: "saving state immediately" });
|
|
4181
|
-
await this.stateManager.saveState({
|
|
4182
|
-
immediate: true,
|
|
4183
|
-
allowStoppingState: true
|
|
4184
|
-
});
|
|
4185
|
-
await this.stateManager.waitForPendingWrites();
|
|
4186
|
-
await this.#scheduleManager.waitForPendingAlarmWrites();
|
|
4187
|
-
}
|
|
4188
|
-
// MARK: - Sleep
|
|
4189
|
-
startSleep() {
|
|
4190
|
-
var _a;
|
|
4191
|
-
if (this.#stopCalled || this.#destroyCalled) {
|
|
4192
|
-
this.#rLog.debug({
|
|
4193
|
-
msg: "cannot call startSleep if actor already stopping"
|
|
4194
|
-
});
|
|
4195
|
-
return;
|
|
4196
|
-
}
|
|
4197
|
-
if (this.#sleepCalled) {
|
|
4198
|
-
this.#rLog.warn({
|
|
4199
|
-
msg: "cannot call startSleep twice, actor already sleeping"
|
|
4200
|
-
});
|
|
4201
|
-
return;
|
|
4202
|
-
}
|
|
4203
|
-
this.#sleepCalled = true;
|
|
4204
|
-
const sleep = (_a = this.driver.startSleep) == null ? void 0 : _a.bind(this.driver, this.#actorId);
|
|
4205
|
-
invariant7(this.#sleepingSupported, "sleeping not supported");
|
|
4206
|
-
invariant7(sleep, "no sleep on driver");
|
|
4207
|
-
this.#rLog.info({ msg: "actor sleeping" });
|
|
4208
|
-
setImmediate(() => {
|
|
4209
|
-
sleep();
|
|
4210
|
-
});
|
|
4211
|
-
}
|
|
4212
|
-
// MARK: - Destroy
|
|
4213
|
-
startDestroy() {
|
|
4214
|
-
if (this.#stopCalled || this.#sleepCalled) {
|
|
4215
|
-
this.#rLog.debug({
|
|
4216
|
-
msg: "cannot call startDestroy if actor already stopping or sleeping"
|
|
4217
|
-
});
|
|
4218
|
-
return;
|
|
4219
|
-
}
|
|
4220
|
-
if (this.#destroyCalled) {
|
|
4221
|
-
this.#rLog.warn({
|
|
4222
|
-
msg: "cannot call startDestroy twice, actor already destroying"
|
|
4223
|
-
});
|
|
4224
|
-
return;
|
|
4225
|
-
}
|
|
4226
|
-
this.#destroyCalled = true;
|
|
4227
|
-
const destroy = this.driver.startDestroy.bind(
|
|
4228
|
-
this.driver,
|
|
4229
|
-
this.#actorId
|
|
4230
|
-
);
|
|
4231
|
-
this.#rLog.info({ msg: "actor destroying" });
|
|
4232
|
-
setImmediate(() => {
|
|
4233
|
-
destroy();
|
|
4234
|
-
});
|
|
4235
|
-
}
|
|
4236
|
-
// MARK: - HTTP Request Tracking
|
|
4237
|
-
beginHonoHttpRequest() {
|
|
4238
|
-
this.#activeHonoHttpRequests++;
|
|
4239
|
-
this.resetSleepTimer();
|
|
4240
|
-
}
|
|
4241
|
-
endHonoHttpRequest() {
|
|
4242
|
-
this.#activeHonoHttpRequests--;
|
|
4243
|
-
if (this.#activeHonoHttpRequests < 0) {
|
|
4244
|
-
this.#activeHonoHttpRequests = 0;
|
|
4245
|
-
this.#rLog.warn({
|
|
4246
|
-
msg: "active hono requests went below 0, this is a RivetKit bug",
|
|
4247
|
-
...EXTRA_ERROR_LOG
|
|
4248
|
-
});
|
|
4249
|
-
}
|
|
4250
|
-
this.resetSleepTimer();
|
|
4251
|
-
}
|
|
4252
|
-
// MARK: - Message Processing
|
|
4253
|
-
async processMessage(message, conn) {
|
|
4254
|
-
await processMessage(message, this, conn, {
|
|
4255
|
-
onExecuteAction: async (ctx, name, args) => {
|
|
4256
|
-
this.inspector.emitter.emit("eventFired", {
|
|
4257
|
-
type: "action",
|
|
4258
|
-
name,
|
|
4259
|
-
args,
|
|
4260
|
-
connId: conn.id
|
|
4261
|
-
});
|
|
4262
|
-
return await this.executeAction(ctx, name, args);
|
|
4263
|
-
},
|
|
4264
|
-
onSubscribe: async (eventName, conn2) => {
|
|
4265
|
-
this.inspector.emitter.emit("eventFired", {
|
|
4266
|
-
type: "subscribe",
|
|
4267
|
-
eventName,
|
|
4268
|
-
connId: conn2.id
|
|
4269
|
-
});
|
|
4270
|
-
this.eventManager.addSubscription(eventName, conn2, false);
|
|
4271
|
-
},
|
|
4272
|
-
onUnsubscribe: async (eventName, conn2) => {
|
|
4273
|
-
this.inspector.emitter.emit("eventFired", {
|
|
4274
|
-
type: "unsubscribe",
|
|
4275
|
-
eventName,
|
|
4276
|
-
connId: conn2.id
|
|
4277
|
-
});
|
|
4278
|
-
this.eventManager.removeSubscription(eventName, conn2, false);
|
|
4279
|
-
}
|
|
4280
|
-
});
|
|
4281
|
-
}
|
|
4282
|
-
// MARK: - Action Execution
|
|
4283
|
-
async executeAction(ctx, actionName, args) {
|
|
4284
|
-
this.assertReady();
|
|
4285
|
-
const actions = this.#config.actions ?? {};
|
|
4286
|
-
if (!(actionName in actions)) {
|
|
4287
|
-
this.#rLog.warn({ msg: "action does not exist", actionName });
|
|
4288
|
-
throw new ActionNotFound(actionName);
|
|
4289
|
-
}
|
|
4290
|
-
const actionFunction = actions[actionName];
|
|
4291
|
-
if (typeof actionFunction !== "function") {
|
|
4292
|
-
this.#rLog.warn({
|
|
4293
|
-
msg: "action is not a function",
|
|
4294
|
-
actionName,
|
|
4295
|
-
type: typeof actionFunction
|
|
4296
|
-
});
|
|
4297
|
-
throw new ActionNotFound(actionName);
|
|
4298
|
-
}
|
|
4299
|
-
try {
|
|
4300
|
-
this.#rLog.debug({
|
|
4301
|
-
msg: "executing action",
|
|
4302
|
-
actionName,
|
|
4303
|
-
args
|
|
4304
|
-
});
|
|
4305
|
-
const outputOrPromise = actionFunction.call(
|
|
4306
|
-
void 0,
|
|
4307
|
-
ctx,
|
|
4308
|
-
...args
|
|
4309
|
-
);
|
|
4310
|
-
let output;
|
|
4311
|
-
if (outputOrPromise instanceof Promise) {
|
|
4312
|
-
output = await deadline(
|
|
4313
|
-
outputOrPromise,
|
|
4314
|
-
this.#config.options.actionTimeout
|
|
4315
|
-
);
|
|
4316
|
-
} else {
|
|
4317
|
-
output = outputOrPromise;
|
|
4318
|
-
}
|
|
4319
|
-
if (this.#config.onBeforeActionResponse) {
|
|
4320
|
-
try {
|
|
4321
|
-
const processedOutput = this.#config.onBeforeActionResponse(
|
|
4322
|
-
this.actorContext,
|
|
4323
|
-
actionName,
|
|
4324
|
-
args,
|
|
4325
|
-
output
|
|
4326
|
-
);
|
|
4327
|
-
if (processedOutput instanceof Promise) {
|
|
4328
|
-
output = await processedOutput;
|
|
4329
|
-
} else {
|
|
4330
|
-
output = processedOutput;
|
|
4331
|
-
}
|
|
4332
|
-
} catch (error) {
|
|
4333
|
-
this.#rLog.error({
|
|
4334
|
-
msg: "error in `onBeforeActionResponse`",
|
|
4335
|
-
error: stringifyError(error)
|
|
4336
|
-
});
|
|
4337
|
-
}
|
|
4338
|
-
}
|
|
4339
|
-
return output;
|
|
4340
|
-
} catch (error) {
|
|
4341
|
-
if (error instanceof DeadlineError) {
|
|
4342
|
-
throw new ActionTimedOut();
|
|
4343
|
-
}
|
|
4344
|
-
this.#rLog.error({
|
|
4345
|
-
msg: "action error",
|
|
4346
|
-
actionName,
|
|
4347
|
-
error: stringifyError(error)
|
|
4348
|
-
});
|
|
4349
|
-
throw error;
|
|
4350
|
-
} finally {
|
|
4351
|
-
this.stateManager.savePersistThrottled();
|
|
4352
|
-
}
|
|
4353
|
-
}
|
|
4354
|
-
// MARK: - HTTP/WebSocket Handlers
|
|
4355
|
-
async handleRawRequest(conn, request) {
|
|
4356
|
-
this.assertReady();
|
|
4357
|
-
if (!this.#config.onRequest) {
|
|
4358
|
-
throw new RequestHandlerNotDefined();
|
|
4359
|
-
}
|
|
4360
|
-
try {
|
|
4361
|
-
const ctx = new RequestContext(this, conn, request);
|
|
4362
|
-
const response = await this.#config.onRequest(ctx, request);
|
|
4363
|
-
if (!response) {
|
|
4364
|
-
throw new InvalidRequestHandlerResponse();
|
|
4365
|
-
}
|
|
4366
|
-
return response;
|
|
4367
|
-
} catch (error) {
|
|
4368
|
-
this.#rLog.error({
|
|
4369
|
-
msg: "onRequest error",
|
|
4370
|
-
error: stringifyError(error)
|
|
4371
|
-
});
|
|
4372
|
-
throw error;
|
|
4373
|
-
} finally {
|
|
4374
|
-
this.stateManager.savePersistThrottled();
|
|
4375
|
-
}
|
|
4376
|
-
}
|
|
4377
|
-
handleRawWebSocket(conn, websocket, request) {
|
|
4378
|
-
this.assertReady();
|
|
4379
|
-
if (!this.#config.onWebSocket) {
|
|
4380
|
-
throw new InternalError("onWebSocket handler not defined");
|
|
4381
|
-
}
|
|
4382
|
-
try {
|
|
4383
|
-
this.resetSleepTimer();
|
|
4384
|
-
const ctx = new WebSocketContext(this, conn, request);
|
|
4385
|
-
const voidOrPromise = this.#config.onWebSocket(ctx, websocket);
|
|
4386
|
-
if (voidOrPromise instanceof Promise) {
|
|
4387
|
-
voidOrPromise.then(() => {
|
|
4388
|
-
this.stateManager.savePersistThrottled();
|
|
4389
|
-
});
|
|
4390
|
-
} else {
|
|
4391
|
-
this.stateManager.savePersistThrottled();
|
|
4392
|
-
}
|
|
4393
|
-
} catch (error) {
|
|
4394
|
-
this.#rLog.error({
|
|
4395
|
-
msg: "onWebSocket error",
|
|
4396
|
-
error: stringifyError(error)
|
|
4397
|
-
});
|
|
4398
|
-
throw error;
|
|
4399
|
-
}
|
|
4400
|
-
}
|
|
4401
|
-
// MARK: - Scheduling
|
|
4402
|
-
async scheduleEvent(timestamp, action, args) {
|
|
4403
|
-
await this.#scheduleManager.scheduleEvent(timestamp, action, args);
|
|
4404
|
-
}
|
|
4405
|
-
async onAlarm() {
|
|
4406
|
-
this.resetSleepTimer();
|
|
4407
|
-
await this.#scheduleManager.onAlarm();
|
|
4408
|
-
}
|
|
4409
|
-
// MARK: - Background Tasks
|
|
4410
|
-
waitUntil(promise) {
|
|
4411
|
-
this.assertReady();
|
|
4412
|
-
const nonfailablePromise = promise.then(() => {
|
|
4413
|
-
this.#rLog.debug({ msg: "wait until promise complete" });
|
|
4414
|
-
}).catch((error) => {
|
|
4415
|
-
this.#rLog.error({
|
|
4416
|
-
msg: "wait until promise failed",
|
|
4417
|
-
error: stringifyError(error)
|
|
4418
|
-
});
|
|
4419
|
-
});
|
|
4420
|
-
this.#backgroundPromises.push(nonfailablePromise);
|
|
4421
|
-
}
|
|
4422
|
-
// MARK: - Private Helper Methods
|
|
4423
|
-
#initializeLogging() {
|
|
4424
|
-
var _a, _b;
|
|
4425
|
-
const logParams = {
|
|
4426
|
-
actor: this.#name,
|
|
4427
|
-
key: serializeActorKey(this.#key),
|
|
4428
|
-
actorId: this.#actorId
|
|
4429
|
-
};
|
|
4430
|
-
const extraLogParams = (_b = (_a = this.driver).getExtraActorLogParams) == null ? void 0 : _b.call(_a);
|
|
4431
|
-
if (extraLogParams) Object.assign(logParams, extraLogParams);
|
|
4432
|
-
this.#log = getBaseLogger().child(
|
|
4433
|
-
Object.assign(
|
|
4434
|
-
getIncludeTarget() ? { target: "actor" } : {},
|
|
4435
|
-
logParams
|
|
4436
|
-
)
|
|
4437
|
-
);
|
|
4438
|
-
this.#rLog = getBaseLogger().child(
|
|
4439
|
-
Object.assign(
|
|
4440
|
-
getIncludeTarget() ? { target: "actor-runtime" } : {},
|
|
4441
|
-
logParams
|
|
4442
|
-
)
|
|
4443
|
-
);
|
|
4444
|
-
}
|
|
4445
|
-
async #loadState() {
|
|
4446
|
-
const [persistDataBuffer] = await this.driver.kvBatchGet(
|
|
4447
|
-
this.#actorId,
|
|
4448
|
-
[KEYS.PERSIST_DATA]
|
|
4449
|
-
);
|
|
4450
|
-
invariant7(
|
|
4451
|
-
persistDataBuffer !== null,
|
|
4452
|
-
"persist data has not been set, it should be set when initialized"
|
|
4453
|
-
);
|
|
4454
|
-
const bareData = ACTOR_VERSIONED.deserializeWithEmbeddedVersion(persistDataBuffer);
|
|
4455
|
-
const persistData = convertActorFromBarePersisted(bareData);
|
|
4456
|
-
if (persistData.hasInitialized) {
|
|
4457
|
-
await this.#restoreExistingActor(persistData);
|
|
4458
|
-
} else {
|
|
4459
|
-
await this.#createNewActor(persistData);
|
|
4460
|
-
}
|
|
4461
|
-
this.#scheduleManager.setPersist(this.stateManager.persist);
|
|
4462
|
-
}
|
|
4463
|
-
async #createNewActor(persistData) {
|
|
4464
|
-
this.#rLog.info({ msg: "actor creating" });
|
|
4465
|
-
await this.stateManager.initializeState(persistData);
|
|
4466
|
-
if (this.#config.onCreate) {
|
|
4467
|
-
await this.#config.onCreate(
|
|
4468
|
-
this.actorContext,
|
|
4469
|
-
persistData.input
|
|
4470
|
-
);
|
|
4471
|
-
}
|
|
4472
|
-
}
|
|
4473
|
-
async #restoreExistingActor(persistData) {
|
|
4474
|
-
const connEntries = await this.driver.kvListPrefix(
|
|
4475
|
-
this.#actorId,
|
|
4476
|
-
KEYS.CONN_PREFIX
|
|
4477
|
-
);
|
|
4478
|
-
const connections = [];
|
|
4479
|
-
for (const [_key, value] of connEntries) {
|
|
4480
|
-
try {
|
|
4481
|
-
const bareData = CONN_VERSIONED.deserializeWithEmbeddedVersion(
|
|
4482
|
-
new Uint8Array(value)
|
|
4483
|
-
);
|
|
4484
|
-
const conn = convertConnFromBarePersistedConn(bareData);
|
|
4485
|
-
connections.push(conn);
|
|
4486
|
-
} catch (error) {
|
|
4487
|
-
this.#rLog.error({
|
|
4488
|
-
msg: "failed to decode connection",
|
|
4489
|
-
error: stringifyError(error)
|
|
4490
|
-
});
|
|
4491
|
-
}
|
|
4492
|
-
}
|
|
4493
|
-
this.#rLog.info({
|
|
4494
|
-
msg: "actor restoring",
|
|
4495
|
-
connections: connections.length
|
|
4496
|
-
});
|
|
4497
|
-
this.stateManager.initPersistProxy(persistData);
|
|
4498
|
-
this.connectionManager.restoreConnections(connections);
|
|
4499
|
-
}
|
|
4500
|
-
async #initializeInspectorToken() {
|
|
4501
|
-
const [tokenBuffer] = await this.driver.kvBatchGet(this.#actorId, [
|
|
4502
|
-
KEYS.INSPECTOR_TOKEN
|
|
4503
|
-
]);
|
|
4504
|
-
if (tokenBuffer !== null) {
|
|
4505
|
-
const decoder = new TextDecoder();
|
|
4506
|
-
this.#inspectorToken = decoder.decode(tokenBuffer);
|
|
4507
|
-
this.#rLog.debug({ msg: "loaded existing inspector token" });
|
|
4508
|
-
} else {
|
|
4509
|
-
this.#inspectorToken = generateSecureToken();
|
|
4510
|
-
const tokenBytes = new TextEncoder().encode(this.#inspectorToken);
|
|
4511
|
-
await this.driver.kvBatchPut(this.#actorId, [
|
|
4512
|
-
[KEYS.INSPECTOR_TOKEN, tokenBytes]
|
|
4513
|
-
]);
|
|
4514
|
-
this.#rLog.debug({ msg: "generated new inspector token" });
|
|
4515
|
-
}
|
|
4516
|
-
}
|
|
4517
|
-
async #initializeVars() {
|
|
4518
|
-
let vars;
|
|
4519
|
-
if ("createVars" in this.#config) {
|
|
4520
|
-
const dataOrPromise = this.#config.createVars(
|
|
4521
|
-
this.actorContext,
|
|
4522
|
-
this.driver.getContext(this.#actorId)
|
|
4523
|
-
);
|
|
4524
|
-
if (dataOrPromise instanceof Promise) {
|
|
4525
|
-
vars = await deadline(
|
|
4526
|
-
dataOrPromise,
|
|
4527
|
-
this.#config.options.createVarsTimeout
|
|
4528
|
-
);
|
|
4529
|
-
} else {
|
|
4530
|
-
vars = dataOrPromise;
|
|
4531
|
-
}
|
|
4532
|
-
} else if ("vars" in this.#config) {
|
|
4533
|
-
vars = structuredClone(this.#config.vars);
|
|
4534
|
-
} else {
|
|
4535
|
-
throw new Error(
|
|
4536
|
-
"Could not create variables from 'createVars' or 'vars'"
|
|
4537
|
-
);
|
|
4538
|
-
}
|
|
4539
|
-
this.#vars = vars;
|
|
4540
|
-
}
|
|
4541
|
-
async #callOnStart() {
|
|
4542
|
-
this.#rLog.info({ msg: "actor starting" });
|
|
4543
|
-
if (this.#config.onWake) {
|
|
4544
|
-
const result = this.#config.onWake(this.actorContext);
|
|
4545
|
-
if (result instanceof Promise) {
|
|
4546
|
-
await result;
|
|
4547
|
-
}
|
|
4548
|
-
}
|
|
4549
|
-
}
|
|
4550
|
-
async #callOnSleep() {
|
|
4551
|
-
if (this.#config.onSleep) {
|
|
4552
|
-
try {
|
|
4553
|
-
this.#rLog.debug({ msg: "calling onSleep" });
|
|
4554
|
-
const result = this.#config.onSleep(this.actorContext);
|
|
4555
|
-
if (result instanceof Promise) {
|
|
4556
|
-
await deadline(result, this.#config.options.onSleepTimeout);
|
|
4557
|
-
}
|
|
4558
|
-
this.#rLog.debug({ msg: "onSleep completed" });
|
|
4559
|
-
} catch (error) {
|
|
4560
|
-
if (error instanceof DeadlineError) {
|
|
4561
|
-
this.#rLog.error({ msg: "onSleep timed out" });
|
|
4562
|
-
} else {
|
|
4563
|
-
this.#rLog.error({
|
|
4564
|
-
msg: "error in onSleep",
|
|
4565
|
-
error: stringifyError(error)
|
|
4566
|
-
});
|
|
4567
|
-
}
|
|
4568
|
-
}
|
|
4569
|
-
}
|
|
4570
|
-
}
|
|
4571
|
-
async #callOnDestroy() {
|
|
4572
|
-
if (this.#config.onDestroy) {
|
|
4573
|
-
try {
|
|
4574
|
-
this.#rLog.debug({ msg: "calling onDestroy" });
|
|
4575
|
-
const result = this.#config.onDestroy(this.actorContext);
|
|
4576
|
-
if (result instanceof Promise) {
|
|
4577
|
-
await deadline(
|
|
4578
|
-
result,
|
|
4579
|
-
this.#config.options.onDestroyTimeout
|
|
4580
|
-
);
|
|
4581
|
-
}
|
|
4582
|
-
this.#rLog.debug({ msg: "onDestroy completed" });
|
|
4583
|
-
} catch (error) {
|
|
4584
|
-
if (error instanceof DeadlineError) {
|
|
4585
|
-
this.#rLog.error({ msg: "onDestroy timed out" });
|
|
4586
|
-
} else {
|
|
4587
|
-
this.#rLog.error({
|
|
4588
|
-
msg: "error in onDestroy",
|
|
4589
|
-
error: stringifyError(error)
|
|
4590
|
-
});
|
|
4591
|
-
}
|
|
4592
|
-
}
|
|
4593
|
-
}
|
|
4594
|
-
}
|
|
4595
|
-
async #setupDatabase() {
|
|
4596
|
-
var _a, _b;
|
|
4597
|
-
if ("db" in this.#config && this.#config.db) {
|
|
4598
|
-
const client = await this.#config.db.createClient({
|
|
4599
|
-
getDatabase: () => this.driver.getDatabase(this.#actorId)
|
|
4600
|
-
});
|
|
4601
|
-
this.#rLog.info({ msg: "database migration starting" });
|
|
4602
|
-
await ((_b = (_a = this.#config.db).onMigrate) == null ? void 0 : _b.call(_a, client));
|
|
4603
|
-
this.#rLog.info({ msg: "database migration complete" });
|
|
4604
|
-
this.#db = client;
|
|
4605
|
-
}
|
|
4606
|
-
}
|
|
4607
|
-
async #disconnectConnections() {
|
|
4608
|
-
const promises = [];
|
|
4609
|
-
this.#rLog.debug({
|
|
4610
|
-
msg: "disconnecting connections on actor stop",
|
|
4611
|
-
totalConns: this.connectionManager.connections.size
|
|
4612
|
-
});
|
|
4613
|
-
for (const connection of this.connectionManager.connections.values()) {
|
|
4614
|
-
this.#rLog.debug({
|
|
4615
|
-
msg: "checking connection for disconnect",
|
|
4616
|
-
connId: connection.id,
|
|
4617
|
-
isHibernatable: connection.isHibernatable
|
|
4618
|
-
});
|
|
4619
|
-
if (!connection.isHibernatable) {
|
|
4620
|
-
this.#rLog.debug({
|
|
4621
|
-
msg: "disconnecting non-hibernatable connection on actor stop",
|
|
4622
|
-
connId: connection.id
|
|
4623
|
-
});
|
|
4624
|
-
promises.push(connection.disconnect());
|
|
4625
|
-
} else {
|
|
4626
|
-
this.#rLog.debug({
|
|
4627
|
-
msg: "preserving hibernatable connection on actor stop",
|
|
4628
|
-
connId: connection.id
|
|
4629
|
-
});
|
|
4630
|
-
}
|
|
4631
|
-
}
|
|
4632
|
-
const res = await Promise.race([
|
|
4633
|
-
Promise.all(promises).then(() => false),
|
|
4634
|
-
new Promise(
|
|
4635
|
-
(res2) => globalThis.setTimeout(() => res2(true), 1500)
|
|
4636
|
-
)
|
|
4637
|
-
]);
|
|
4638
|
-
if (res) {
|
|
4639
|
-
this.#rLog.warn({
|
|
4640
|
-
msg: "timed out waiting for connections to close, shutting down anyway"
|
|
4641
|
-
});
|
|
4642
|
-
}
|
|
4643
|
-
}
|
|
4644
|
-
async #waitBackgroundPromises(timeoutMs) {
|
|
4645
|
-
const pending = this.#backgroundPromises;
|
|
4646
|
-
if (pending.length === 0) {
|
|
4647
|
-
this.#rLog.debug({ msg: "no background promises" });
|
|
4648
|
-
return;
|
|
4649
|
-
}
|
|
4650
|
-
const timedOut = await Promise.race([
|
|
4651
|
-
Promise.allSettled(pending).then(() => false),
|
|
4652
|
-
new Promise(
|
|
4653
|
-
(resolve) => setTimeout(() => resolve(true), timeoutMs)
|
|
4654
|
-
)
|
|
4655
|
-
]);
|
|
4656
|
-
if (timedOut) {
|
|
4657
|
-
this.#rLog.error({
|
|
4658
|
-
msg: "timed out waiting for background tasks",
|
|
4659
|
-
count: pending.length,
|
|
4660
|
-
timeoutMs
|
|
4661
|
-
});
|
|
4662
|
-
} else {
|
|
4663
|
-
this.#rLog.debug({ msg: "background promises finished" });
|
|
4664
|
-
}
|
|
4665
|
-
}
|
|
4666
|
-
resetSleepTimer() {
|
|
4667
|
-
if (this.#config.options.noSleep || !this.#sleepingSupported) return;
|
|
4668
|
-
if (this.#stopCalled) return;
|
|
4669
|
-
const canSleep = this.#canSleep();
|
|
4670
|
-
this.#rLog.debug({
|
|
4671
|
-
msg: "resetting sleep timer",
|
|
4672
|
-
canSleep: CanSleep[canSleep],
|
|
4673
|
-
existingTimeout: !!this.#sleepTimeout,
|
|
4674
|
-
timeout: this.#config.options.sleepTimeout
|
|
4675
|
-
});
|
|
4676
|
-
if (this.#sleepTimeout) {
|
|
4677
|
-
clearTimeout(this.#sleepTimeout);
|
|
4678
|
-
this.#sleepTimeout = void 0;
|
|
4679
|
-
}
|
|
4680
|
-
if (this.#sleepCalled) return;
|
|
4681
|
-
if (canSleep === 0 /* Yes */) {
|
|
4682
|
-
this.#sleepTimeout = setTimeout(() => {
|
|
4683
|
-
this.startSleep();
|
|
4684
|
-
}, this.#config.options.sleepTimeout);
|
|
4685
|
-
}
|
|
4686
|
-
}
|
|
4687
|
-
#canSleep() {
|
|
4688
|
-
if (!this.#ready) return 1 /* NotReady */;
|
|
4689
|
-
if (!this.#started) return 1 /* NotReady */;
|
|
4690
|
-
if (this.#activeHonoHttpRequests > 0)
|
|
4691
|
-
return 4 /* ActiveHonoHttpRequests */;
|
|
4692
|
-
for (const _conn of this.connectionManager.connections.values()) {
|
|
4693
|
-
return 3 /* ActiveConns */;
|
|
4694
|
-
}
|
|
4695
|
-
return 0 /* Yes */;
|
|
4696
|
-
}
|
|
4697
|
-
get #sleepingSupported() {
|
|
4698
|
-
return this.driver.startSleep !== void 0;
|
|
4699
|
-
}
|
|
4700
|
-
get #varsEnabled() {
|
|
4701
|
-
return "createVars" in this.#config || "vars" in this.#config;
|
|
4702
|
-
}
|
|
4703
|
-
#validateVarsEnabled() {
|
|
4704
|
-
if (!this.#varsEnabled) {
|
|
4705
|
-
throw new VarsNotEnabled();
|
|
4706
|
-
}
|
|
4707
|
-
}
|
|
4708
|
-
};
|
|
4709
|
-
|
|
4710
|
-
// src/actor/definition.ts
|
|
4711
|
-
var ActorDefinition = class {
|
|
4712
|
-
#config;
|
|
4713
|
-
constructor(config) {
|
|
4714
|
-
this.#config = config;
|
|
4715
|
-
}
|
|
4716
|
-
get config() {
|
|
4717
|
-
return this.#config;
|
|
4718
|
-
}
|
|
4719
|
-
instantiate() {
|
|
4720
|
-
return new ActorInstance(this.#config);
|
|
4721
|
-
}
|
|
4722
|
-
};
|
|
4723
|
-
function lookupInRegistry(config, name) {
|
|
4724
|
-
const definition = config.use[name];
|
|
4725
|
-
if (!definition) throw new Error(`no actor in registry for name ${name}`);
|
|
4726
|
-
return definition;
|
|
4727
|
-
}
|
|
4728
|
-
|
|
4729
|
-
// src/client/mod.ts
|
|
4730
|
-
function createClient(endpointOrConfig) {
|
|
4731
|
-
const configInput = endpointOrConfig === void 0 ? {} : typeof endpointOrConfig === "string" ? { endpoint: endpointOrConfig } : endpointOrConfig;
|
|
4732
|
-
const config = ClientConfigSchema.parse(configInput);
|
|
4733
|
-
const driver = new RemoteManagerDriver(config);
|
|
4734
|
-
if (config.devtools) {
|
|
4735
|
-
injectDevtools(config);
|
|
4736
|
-
}
|
|
4737
|
-
return createClientWithDriver(driver, config);
|
|
2634
|
+
return createClientWithDriver(driver, config);
|
|
4738
2635
|
}
|
|
4739
2636
|
|
|
4740
2637
|
export {
|
|
4741
|
-
ActorDefinition,
|
|
4742
|
-
lookupInRegistry,
|
|
4743
2638
|
ActorClientError,
|
|
4744
|
-
|
|
2639
|
+
InternalError,
|
|
4745
2640
|
ManagerError,
|
|
4746
2641
|
MalformedResponseMessage,
|
|
4747
2642
|
ActorError,
|
|
@@ -4759,4 +2654,4 @@ export {
|
|
|
4759
2654
|
RemoteManagerDriver,
|
|
4760
2655
|
createClient
|
|
4761
2656
|
};
|
|
4762
|
-
//# sourceMappingURL=chunk-
|
|
2657
|
+
//# sourceMappingURL=chunk-DIGBC2VI.js.map
|