rivetkit 2.0.6 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/dist/schemas/actor-persist/v1.ts +0 -6
  2. package/dist/tsup/actor-router-consts-B3Lu87yJ.d.cts +28 -0
  3. package/dist/tsup/actor-router-consts-B3Lu87yJ.d.ts +28 -0
  4. package/dist/tsup/{chunk-7OUKNSTU.js → chunk-2NL3KGJ7.js} +17 -14
  5. package/dist/tsup/chunk-2NL3KGJ7.js.map +1 -0
  6. package/dist/tsup/{chunk-6P6RA47N.cjs → chunk-3ALZ7EGX.cjs} +14 -10
  7. package/dist/tsup/chunk-3ALZ7EGX.cjs.map +1 -0
  8. package/dist/tsup/chunk-4EXJ4ITR.cjs +102 -0
  9. package/dist/tsup/chunk-4EXJ4ITR.cjs.map +1 -0
  10. package/dist/tsup/{chunk-ZYLTS2EM.js → chunk-54MAHBLL.js} +2 -2
  11. package/dist/tsup/{chunk-NTCUGYSD.cjs → chunk-7OOBMCQI.cjs} +34 -31
  12. package/dist/tsup/chunk-7OOBMCQI.cjs.map +1 -0
  13. package/dist/tsup/{chunk-VCEHU56K.js → chunk-B6N6VM37.js} +2 -2
  14. package/dist/tsup/{chunk-VPV4MWXR.js → chunk-DIHKN7NM.js} +3 -3
  15. package/dist/tsup/{chunk-MRRT2CZD.cjs → chunk-ETDWYT2P.cjs} +7 -7
  16. package/dist/tsup/{chunk-MRRT2CZD.cjs.map → chunk-ETDWYT2P.cjs.map} +1 -1
  17. package/dist/tsup/{chunk-TWGATZ3X.cjs → chunk-F7YL5G7Q.cjs} +922 -872
  18. package/dist/tsup/chunk-F7YL5G7Q.cjs.map +1 -0
  19. package/dist/tsup/{chunk-UTI5NCES.cjs → chunk-GWJTWY3G.cjs} +6 -6
  20. package/dist/tsup/{chunk-UTI5NCES.cjs.map → chunk-GWJTWY3G.cjs.map} +1 -1
  21. package/dist/tsup/{chunk-W6LN7AF5.js → chunk-KHRZPP5T.js} +866 -816
  22. package/dist/tsup/chunk-KHRZPP5T.js.map +1 -0
  23. package/dist/tsup/{chunk-5JBFVV4C.cjs → chunk-LXAVET4A.cjs} +21 -7
  24. package/dist/tsup/chunk-LXAVET4A.cjs.map +1 -0
  25. package/dist/tsup/{chunk-TCUI5JFE.cjs → chunk-NDCVQZBS.cjs} +45 -18
  26. package/dist/tsup/chunk-NDCVQZBS.cjs.map +1 -0
  27. package/dist/tsup/{chunk-4CKHQRXG.js → chunk-NII4KKHD.js} +515 -240
  28. package/dist/tsup/chunk-NII4KKHD.js.map +1 -0
  29. package/dist/tsup/{chunk-2K3JMDAN.js → chunk-NRELKXIX.js} +40 -13
  30. package/dist/tsup/chunk-NRELKXIX.js.map +1 -0
  31. package/dist/tsup/{chunk-UFWAK3X2.cjs → chunk-NUA6LOOJ.cjs} +660 -385
  32. package/dist/tsup/chunk-NUA6LOOJ.cjs.map +1 -0
  33. package/dist/tsup/{chunk-DIAYNQTE.cjs → chunk-OSK2VSJF.cjs} +12 -12
  34. package/dist/tsup/{chunk-DIAYNQTE.cjs.map → chunk-OSK2VSJF.cjs.map} +1 -1
  35. package/dist/tsup/chunk-PD6HCAJE.js +102 -0
  36. package/dist/tsup/chunk-PD6HCAJE.js.map +1 -0
  37. package/dist/tsup/{chunk-RGQR2J7S.js → chunk-RLBM6D4L.js} +20 -6
  38. package/dist/tsup/chunk-RLBM6D4L.js.map +1 -0
  39. package/dist/tsup/{chunk-KG3C7MKR.cjs → chunk-VAF63BEI.cjs} +3 -3
  40. package/dist/tsup/{chunk-KG3C7MKR.cjs.map → chunk-VAF63BEI.cjs.map} +1 -1
  41. package/dist/tsup/{chunk-G75SVQON.js → chunk-WAT5AE7S.js} +9 -5
  42. package/dist/tsup/chunk-WAT5AE7S.js.map +1 -0
  43. package/dist/tsup/{chunk-WC2PSJWN.js → chunk-YL4VZMMT.js} +2 -2
  44. package/dist/tsup/client/mod.cjs +9 -9
  45. package/dist/tsup/client/mod.d.cts +7 -8
  46. package/dist/tsup/client/mod.d.ts +7 -8
  47. package/dist/tsup/client/mod.js +8 -8
  48. package/dist/tsup/common/log.cjs +3 -3
  49. package/dist/tsup/common/log.js +2 -2
  50. package/dist/tsup/common/websocket.cjs +4 -4
  51. package/dist/tsup/common/websocket.js +3 -3
  52. package/dist/tsup/{connection-BLemxi4f.d.ts → conn-DCSQgIlw.d.ts} +1605 -1353
  53. package/dist/tsup/{connection-CpDIydXf.d.cts → conn-DdzHTm2E.d.cts} +1605 -1353
  54. package/dist/tsup/driver-helpers/mod.cjs +31 -5
  55. package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
  56. package/dist/tsup/driver-helpers/mod.d.cts +7 -8
  57. package/dist/tsup/driver-helpers/mod.d.ts +7 -8
  58. package/dist/tsup/driver-helpers/mod.js +33 -7
  59. package/dist/tsup/driver-test-suite/mod.cjs +317 -222
  60. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
  61. package/dist/tsup/driver-test-suite/mod.d.cts +7 -7
  62. package/dist/tsup/driver-test-suite/mod.d.ts +7 -7
  63. package/dist/tsup/driver-test-suite/mod.js +582 -487
  64. package/dist/tsup/driver-test-suite/mod.js.map +1 -1
  65. package/dist/tsup/inspector/mod.cjs +16 -6
  66. package/dist/tsup/inspector/mod.cjs.map +1 -1
  67. package/dist/tsup/inspector/mod.d.cts +34 -7
  68. package/dist/tsup/inspector/mod.d.ts +34 -7
  69. package/dist/tsup/inspector/mod.js +17 -7
  70. package/dist/tsup/mod.cjs +10 -20
  71. package/dist/tsup/mod.cjs.map +1 -1
  72. package/dist/tsup/mod.d.cts +9 -7
  73. package/dist/tsup/mod.d.ts +9 -7
  74. package/dist/tsup/mod.js +9 -19
  75. package/dist/tsup/test/mod.cjs +11 -11
  76. package/dist/tsup/test/mod.d.cts +6 -7
  77. package/dist/tsup/test/mod.d.ts +6 -7
  78. package/dist/tsup/test/mod.js +10 -10
  79. package/dist/tsup/utils.cjs +4 -2
  80. package/dist/tsup/utils.cjs.map +1 -1
  81. package/dist/tsup/utils.d.cts +11 -1
  82. package/dist/tsup/utils.d.ts +11 -1
  83. package/dist/tsup/utils.js +3 -1
  84. package/package.json +8 -4
  85. package/src/actor/action.ts +1 -1
  86. package/src/actor/config.ts +1 -1
  87. package/src/actor/conn-drivers.ts +205 -0
  88. package/src/actor/conn-socket.ts +6 -0
  89. package/src/actor/{connection.ts → conn.ts} +78 -84
  90. package/src/actor/context.ts +1 -1
  91. package/src/actor/driver.ts +4 -43
  92. package/src/actor/instance.ts +162 -86
  93. package/src/actor/mod.ts +1 -11
  94. package/src/actor/persisted.ts +2 -5
  95. package/src/actor/protocol/old.ts +1 -1
  96. package/src/actor/router-endpoints.ts +142 -106
  97. package/src/actor/router.ts +81 -45
  98. package/src/actor/utils.ts +5 -1
  99. package/src/client/actor-conn.ts +154 -23
  100. package/src/client/client.ts +1 -1
  101. package/src/client/config.ts +7 -0
  102. package/src/common/actor-router-consts.ts +29 -8
  103. package/src/common/router.ts +2 -1
  104. package/src/common/versioned-data.ts +5 -5
  105. package/src/driver-helpers/mod.ts +14 -1
  106. package/src/driver-test-suite/mod.ts +11 -2
  107. package/src/driver-test-suite/test-inline-client-driver.ts +36 -18
  108. package/src/driver-test-suite/tests/actor-conn-state.ts +66 -22
  109. package/src/driver-test-suite/tests/actor-conn.ts +65 -126
  110. package/src/driver-test-suite/tests/actor-reconnect.ts +160 -0
  111. package/src/driver-test-suite/tests/actor-sleep.ts +0 -1
  112. package/src/driver-test-suite/tests/raw-websocket.ts +0 -35
  113. package/src/driver-test-suite/utils.ts +3 -3
  114. package/src/drivers/default.ts +8 -7
  115. package/src/drivers/engine/actor-driver.ts +53 -31
  116. package/src/drivers/engine/config.ts +4 -0
  117. package/src/drivers/file-system/actor.ts +0 -6
  118. package/src/drivers/file-system/global-state.ts +3 -14
  119. package/src/drivers/file-system/manager.ts +12 -8
  120. package/src/inspector/actor.ts +4 -3
  121. package/src/inspector/config.ts +10 -1
  122. package/src/inspector/mod.ts +1 -0
  123. package/src/inspector/utils.ts +23 -4
  124. package/src/manager/driver.ts +11 -1
  125. package/src/manager/gateway.ts +407 -0
  126. package/src/manager/router.ts +269 -468
  127. package/src/manager-api/actors.ts +61 -0
  128. package/src/manager-api/common.ts +4 -0
  129. package/src/mod.ts +1 -1
  130. package/src/registry/mod.ts +119 -10
  131. package/src/remote-manager-driver/actor-http-client.ts +30 -19
  132. package/src/remote-manager-driver/actor-websocket-client.ts +43 -16
  133. package/src/remote-manager-driver/api-endpoints.ts +19 -21
  134. package/src/remote-manager-driver/api-utils.ts +10 -1
  135. package/src/remote-manager-driver/mod.ts +51 -48
  136. package/src/remote-manager-driver/ws-proxy.ts +2 -9
  137. package/src/test/mod.ts +6 -2
  138. package/src/utils.ts +21 -2
  139. package/dist/tsup/actor-router-consts-BK6arfy8.d.cts +0 -17
  140. package/dist/tsup/actor-router-consts-BK6arfy8.d.ts +0 -17
  141. package/dist/tsup/chunk-2K3JMDAN.js.map +0 -1
  142. package/dist/tsup/chunk-42I3OZ3Q.js +0 -15
  143. package/dist/tsup/chunk-42I3OZ3Q.js.map +0 -1
  144. package/dist/tsup/chunk-4CKHQRXG.js.map +0 -1
  145. package/dist/tsup/chunk-5JBFVV4C.cjs.map +0 -1
  146. package/dist/tsup/chunk-6P6RA47N.cjs.map +0 -1
  147. package/dist/tsup/chunk-7OUKNSTU.js.map +0 -1
  148. package/dist/tsup/chunk-G75SVQON.js.map +0 -1
  149. package/dist/tsup/chunk-KUPQZYUQ.cjs +0 -15
  150. package/dist/tsup/chunk-KUPQZYUQ.cjs.map +0 -1
  151. package/dist/tsup/chunk-NTCUGYSD.cjs.map +0 -1
  152. package/dist/tsup/chunk-RGQR2J7S.js.map +0 -1
  153. package/dist/tsup/chunk-TCUI5JFE.cjs.map +0 -1
  154. package/dist/tsup/chunk-TWGATZ3X.cjs.map +0 -1
  155. package/dist/tsup/chunk-UFWAK3X2.cjs.map +0 -1
  156. package/dist/tsup/chunk-W6LN7AF5.js.map +0 -1
  157. package/dist/tsup/common-CXCe7s6i.d.cts +0 -218
  158. package/dist/tsup/common-CXCe7s6i.d.ts +0 -218
  159. package/src/actor/generic-conn-driver.ts +0 -246
  160. package/src/common/fake-event-source.ts +0 -267
  161. package/src/manager-api/routes/actors-create.ts +0 -16
  162. package/src/manager-api/routes/actors-delete.ts +0 -4
  163. package/src/manager-api/routes/actors-get-by-id.ts +0 -7
  164. package/src/manager-api/routes/actors-get-or-create-by-id.ts +0 -29
  165. package/src/manager-api/routes/actors-get.ts +0 -7
  166. package/src/manager-api/routes/common.ts +0 -18
  167. /package/dist/tsup/{chunk-ZYLTS2EM.js.map → chunk-54MAHBLL.js.map} +0 -0
  168. /package/dist/tsup/{chunk-VCEHU56K.js.map → chunk-B6N6VM37.js.map} +0 -0
  169. /package/dist/tsup/{chunk-VPV4MWXR.js.map → chunk-DIHKN7NM.js.map} +0 -0
  170. /package/dist/tsup/{chunk-WC2PSJWN.js.map → chunk-YL4VZMMT.js.map} +0 -0
@@ -10,7 +10,8 @@
10
10
 
11
11
 
12
12
 
13
- var _chunk5JBFVV4Ccjs = require('./chunk-5JBFVV4C.cjs');
13
+
14
+ var _chunkLXAVET4Acjs = require('./chunk-LXAVET4A.cjs');
14
15
  require('./chunk-5QGQK44L.cjs');
15
16
 
16
17
 
@@ -24,5 +25,6 @@ require('./chunk-5QGQK44L.cjs');
24
25
 
25
26
 
26
27
 
27
- exports.SinglePromiseQueue = _chunk5JBFVV4Ccjs.SinglePromiseQueue; exports.VERSION = _chunk5JBFVV4Ccjs.VERSION; exports.assertUnreachable = _chunk5JBFVV4Ccjs.assertUnreachable; exports.bufferToArrayBuffer = _chunk5JBFVV4Ccjs.bufferToArrayBuffer; exports.combineUrlPath = _chunk5JBFVV4Ccjs.combineUrlPath; exports.dbg = _chunk5JBFVV4Ccjs.dbg; exports.getEnvUniversal = _chunk5JBFVV4Ccjs.getEnvUniversal; exports.httpUserAgent = _chunk5JBFVV4Ccjs.httpUserAgent; exports.setLongTimeout = _chunk5JBFVV4Ccjs.setLongTimeout; exports.stringifyError = _chunk5JBFVV4Ccjs.stringifyError; exports.toUint8Array = _chunk5JBFVV4Ccjs.toUint8Array;
28
+
29
+ exports.SinglePromiseQueue = _chunkLXAVET4Acjs.SinglePromiseQueue; exports.VERSION = _chunkLXAVET4Acjs.VERSION; exports.assertUnreachable = _chunkLXAVET4Acjs.assertUnreachable; exports.bufferToArrayBuffer = _chunkLXAVET4Acjs.bufferToArrayBuffer; exports.combineUrlPath = _chunkLXAVET4Acjs.combineUrlPath; exports.dbg = _chunkLXAVET4Acjs.dbg; exports.getEnvUniversal = _chunkLXAVET4Acjs.getEnvUniversal; exports.httpUserAgent = _chunkLXAVET4Acjs.httpUserAgent; exports.promiseWithResolvers = _chunkLXAVET4Acjs.promiseWithResolvers; exports.setLongTimeout = _chunkLXAVET4Acjs.setLongTimeout; exports.stringifyError = _chunkLXAVET4Acjs.stringifyError; exports.toUint8Array = _chunkLXAVET4Acjs.toUint8Array;
28
30
  //# sourceMappingURL=utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/utils.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wnBAAC","file":"/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/utils.cjs"}
1
+ {"version":3,"sources":["/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/utils.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,+rBAAC","file":"/Users/nathan/rivetkit/packages/rivetkit/dist/tsup/utils.cjs"}
@@ -18,6 +18,16 @@ declare function toUint8Array(data: ArrayBuffer | ArrayBufferView): Uint8Array;
18
18
  type LongTimeoutHandle = {
19
19
  abort: () => void;
20
20
  };
21
+ /**
22
+ * Polyfill for Promise.withResolvers().
23
+ *
24
+ * This is specifically for Cloudflare Workers. Their implementation of Promise.withResolvers does not work correctly.
25
+ */
26
+ declare function promiseWithResolvers<T>(): {
27
+ promise: Promise<T>;
28
+ resolve: (value: T | PromiseLike<T>) => void;
29
+ reject: (reason?: any) => void;
30
+ };
21
31
  declare function setLongTimeout(listener: () => void, after: number): LongTimeoutHandle;
22
32
  /**
23
33
  * A tiny utility that coalesces/enqueues async operations so only the latest
@@ -50,4 +60,4 @@ declare function bufferToArrayBuffer(buf: Buffer | Uint8Array): ArrayBuffer;
50
60
  */
51
61
  declare function combineUrlPath(endpoint: string, path: string, queryParams?: Record<string, string | undefined>): string;
52
62
 
53
- export { type LongTimeoutHandle, SinglePromiseQueue, type UpgradeWebSocket, VERSION, bufferToArrayBuffer, combineUrlPath, dbg, getEnvUniversal, httpUserAgent, setLongTimeout, toUint8Array };
63
+ export { type LongTimeoutHandle, SinglePromiseQueue, type UpgradeWebSocket, VERSION, bufferToArrayBuffer, combineUrlPath, dbg, getEnvUniversal, httpUserAgent, promiseWithResolvers, setLongTimeout, toUint8Array };
@@ -18,6 +18,16 @@ declare function toUint8Array(data: ArrayBuffer | ArrayBufferView): Uint8Array;
18
18
  type LongTimeoutHandle = {
19
19
  abort: () => void;
20
20
  };
21
+ /**
22
+ * Polyfill for Promise.withResolvers().
23
+ *
24
+ * This is specifically for Cloudflare Workers. Their implementation of Promise.withResolvers does not work correctly.
25
+ */
26
+ declare function promiseWithResolvers<T>(): {
27
+ promise: Promise<T>;
28
+ resolve: (value: T | PromiseLike<T>) => void;
29
+ reject: (reason?: any) => void;
30
+ };
21
31
  declare function setLongTimeout(listener: () => void, after: number): LongTimeoutHandle;
22
32
  /**
23
33
  * A tiny utility that coalesces/enqueues async operations so only the latest
@@ -50,4 +60,4 @@ declare function bufferToArrayBuffer(buf: Buffer | Uint8Array): ArrayBuffer;
50
60
  */
51
61
  declare function combineUrlPath(endpoint: string, path: string, queryParams?: Record<string, string | undefined>): string;
52
62
 
53
- export { type LongTimeoutHandle, SinglePromiseQueue, type UpgradeWebSocket, VERSION, bufferToArrayBuffer, combineUrlPath, dbg, getEnvUniversal, httpUserAgent, setLongTimeout, toUint8Array };
63
+ export { type LongTimeoutHandle, SinglePromiseQueue, type UpgradeWebSocket, VERSION, bufferToArrayBuffer, combineUrlPath, dbg, getEnvUniversal, httpUserAgent, promiseWithResolvers, setLongTimeout, toUint8Array };
@@ -7,10 +7,11 @@ import {
7
7
  dbg,
8
8
  getEnvUniversal,
9
9
  httpUserAgent,
10
+ promiseWithResolvers,
10
11
  setLongTimeout,
11
12
  stringifyError,
12
13
  toUint8Array
13
- } from "./chunk-RGQR2J7S.js";
14
+ } from "./chunk-RLBM6D4L.js";
14
15
  import "./chunk-YPZFLUO6.js";
15
16
  export {
16
17
  SinglePromiseQueue,
@@ -21,6 +22,7 @@ export {
21
22
  dbg,
22
23
  getEnvUniversal,
23
24
  httpUserAgent,
25
+ promiseWithResolvers,
24
26
  setLongTimeout,
25
27
  stringifyError,
26
28
  toUint8Array
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rivetkit",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "description": "Lightweight libraries for building stateful actors on edge platforms",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -147,12 +147,15 @@
147
147
  "engines": {
148
148
  "node": ">=22.0.0"
149
149
  },
150
- "sideEffects": false,
150
+ "sideEffects": [
151
+ "./dist/tsup/chunk-*.js",
152
+ "./dist/tsup/chunk-*.cjs"
153
+ ],
151
154
  "dependencies": {
152
155
  "@bare-ts/lib": "~0.3.0",
153
156
  "@hono/standard-validator": "^0.1.3",
154
157
  "@hono/zod-openapi": "^0.19.10",
155
- "@rivetkit/engine-runner": "https://pkg.pr.new/rivet-dev/engine/@rivetkit/engine-runner@b72b232",
158
+ "@rivetkit/engine-runner": "https://pkg.pr.new/rivet-dev/engine/@rivetkit/engine-runner@3002",
156
159
  "@rivetkit/fast-json-patch": "^3.1.2",
157
160
  "cbor-x": "^1.6.0",
158
161
  "hono": "^4.7.0",
@@ -177,7 +180,8 @@
177
180
  "tsx": "^4.19.4",
178
181
  "typescript": "^5.7.3",
179
182
  "vitest": "^3.1.1",
180
- "ws": "^8.18.1"
183
+ "ws": "^8.18.1",
184
+ "bufferutil": "^4.0.9"
181
185
  },
182
186
  "peerDependencies": {
183
187
  "@hono/node-server": "^1.14.0",
@@ -2,7 +2,7 @@ import type { ActorKey } from "@/actor/mod";
2
2
  import type { Client } from "@/client/client";
3
3
  import type { Logger } from "@/common/log";
4
4
  import type { Registry } from "@/registry/mod";
5
- import type { Conn, ConnId } from "./connection";
5
+ import type { Conn, ConnId } from "./conn";
6
6
  import type { ActorContext } from "./context";
7
7
  import type { AnyDatabaseProvider, InferDatabaseClient } from "./database";
8
8
  import type { SaveStateOptions } from "./instance";
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import type { UniversalWebSocket } from "@/common/websocket-interface";
3
3
  import type { ActionContext } from "./action";
4
- import type { Conn } from "./connection";
4
+ import type { Conn } from "./conn";
5
5
  import type { ActorContext } from "./context";
6
6
  import type { AnyDatabaseProvider } from "./database";
7
7
 
@@ -0,0 +1,205 @@
1
+ import type { SSEStreamingApi } from "hono/streaming";
2
+ import type { WSContext } from "hono/ws";
3
+ import type { WebSocket } from "ws";
4
+ import type { AnyConn } from "@/actor/conn";
5
+ import type { AnyActorInstance } from "@/actor/instance";
6
+ import type { CachedSerializer, Encoding } from "@/actor/protocol/serde";
7
+ import { encodeDataToString } from "@/actor/protocol/serde";
8
+ import type * as protocol from "@/schemas/client-protocol/mod";
9
+ import { assertUnreachable, type promiseWithResolvers } from "@/utils";
10
+
11
+ export enum ConnDriverKind {
12
+ WEBSOCKET = 0,
13
+ SSE = 1,
14
+ HTTP = 2,
15
+ }
16
+
17
+ export enum ConnReadyState {
18
+ UNKNOWN = -1,
19
+ CONNECTING = 0,
20
+ OPEN = 1,
21
+ CLOSING = 2,
22
+ CLOSED = 3,
23
+ }
24
+
25
+ export interface ConnDriverWebSocketState {
26
+ encoding: Encoding;
27
+ websocket: WSContext;
28
+ closePromise: ReturnType<typeof promiseWithResolvers<void>>;
29
+ }
30
+
31
+ export interface ConnDriverSseState {
32
+ encoding: Encoding;
33
+ stream: SSEStreamingApi;
34
+ }
35
+
36
+ export type ConnDriverHttpState = Record<never, never>;
37
+
38
+ export type ConnDriverState =
39
+ | { [ConnDriverKind.WEBSOCKET]: ConnDriverWebSocketState }
40
+ | { [ConnDriverKind.SSE]: ConnDriverSseState }
41
+ | { [ConnDriverKind.HTTP]: ConnDriverHttpState };
42
+
43
+ export interface ConnDriver<State> {
44
+ sendMessage?(
45
+ actor: AnyActorInstance,
46
+ conn: AnyConn,
47
+ state: State,
48
+ message: CachedSerializer<protocol.ToClient>,
49
+ ): void;
50
+
51
+ /**
52
+ * This returns a promise since we commonly disconnect at the end of a program, and not waiting will cause the socket to not close cleanly.
53
+ */
54
+ disconnect(
55
+ actor: AnyActorInstance,
56
+ conn: AnyConn,
57
+ state: State,
58
+ reason?: string,
59
+ ): Promise<void>;
60
+
61
+ /**
62
+ * Returns the ready state of the connection.
63
+ * This is used to determine if the connection is ready to send messages, or if the connection is stale.
64
+ */
65
+ getConnectionReadyState(
66
+ actor: AnyActorInstance,
67
+ conn: AnyConn,
68
+ state: State,
69
+ ): ConnReadyState | undefined;
70
+ }
71
+
72
+ // MARK: WebSocket
73
+ const WEBSOCKET_DRIVER: ConnDriver<ConnDriverWebSocketState> = {
74
+ sendMessage: (
75
+ actor: AnyActorInstance,
76
+ _conn: AnyConn,
77
+ state: ConnDriverWebSocketState,
78
+ message: CachedSerializer<protocol.ToClient>,
79
+ ) => {
80
+ const serialized = message.serialize(state.encoding);
81
+
82
+ actor.rLog.debug({
83
+ msg: "sending websocket message",
84
+ encoding: state.encoding,
85
+ dataType: typeof serialized,
86
+ isUint8Array: serialized instanceof Uint8Array,
87
+ isArrayBuffer: serialized instanceof ArrayBuffer,
88
+ dataLength: (serialized as any).byteLength || (serialized as any).length,
89
+ });
90
+
91
+ // Convert Uint8Array to ArrayBuffer for proper transmission
92
+ if (serialized instanceof Uint8Array) {
93
+ const buffer = serialized.buffer.slice(
94
+ serialized.byteOffset,
95
+ serialized.byteOffset + serialized.byteLength,
96
+ );
97
+ // Handle SharedArrayBuffer case
98
+ if (buffer instanceof SharedArrayBuffer) {
99
+ const arrayBuffer = new ArrayBuffer(buffer.byteLength);
100
+ new Uint8Array(arrayBuffer).set(new Uint8Array(buffer));
101
+ actor.rLog.debug({
102
+ msg: "converted SharedArrayBuffer to ArrayBuffer",
103
+ byteLength: arrayBuffer.byteLength,
104
+ });
105
+ state.websocket.send(arrayBuffer);
106
+ } else {
107
+ actor.rLog.debug({
108
+ msg: "sending ArrayBuffer",
109
+ byteLength: buffer.byteLength,
110
+ });
111
+ state.websocket.send(buffer);
112
+ }
113
+ } else {
114
+ actor.rLog.debug({
115
+ msg: "sending string data",
116
+ length: (serialized as string).length,
117
+ });
118
+ state.websocket.send(serialized);
119
+ }
120
+ },
121
+
122
+ disconnect: async (
123
+ _actor: AnyActorInstance,
124
+ _conn: AnyConn,
125
+ state: ConnDriverWebSocketState,
126
+ reason?: string,
127
+ ) => {
128
+ // Close socket
129
+ state.websocket.close(1000, reason);
130
+
131
+ // Create promise to wait for socket to close gracefully
132
+ await state.closePromise.promise;
133
+ },
134
+
135
+ getConnectionReadyState: (
136
+ _actor: AnyActorInstance,
137
+ _conn: AnyConn,
138
+ state: ConnDriverWebSocketState,
139
+ ): ConnReadyState | undefined => {
140
+ return state.websocket.readyState;
141
+ },
142
+ };
143
+
144
+ // MARK: SSE
145
+ const SSE_DRIVER: ConnDriver<ConnDriverSseState> = {
146
+ sendMessage: (
147
+ _actor: AnyActorInstance,
148
+ _conn: AnyConn,
149
+ state: ConnDriverSseState,
150
+ message: CachedSerializer<protocol.ToClient>,
151
+ ) => {
152
+ state.stream.writeSSE({
153
+ data: encodeDataToString(message.serialize(state.encoding)),
154
+ });
155
+ },
156
+
157
+ disconnect: async (
158
+ _actor: AnyActorInstance,
159
+ _conn: AnyConn,
160
+ state: ConnDriverSseState,
161
+ _reason?: string,
162
+ ) => {
163
+ state.stream.close();
164
+ },
165
+
166
+ getConnectionReadyState: (
167
+ _actor: AnyActorInstance,
168
+ _conn: AnyConn,
169
+ state: ConnDriverSseState,
170
+ ): ConnReadyState | undefined => {
171
+ if (state.stream.aborted || state.stream.closed) {
172
+ return ConnReadyState.CLOSED;
173
+ }
174
+
175
+ return ConnReadyState.OPEN;
176
+ },
177
+ };
178
+
179
+ // MARK: HTTP
180
+ const HTTP_DRIVER: ConnDriver<ConnDriverHttpState> = {
181
+ getConnectionReadyState(_actor, _conn) {
182
+ // TODO: This might not be the correct logic
183
+ return ConnReadyState.OPEN;
184
+ },
185
+ disconnect: async () => {
186
+ // Noop
187
+ // TODO: Abort the request
188
+ },
189
+ };
190
+
191
+ /** List of all connection drivers. */
192
+ export const CONN_DRIVERS: Record<ConnDriverKind, ConnDriver<unknown>> = {
193
+ [ConnDriverKind.WEBSOCKET]: WEBSOCKET_DRIVER,
194
+ [ConnDriverKind.SSE]: SSE_DRIVER,
195
+ [ConnDriverKind.HTTP]: HTTP_DRIVER,
196
+ };
197
+
198
+ export function getConnDriverKindFromState(
199
+ state: ConnDriverState,
200
+ ): ConnDriverKind {
201
+ if (ConnDriverKind.WEBSOCKET in state) return ConnDriverKind.WEBSOCKET;
202
+ else if (ConnDriverKind.SSE in state) return ConnDriverKind.SSE;
203
+ else if (ConnDriverKind.HTTP in state) return ConnDriverKind.HTTP;
204
+ else assertUnreachable(state);
205
+ }
@@ -0,0 +1,6 @@
1
+ import type { ConnDriverState } from "./conn-drivers";
2
+
3
+ export interface ConnSocket {
4
+ socketId: string;
5
+ driverState: ConnDriverState;
6
+ }
@@ -1,12 +1,19 @@
1
1
  import * as cbor from "cbor-x";
2
+ import invariant from "invariant";
2
3
  import type * as protocol from "@/schemas/client-protocol/mod";
3
4
  import { TO_CLIENT_VERSIONED } from "@/schemas/client-protocol/versioned";
4
5
  import { bufferToArrayBuffer } from "@/utils";
6
+ import {
7
+ CONN_DRIVERS,
8
+ ConnDriverKind,
9
+ type ConnDriverState,
10
+ ConnReadyState,
11
+ getConnDriverKindFromState,
12
+ } from "./conn-drivers";
13
+ import type { ConnSocket } from "./conn-socket";
5
14
  import type { AnyDatabaseProvider } from "./database";
6
- import { type ConnDriver, ConnectionReadyState } from "./driver";
7
15
  import * as errors from "./errors";
8
16
  import type { ActorInstance } from "./instance";
9
- import { loggerWithoutContext } from "./log";
10
17
  import type { PersistedConn } from "./persisted";
11
18
  import { CachedSerializer } from "./protocol/serde";
12
19
  import { generateSecureToken } from "./utils";
@@ -19,23 +26,16 @@ export function generateConnToken(): string {
19
26
  return generateSecureToken(32);
20
27
  }
21
28
 
29
+ export function generateConnSocketId(): string {
30
+ return crypto.randomUUID();
31
+ }
32
+
22
33
  export type ConnId = string;
23
34
 
24
35
  export type AnyConn = Conn<any, any, any, any, any, any>;
25
36
 
26
- export const CONNECTION_DRIVER_WEBSOCKET = "webSocket";
27
- export const CONNECTION_DRIVER_SSE = "sse";
28
- export const CONNECTION_DRIVER_HTTP = "http";
29
-
30
- export type ConnectionDriver =
31
- | typeof CONNECTION_DRIVER_WEBSOCKET
32
- | typeof CONNECTION_DRIVER_SSE
33
- | typeof CONNECTION_DRIVER_HTTP;
34
-
35
37
  export type ConnectionStatus = "connected" | "reconnecting";
36
38
 
37
- export const CONNECTION_CHECK_LIVENESS_SYMBOL = Symbol("checkLiveness");
38
-
39
39
  /**
40
40
  * Represents a client connection to a actor.
41
41
  *
@@ -46,13 +46,9 @@ export const CONNECTION_CHECK_LIVENESS_SYMBOL = Symbol("checkLiveness");
46
46
  export class Conn<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
47
47
  subscriptions: Set<string> = new Set<string>();
48
48
 
49
- #stateEnabled: boolean;
50
-
51
49
  // TODO: Remove this cyclical reference
52
50
  #actor: ActorInstance<S, CP, CS, V, I, DB>;
53
51
 
54
- #status: ConnectionStatus = "connected";
55
-
56
52
  /**
57
53
  * The proxied state that notifies of changes automatically.
58
54
  *
@@ -60,23 +56,31 @@ export class Conn<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
60
56
  */
61
57
  __persist: PersistedConn<CP, CS>;
62
58
 
59
+ get __driverState(): ConnDriverState | undefined {
60
+ return this.__socket?.driverState;
61
+ }
62
+
63
63
  /**
64
- * Driver used to manage realtime connection communication.
64
+ * Socket connected to this connection.
65
65
  *
66
- * @protected
66
+ * If undefined, then nothing is connected to this.
67
67
  */
68
- #driver: ConnDriver;
68
+ __socket?: ConnSocket;
69
69
 
70
- public get params(): CP {
71
- return this.__persist.params;
70
+ get __status(): ConnectionStatus {
71
+ if (this.__socket) {
72
+ return "connected";
73
+ } else {
74
+ return "reconnecting";
75
+ }
72
76
  }
73
77
 
74
- public get driver(): ConnectionDriver {
75
- return this.__persist.connDriver as ConnectionDriver;
78
+ public get params(): CP {
79
+ return this.__persist.params;
76
80
  }
77
81
 
78
- public get _stateEnabled() {
79
- return this.#stateEnabled;
82
+ public get __stateEnabled() {
83
+ return this.#actor.connStateEnabled;
80
84
  }
81
85
 
82
86
  /**
@@ -118,7 +122,7 @@ export class Conn<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
118
122
  * Status of the connection.
119
123
  */
120
124
  public get status(): ConnectionStatus {
121
- return this.#status;
125
+ return this.__status;
122
126
  }
123
127
 
124
128
  /**
@@ -138,17 +142,13 @@ export class Conn<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
138
142
  public constructor(
139
143
  actor: ActorInstance<S, CP, CS, V, I, DB>,
140
144
  persist: PersistedConn<CP, CS>,
141
- driver: ConnDriver,
142
- stateEnabled: boolean,
143
145
  ) {
144
146
  this.#actor = actor;
145
147
  this.__persist = persist;
146
- this.#driver = driver;
147
- this.#stateEnabled = stateEnabled;
148
148
  }
149
149
 
150
150
  #validateStateEnabled() {
151
- if (!this.#stateEnabled) {
151
+ if (!this.__stateEnabled) {
152
152
  throw new errors.ConnStateNotEnabled();
153
153
  }
154
154
  }
@@ -161,12 +161,28 @@ export class Conn<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
161
161
  * @protected
162
162
  */
163
163
  public _sendMessage(message: CachedSerializer<protocol.ToClient>) {
164
- this.#driver.sendMessage?.(
165
- this.#actor,
166
- this,
167
- this.__persist.connDriverState,
168
- message,
169
- );
164
+ if (this.__driverState) {
165
+ const driverKind = getConnDriverKindFromState(this.__driverState);
166
+ const driver = CONN_DRIVERS[driverKind];
167
+ if (driver.sendMessage) {
168
+ driver.sendMessage(
169
+ this.#actor,
170
+ this,
171
+ (this.__driverState as any)[driverKind],
172
+ message,
173
+ );
174
+ } else {
175
+ this.#actor.rLog.debug({
176
+ msg: "conn driver does not support sending messages",
177
+ conn: this.id,
178
+ });
179
+ }
180
+ } else {
181
+ this.#actor.rLog.warn({
182
+ msg: "missing connection driver state for send message",
183
+ conn: this.id,
184
+ });
185
+ }
170
186
  }
171
187
 
172
188
  /**
@@ -205,53 +221,31 @@ export class Conn<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
205
221
  * @param reason - The reason for disconnection.
206
222
  */
207
223
  public async disconnect(reason?: string) {
208
- this.#status = "reconnecting";
209
- await this.#driver.disconnect(
210
- this.#actor,
211
- this,
212
- this.__persist.connDriverState,
213
- reason,
214
- );
215
- }
216
-
217
- /**
218
- * This method checks the connection's liveness by querying the driver for its ready state.
219
- * If the connection is not closed, it updates the last liveness timestamp and returns `true`.
220
- * Otherwise, it returns `false`.
221
- * @internal
222
- */
223
- [CONNECTION_CHECK_LIVENESS_SYMBOL]() {
224
- const readyState = this.#driver.getConnectionReadyState(this.#actor, this);
225
-
226
- const isConnectionClosed =
227
- readyState === ConnectionReadyState.CLOSED ||
228
- readyState === ConnectionReadyState.CLOSING ||
229
- readyState === undefined;
230
-
231
- const newLastSeen = Date.now();
232
- const newStatus = isConnectionClosed ? "reconnecting" : "connected";
233
-
234
- this.#actor.rLog.debug({
235
- msg: "liveness probe for connection",
236
- connId: this.id,
237
- actorId: this.#actor.id,
238
- readyState,
239
-
240
- status: this.#status,
241
- newStatus,
242
-
243
- lastSeen: this.__persist.lastSeen,
244
- currentTs: newLastSeen,
245
- });
246
-
247
- if (!isConnectionClosed) {
248
- this.__persist.lastSeen = newLastSeen;
224
+ if (this.__socket && this.__driverState) {
225
+ const driverKind = getConnDriverKindFromState(this.__driverState);
226
+ const driver = CONN_DRIVERS[driverKind];
227
+ if (driver.disconnect) {
228
+ driver.disconnect(
229
+ this.#actor,
230
+ this,
231
+ (this.__driverState as any)[driverKind],
232
+ reason,
233
+ );
234
+ } else {
235
+ this.#actor.rLog.debug({
236
+ msg: "no disconnect handler for conn driver",
237
+ conn: this.id,
238
+ });
239
+ }
240
+
241
+ this.#actor.__connDisconnected(this, true, this.__socket.socketId);
242
+ } else {
243
+ this.#actor.rLog.warn({
244
+ msg: "missing connection driver state for disconnect",
245
+ conn: this.id,
246
+ });
249
247
  }
250
248
 
251
- this.#status = newStatus;
252
- return {
253
- status: this.#status,
254
- lastSeen: this.__persist.lastSeen,
255
- };
249
+ this.__socket = undefined;
256
250
  }
257
251
  }
@@ -2,7 +2,7 @@ import type { ActorKey } from "@/actor/mod";
2
2
  import type { Client } from "@/client/client";
3
3
  import type { Logger } from "@/common/log";
4
4
  import type { Registry } from "@/registry/mod";
5
- import type { Conn, ConnId } from "./connection";
5
+ import type { Conn, ConnId } from "./conn";
6
6
  import type { AnyDatabaseProvider, InferDatabaseClient } from "./database";
7
7
  import type { ActorInstance, SaveStateOptions } from "./instance";
8
8
  import type { Schedule } from "./schedule";
@@ -1,15 +1,10 @@
1
- import type { CachedSerializer } from "@/actor/protocol/serde";
1
+ import type { Context as HonoContext } from "hono";
2
2
  import type { AnyClient } from "@/client/client";
3
3
  import type { ManagerDriver } from "@/manager/driver";
4
4
  import type { RegistryConfig } from "@/registry/config";
5
5
  import type { RunConfig } from "@/registry/run-config";
6
- import type * as protocol from "@/schemas/client-protocol/mod";
7
- import type { AnyConn, ConnectionDriver } from "./connection";
8
- import type { GenericConnGlobalState } from "./generic-conn-driver";
9
6
  import type { AnyActorInstance } from "./instance";
10
7
 
11
- export type ConnectionDriversMap = Record<ConnectionDriver, ConnDriver>;
12
-
13
8
  export type ActorDriverBuilder = (
14
9
  registryConfig: RegistryConfig,
15
10
  runConfig: RunConfig,
@@ -22,8 +17,6 @@ export interface ActorDriver {
22
17
 
23
18
  loadActor(actorId: string): Promise<AnyActorInstance>;
24
19
 
25
- getGenericConnGlobalState(actorId: string): GenericConnGlobalState;
26
-
27
20
  getContext(actorId: string): unknown;
28
21
 
29
22
  readPersistedData(actorId: string): Promise<Uint8Array | undefined>;
@@ -45,40 +38,8 @@ export interface ActorDriver {
45
38
  sleep?(actorId: string): Promise<void>;
46
39
 
47
40
  shutdown?(immediate: boolean): Promise<void>;
48
- }
49
-
50
- export enum ConnectionReadyState {
51
- UNKNOWN = -1,
52
- CONNECTING = 0,
53
- OPEN = 1,
54
- CLOSING = 2,
55
- CLOSED = 3,
56
- }
57
-
58
- export interface ConnDriver<ConnDriverState = unknown> {
59
- sendMessage?(
60
- actor: AnyActorInstance,
61
- conn: AnyConn,
62
- state: ConnDriverState,
63
- message: CachedSerializer<protocol.ToClient>,
64
- ): void;
65
41
 
66
- /**
67
- * This returns a promise since we commonly disconnect at the end of a program, and not waiting will cause the socket to not close cleanly.
68
- */
69
- disconnect(
70
- actor: AnyActorInstance,
71
- conn: AnyConn,
72
- state: ConnDriverState,
73
- reason?: string,
74
- ): Promise<void>;
75
-
76
- /**
77
- * Returns the ready state of the connection.
78
- * This is used to determine if the connection is ready to send messages, or if the connection is stale.
79
- */
80
- getConnectionReadyState(
81
- actor: AnyActorInstance,
82
- conn: AnyConn,
83
- ): ConnectionReadyState | undefined;
42
+ // Serverless
43
+ /** This handles the serverless start request. This should manage the lifecycle of the runner tied to the request lifecycle. */
44
+ serverlessHandleStart?(c: HonoContext): Promise<Response>;
84
45
  }