rivetkit 2.0.22-rc.2 → 2.0.23

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 (109) hide show
  1. package/dist/schemas/actor-persist/v2.ts +29 -26
  2. package/dist/tsup/{chunk-FLVL7RGH.js → chunk-3I6ZIJVJ.js} +3 -3
  3. package/dist/tsup/{chunk-GXIO5YOT.cjs → chunk-3JYSUFET.cjs} +24 -10
  4. package/dist/tsup/chunk-3JYSUFET.cjs.map +1 -0
  5. package/dist/tsup/{chunk-NDOG6IQ5.cjs → chunk-54DVMQPT.cjs} +6 -6
  6. package/dist/tsup/{chunk-NDOG6IQ5.cjs.map → chunk-54DVMQPT.cjs.map} +1 -1
  7. package/dist/tsup/{chunk-7RUROQAZ.js → chunk-5PKKNNNS.js} +279 -9
  8. package/dist/tsup/chunk-5PKKNNNS.js.map +1 -0
  9. package/dist/tsup/{chunk-F7WVJXPB.js → chunk-5UJQWWO3.js} +2 -2
  10. package/dist/tsup/{chunk-YUBR6XCJ.cjs → chunk-C56XVVV4.cjs} +280 -10
  11. package/dist/tsup/chunk-C56XVVV4.cjs.map +1 -0
  12. package/dist/tsup/{chunk-Q5CAVEKC.cjs → chunk-D6PCH7FR.cjs} +561 -487
  13. package/dist/tsup/chunk-D6PCH7FR.cjs.map +1 -0
  14. package/dist/tsup/{chunk-C4FPCW7T.js → chunk-DLYZKFRY.js} +2 -2
  15. package/dist/tsup/{chunk-AMK3AACS.js → chunk-FTQ62XTN.js} +373 -299
  16. package/dist/tsup/chunk-FTQ62XTN.js.map +1 -0
  17. package/dist/tsup/{chunk-LFP446KS.cjs → chunk-HNYF4T36.cjs} +14 -14
  18. package/dist/tsup/{chunk-LFP446KS.cjs.map → chunk-HNYF4T36.cjs.map} +1 -1
  19. package/dist/tsup/{chunk-5TRXLS6X.cjs → chunk-JMLTKMJ7.cjs} +48 -44
  20. package/dist/tsup/chunk-JMLTKMJ7.cjs.map +1 -0
  21. package/dist/tsup/{chunk-ZY4DKLMT.cjs → chunk-NCUALX2Q.cjs} +3 -3
  22. package/dist/tsup/{chunk-ZY4DKLMT.cjs.map → chunk-NCUALX2Q.cjs.map} +1 -1
  23. package/dist/tsup/{chunk-HLZT5C6A.js → chunk-NOZSCUPQ.js} +99 -50
  24. package/dist/tsup/chunk-NOZSCUPQ.js.map +1 -0
  25. package/dist/tsup/{chunk-CVLO2OOK.js → chunk-PHNIVSG5.js} +19 -5
  26. package/dist/tsup/chunk-PHNIVSG5.js.map +1 -0
  27. package/dist/tsup/{chunk-BHLQTKOD.js → chunk-RUTBXBRR.js} +27 -23
  28. package/dist/tsup/{chunk-BHLQTKOD.js.map → chunk-RUTBXBRR.js.map} +1 -1
  29. package/dist/tsup/{chunk-MQDXPGNE.js → chunk-RVVUS4X6.js} +6 -6
  30. package/dist/tsup/{chunk-UBMUBNS2.cjs → chunk-SN4KWTRA.cjs} +12 -12
  31. package/dist/tsup/{chunk-UBMUBNS2.cjs.map → chunk-SN4KWTRA.cjs.map} +1 -1
  32. package/dist/tsup/{chunk-ZL6NSKF2.cjs → chunk-XSDSNHSE.cjs} +3 -3
  33. package/dist/tsup/{chunk-ZL6NSKF2.cjs.map → chunk-XSDSNHSE.cjs.map} +1 -1
  34. package/dist/tsup/{chunk-YLWF6RFL.cjs → chunk-XYK5PY3B.cjs} +283 -234
  35. package/dist/tsup/chunk-XYK5PY3B.cjs.map +1 -0
  36. package/dist/tsup/{chunk-EJXZYQ3N.js → chunk-YAYNBR37.js} +2 -2
  37. package/dist/tsup/client/mod.cjs +8 -9
  38. package/dist/tsup/client/mod.cjs.map +1 -1
  39. package/dist/tsup/client/mod.d.cts +2 -2
  40. package/dist/tsup/client/mod.d.ts +2 -2
  41. package/dist/tsup/client/mod.js +7 -8
  42. package/dist/tsup/common/log.cjs +2 -3
  43. package/dist/tsup/common/log.cjs.map +1 -1
  44. package/dist/tsup/common/log.js +1 -2
  45. package/dist/tsup/common/websocket.cjs +3 -4
  46. package/dist/tsup/common/websocket.cjs.map +1 -1
  47. package/dist/tsup/common/websocket.js +2 -3
  48. package/dist/tsup/{conn-BYXlxnh0.d.ts → conn-B3Vhbgnd.d.ts} +5 -1
  49. package/dist/tsup/{conn-BiazosE_.d.cts → conn-DJWL3nGx.d.cts} +5 -1
  50. package/dist/tsup/driver-helpers/mod.cjs +4 -5
  51. package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
  52. package/dist/tsup/driver-helpers/mod.d.cts +1 -1
  53. package/dist/tsup/driver-helpers/mod.d.ts +1 -1
  54. package/dist/tsup/driver-helpers/mod.js +3 -4
  55. package/dist/tsup/driver-test-suite/mod.cjs +70 -72
  56. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
  57. package/dist/tsup/driver-test-suite/mod.d.cts +1 -1
  58. package/dist/tsup/driver-test-suite/mod.d.ts +1 -1
  59. package/dist/tsup/driver-test-suite/mod.js +11 -13
  60. package/dist/tsup/driver-test-suite/mod.js.map +1 -1
  61. package/dist/tsup/inspector/mod.cjs +5 -6
  62. package/dist/tsup/inspector/mod.cjs.map +1 -1
  63. package/dist/tsup/inspector/mod.d.cts +2 -2
  64. package/dist/tsup/inspector/mod.d.ts +2 -2
  65. package/dist/tsup/inspector/mod.js +4 -5
  66. package/dist/tsup/mod.cjs +9 -10
  67. package/dist/tsup/mod.cjs.map +1 -1
  68. package/dist/tsup/mod.d.cts +4 -4
  69. package/dist/tsup/mod.d.ts +4 -4
  70. package/dist/tsup/mod.js +8 -9
  71. package/dist/tsup/test/mod.cjs +10 -11
  72. package/dist/tsup/test/mod.cjs.map +1 -1
  73. package/dist/tsup/test/mod.d.cts +1 -1
  74. package/dist/tsup/test/mod.d.ts +1 -1
  75. package/dist/tsup/test/mod.js +9 -10
  76. package/dist/tsup/utils.cjs +2 -2
  77. package/dist/tsup/utils.js +1 -1
  78. package/package.json +2 -2
  79. package/src/actor/conn-drivers.ts +0 -32
  80. package/src/actor/conn-socket.ts +2 -0
  81. package/src/actor/conn.ts +13 -12
  82. package/src/actor/instance.ts +164 -36
  83. package/src/actor/persisted.ts +4 -1
  84. package/src/actor/router-endpoints.ts +14 -0
  85. package/src/actor/router.ts +2 -0
  86. package/src/actor/utils.test.ts +48 -0
  87. package/src/actor/utils.ts +23 -0
  88. package/src/drivers/engine/actor-driver.ts +97 -35
  89. package/src/drivers/file-system/manager.ts +4 -0
  90. package/src/schemas/actor-persist/versioned.ts +4 -0
  91. package/src/utils.ts +15 -6
  92. package/dist/tsup/chunk-5N6F5PXD.cjs +0 -269
  93. package/dist/tsup/chunk-5N6F5PXD.cjs.map +0 -1
  94. package/dist/tsup/chunk-5TRXLS6X.cjs.map +0 -1
  95. package/dist/tsup/chunk-7RUROQAZ.js.map +0 -1
  96. package/dist/tsup/chunk-AMK3AACS.js.map +0 -1
  97. package/dist/tsup/chunk-CVLO2OOK.js.map +0 -1
  98. package/dist/tsup/chunk-GXIO5YOT.cjs.map +0 -1
  99. package/dist/tsup/chunk-HLZT5C6A.js.map +0 -1
  100. package/dist/tsup/chunk-Q5CAVEKC.cjs.map +0 -1
  101. package/dist/tsup/chunk-VMFBKBJL.js +0 -269
  102. package/dist/tsup/chunk-VMFBKBJL.js.map +0 -1
  103. package/dist/tsup/chunk-YLWF6RFL.cjs.map +0 -1
  104. package/dist/tsup/chunk-YUBR6XCJ.cjs.map +0 -1
  105. /package/dist/tsup/{chunk-FLVL7RGH.js.map → chunk-3I6ZIJVJ.js.map} +0 -0
  106. /package/dist/tsup/{chunk-F7WVJXPB.js.map → chunk-5UJQWWO3.js.map} +0 -0
  107. /package/dist/tsup/{chunk-C4FPCW7T.js.map → chunk-DLYZKFRY.js.map} +0 -0
  108. /package/dist/tsup/{chunk-MQDXPGNE.js.map → chunk-RVVUS4X6.js.map} +0 -0
  109. /package/dist/tsup/{chunk-EJXZYQ3N.js.map → chunk-YAYNBR37.js.map} +0 -0
@@ -3,11 +3,11 @@ import {
3
3
  ForeignKeysSchema,
4
4
  PatchSchema,
5
5
  TablesSchema
6
- } from "./chunk-C4FPCW7T.js";
6
+ } from "./chunk-DLYZKFRY.js";
7
7
  import {
8
8
  importWebSocket,
9
9
  logger
10
- } from "./chunk-F7WVJXPB.js";
10
+ } from "./chunk-5UJQWWO3.js";
11
11
  import {
12
12
  ActionContext,
13
13
  HTTP_ACTION_REQUEST_VERSIONED,
@@ -18,7 +18,7 @@ import {
18
18
  TO_SERVER_VERSIONED,
19
19
  inputDataToBuffer,
20
20
  processMessage
21
- } from "./chunk-BHLQTKOD.js";
21
+ } from "./chunk-RUTBXBRR.js";
22
22
  import {
23
23
  CachedSerializer,
24
24
  DeadlineError,
@@ -43,15 +43,12 @@ import {
43
43
  encodingIsBinary,
44
44
  generateRandomString,
45
45
  generateSecureToken,
46
+ isConnStatePath,
47
+ isStatePath,
46
48
  jsonStringifyCompat,
47
49
  serializeWithEncoding,
48
50
  uint8ArrayToBase64
49
- } from "./chunk-CVLO2OOK.js";
50
- import {
51
- getBaseLogger,
52
- getIncludeTarget,
53
- getLogger
54
- } from "./chunk-VMFBKBJL.js";
51
+ } from "./chunk-PHNIVSG5.js";
55
52
  import {
56
53
  EXTRA_ERROR_LOG,
57
54
  SinglePromiseQueue,
@@ -60,13 +57,17 @@ import {
60
57
  bufferToArrayBuffer,
61
58
  combineUrlPath,
62
59
  deconstructError,
60
+ getBaseLogger,
63
61
  getEnvUniversal,
62
+ getIncludeTarget,
63
+ getLogger,
64
64
  httpUserAgent,
65
+ idToStr,
65
66
  isCborSerializable,
66
67
  noopNext,
67
68
  promiseWithResolvers,
68
69
  stringifyError
69
- } from "./chunk-7RUROQAZ.js";
70
+ } from "./chunk-5PKKNNNS.js";
70
71
  import {
71
72
  ActionNotFound,
72
73
  ActionTimedOut,
@@ -83,7 +84,7 @@ import {
83
84
  } from "./chunk-G64QUEDJ.js";
84
85
 
85
86
  // src/actor/conn.ts
86
- import * as cbor from "cbor-x";
87
+ import * as cbor2 from "cbor-x";
87
88
 
88
89
  // src/actor/conn-drivers.ts
89
90
  var WEBSOCKET_DRIVER = {
@@ -139,15 +140,6 @@ var WEBSOCKET_DRIVER = {
139
140
  },
140
141
  getConnectionReadyState: (_actor, _conn, state) => {
141
142
  return state.websocket.readyState;
142
- },
143
- isHibernatable(_actor, _conn, state) {
144
- if (state.websocket.raw) {
145
- const raw = state.websocket.raw;
146
- if (typeof raw.isHibernatable === "boolean") {
147
- return raw.isHibernatable;
148
- }
149
- }
150
- return false;
151
143
  }
152
144
  };
153
145
  var SSE_DRIVER = {
@@ -164,9 +156,6 @@ var SSE_DRIVER = {
164
156
  return 3 /* CLOSED */;
165
157
  }
166
158
  return 1 /* OPEN */;
167
- },
168
- isHibernatable() {
169
- return false;
170
159
  }
171
160
  };
172
161
  var HTTP_DRIVER = {
@@ -174,9 +163,6 @@ var HTTP_DRIVER = {
174
163
  return 1 /* OPEN */;
175
164
  },
176
165
  disconnect: async () => {
177
- },
178
- isHibernatable() {
179
- return false;
180
166
  }
181
167
  };
182
168
  var CONN_DRIVERS = {
@@ -191,221 +177,8 @@ function getConnDriverKindFromState(state) {
191
177
  else assertUnreachable(state);
192
178
  }
193
179
 
194
- // src/actor/conn.ts
195
- function generateConnId() {
196
- return crypto.randomUUID();
197
- }
198
- function generateConnToken() {
199
- return generateSecureToken(32);
200
- }
201
- function generateConnRequestId() {
202
- return crypto.randomUUID();
203
- }
204
- var Conn = class {
205
- subscriptions = /* @__PURE__ */ new Set();
206
- // TODO: Remove this cyclical reference
207
- #actor;
208
- /**
209
- * The proxied state that notifies of changes automatically.
210
- *
211
- * Any data that should be stored indefinitely should be held within this object.
212
- */
213
- __persist;
214
- get __driverState() {
215
- var _a;
216
- return (_a = this.__socket) == null ? void 0 : _a.driverState;
217
- }
218
- /**
219
- * Socket connected to this connection.
220
- *
221
- * If undefined, then nothing is connected to this.
222
- */
223
- __socket;
224
- get __status() {
225
- if (this.__socket) {
226
- return "connected";
227
- } else {
228
- return "reconnecting";
229
- }
230
- }
231
- get params() {
232
- return this.__persist.params;
233
- }
234
- get __stateEnabled() {
235
- return this.#actor.connStateEnabled;
236
- }
237
- /**
238
- * Gets the current state of the connection.
239
- *
240
- * Throws an error if the state is not enabled.
241
- */
242
- get state() {
243
- this.#validateStateEnabled();
244
- if (!this.__persist.state) throw new Error("state should exists");
245
- return this.__persist.state;
246
- }
247
- /**
248
- * Sets the state of the connection.
249
- *
250
- * Throws an error if the state is not enabled.
251
- */
252
- set state(value) {
253
- this.#validateStateEnabled();
254
- this.__persist.state = value;
255
- }
256
- /**
257
- * Unique identifier for the connection.
258
- */
259
- get id() {
260
- return this.__persist.connId;
261
- }
262
- /**
263
- * Token used to authenticate this request.
264
- */
265
- get _token() {
266
- return this.__persist.token;
267
- }
268
- /**
269
- * Status of the connection.
270
- */
271
- get status() {
272
- return this.__status;
273
- }
274
- /**
275
- * @experimental
276
- *
277
- * If the underlying connection can hibernate.
278
- */
279
- get isHibernatable() {
280
- if (this.__driverState) {
281
- const driverKind = getConnDriverKindFromState(this.__driverState);
282
- const driver = CONN_DRIVERS[driverKind];
283
- return driver.isHibernatable(
284
- this.#actor,
285
- this,
286
- this.__driverState[driverKind]
287
- );
288
- } else {
289
- return false;
290
- }
291
- }
292
- /**
293
- * Timestamp of the last time the connection was seen, i.e. the last time the connection was active and checked for liveness.
294
- */
295
- get lastSeen() {
296
- return this.__persist.lastSeen;
297
- }
298
- /**
299
- * Initializes a new instance of the Connection class.
300
- *
301
- * This should only be constructed by {@link Actor}.
302
- *
303
- * @protected
304
- */
305
- constructor(actor, persist) {
306
- this.#actor = actor;
307
- this.__persist = persist;
308
- }
309
- #validateStateEnabled() {
310
- if (!this.__stateEnabled) {
311
- throw new ConnStateNotEnabled();
312
- }
313
- }
314
- /**
315
- * Sends a WebSocket message to the client.
316
- *
317
- * @param message - The message to send.
318
- *
319
- * @protected
320
- */
321
- _sendMessage(message) {
322
- if (this.__driverState) {
323
- const driverKind = getConnDriverKindFromState(this.__driverState);
324
- const driver = CONN_DRIVERS[driverKind];
325
- if (driver.sendMessage) {
326
- driver.sendMessage(
327
- this.#actor,
328
- this,
329
- this.__driverState[driverKind],
330
- message
331
- );
332
- } else {
333
- this.#actor.rLog.debug({
334
- msg: "conn driver does not support sending messages",
335
- conn: this.id
336
- });
337
- }
338
- } else {
339
- this.#actor.rLog.warn({
340
- msg: "missing connection driver state for send message",
341
- conn: this.id
342
- });
343
- }
344
- }
345
- /**
346
- * Sends an event with arguments to the client.
347
- *
348
- * @param eventName - The name of the event.
349
- * @param args - The arguments for the event.
350
- * @see {@link https://rivet.dev/docs/events|Events Documentation}
351
- */
352
- send(eventName, ...args) {
353
- this.#actor.inspector.emitter.emit("eventFired", {
354
- type: "event",
355
- eventName,
356
- args,
357
- connId: this.id
358
- });
359
- this._sendMessage(
360
- new CachedSerializer(
361
- {
362
- body: {
363
- tag: "Event",
364
- val: {
365
- name: eventName,
366
- args: bufferToArrayBuffer(cbor.encode(args))
367
- }
368
- }
369
- },
370
- TO_CLIENT_VERSIONED
371
- )
372
- );
373
- }
374
- /**
375
- * Disconnects the client with an optional reason.
376
- *
377
- * @param reason - The reason for disconnection.
378
- */
379
- async disconnect(reason) {
380
- if (this.__socket && this.__driverState) {
381
- const driverKind = getConnDriverKindFromState(this.__driverState);
382
- const driver = CONN_DRIVERS[driverKind];
383
- if (driver.disconnect) {
384
- driver.disconnect(
385
- this.#actor,
386
- this,
387
- this.__driverState[driverKind],
388
- reason
389
- );
390
- } else {
391
- this.#actor.rLog.debug({
392
- msg: "no disconnect handler for conn driver",
393
- conn: this.id
394
- });
395
- }
396
- this.#actor.__connDisconnected(this, true, this.__socket.requestId);
397
- } else {
398
- this.#actor.rLog.warn({
399
- msg: "missing connection driver state for disconnect",
400
- conn: this.id
401
- });
402
- }
403
- this.__socket = void 0;
404
- }
405
- };
406
-
407
180
  // src/actor/instance.ts
408
- import * as cbor2 from "cbor-x";
181
+ import * as cbor from "cbor-x";
409
182
  import invariant from "invariant";
410
183
  import onChange from "on-change";
411
184
 
@@ -930,21 +703,18 @@ var ActorInstance = class {
930
703
  },
931
704
  getConnections: async () => {
932
705
  return Array.from(this.#connections.entries()).map(
933
- ([id, conn]) => {
934
- var _a;
935
- return {
936
- id,
937
- params: conn.params,
938
- state: conn.__stateEnabled ? conn.state : void 0,
939
- status: conn.status,
940
- subscriptions: conn.subscriptions.size,
941
- lastSeen: conn.lastSeen,
942
- stateEnabled: conn.__stateEnabled,
943
- isHibernatable: conn.isHibernatable,
944
- requestId: (_a = conn.__socket) == null ? void 0 : _a.requestId,
945
- driver: conn.__driverState ? getConnDriverKindFromState(conn.__driverState) : void 0
946
- };
947
- }
706
+ ([id, conn]) => ({
707
+ id,
708
+ params: conn.params,
709
+ state: conn.__stateEnabled ? conn.state : void 0,
710
+ status: conn.status,
711
+ subscriptions: conn.subscriptions.size,
712
+ lastSeen: conn.lastSeen,
713
+ stateEnabled: conn.__stateEnabled,
714
+ isHibernatable: conn.isHibernatable,
715
+ hibernatableRequestId: conn.__persist.hibernatableRequestId ? idToStr(conn.__persist.hibernatableRequestId) : void 0,
716
+ driver: conn.__driverState ? getConnDriverKindFromState(conn.__driverState) : void 0
717
+ })
948
718
  );
949
719
  },
950
720
  setState: async (state) => {
@@ -957,6 +727,7 @@ var ActorInstance = class {
957
727
  const conn = await this.createConn(
958
728
  {
959
729
  requestId,
730
+ hibernatable: false,
960
731
  driverState: { [2 /* HTTP */]: {} }
961
732
  },
962
733
  void 0,
@@ -1167,7 +938,7 @@ var ActorInstance = class {
1167
938
  `Alarm function lookup for ${event.kind.generic.actionName} returned ${typeof fn}`
1168
939
  );
1169
940
  try {
1170
- const args = event.kind.generic.args ? cbor2.decode(new Uint8Array(event.kind.generic.args)) : [];
941
+ const args = event.kind.generic.args ? cbor.decode(new Uint8Array(event.kind.generic.args)) : [];
1171
942
  await fn.call(void 0, this.actorContext, ...args);
1172
943
  } catch (error) {
1173
944
  this.actorContext.log.error({
@@ -1194,7 +965,7 @@ var ActorInstance = class {
1194
965
  kind: {
1195
966
  generic: {
1196
967
  actionName: action,
1197
- args: bufferToArrayBuffer(cbor2.encode(args))
968
+ args: bufferToArrayBuffer(cbor.encode(args))
1198
969
  }
1199
970
  }
1200
971
  });
@@ -1260,6 +1031,10 @@ var ActorInstance = class {
1260
1031
  }
1261
1032
  (_a = this.#onPersistSavedPromise) == null ? void 0 : _a.resolve();
1262
1033
  } catch (error) {
1034
+ this.#rLog.error({
1035
+ msg: "error saving persist",
1036
+ error: stringifyError(error)
1037
+ });
1263
1038
  (_b = this.#onPersistSavedPromise) == null ? void 0 : _b.reject(error);
1264
1039
  throw error;
1265
1040
  }
@@ -1294,27 +1069,34 @@ var ActorInstance = class {
1294
1069
  target,
1295
1070
  // biome-ignore lint/suspicious/noExplicitAny: Don't know types in proxy
1296
1071
  (path, value, _previousValue, _applyData) => {
1297
- if (path !== "state" && !path.startsWith("state.")) {
1298
- return;
1299
- }
1300
- let invalidPath = "";
1301
- if (!isCborSerializable(
1302
- value,
1303
- (invalidPathPart) => {
1304
- invalidPath = invalidPathPart;
1305
- },
1306
- ""
1307
- )) {
1308
- throw new InvalidStateType({
1309
- path: path + (invalidPath ? `.${invalidPath}` : "")
1310
- });
1072
+ const actorStatePath = isStatePath(path);
1073
+ const connStatePath = isConnStatePath(path);
1074
+ if (actorStatePath || connStatePath) {
1075
+ let invalidPath = "";
1076
+ if (!isCborSerializable(
1077
+ value,
1078
+ (invalidPathPart) => {
1079
+ invalidPath = invalidPathPart;
1080
+ },
1081
+ ""
1082
+ )) {
1083
+ throw new InvalidStateType({
1084
+ path: path + (invalidPath ? `.${invalidPath}` : "")
1085
+ });
1086
+ }
1311
1087
  }
1088
+ this.#rLog.debug({
1089
+ msg: "onChange triggered, setting persistChanged=true",
1090
+ path
1091
+ });
1312
1092
  this.#persistChanged = true;
1313
- this.inspector.emitter.emit(
1314
- "stateUpdated",
1315
- this.#persist.state
1316
- );
1317
- if (this.#config.onStateChange && this.#ready && !this.#isInOnStateChange) {
1093
+ if (actorStatePath) {
1094
+ this.inspector.emitter.emit(
1095
+ "stateUpdated",
1096
+ this.#persist.state
1097
+ );
1098
+ }
1099
+ if (actorStatePath && this.#config.onStateChange && this.#ready && !this.#isInOnStateChange) {
1318
1100
  try {
1319
1101
  this.#isInOnStateChange = true;
1320
1102
  this.#config.onStateChange(
@@ -1349,7 +1131,8 @@ var ActorInstance = class {
1349
1131
  if (persistData.hasInitiated) {
1350
1132
  this.#rLog.info({
1351
1133
  msg: "actor restoring",
1352
- connections: persistData.connections.length
1134
+ connections: persistData.connections.length,
1135
+ hibernatableWebSockets: persistData.hibernatableWebSocket.length
1353
1136
  });
1354
1137
  this.#setPersist(persistData);
1355
1138
  for (const connPersist of this.#persist.connections) {
@@ -1480,6 +1263,55 @@ var ActorInstance = class {
1480
1263
  */
1481
1264
  async createConn(socket, params, request, connectionId, connectionToken) {
1482
1265
  this.#assertReady();
1266
+ if (socket.requestIdBuf && socket.hibernatable) {
1267
+ this.rLog.debug({
1268
+ msg: "checking for hibernatable websocket connection",
1269
+ requestId: socket.requestId,
1270
+ existingConnectionsCount: this.#connections.size
1271
+ });
1272
+ const existingConn = Array.from(this.#connections.values()).find(
1273
+ (conn2) => conn2.__persist.hibernatableRequestId && arrayBuffersEqual(
1274
+ conn2.__persist.hibernatableRequestId,
1275
+ socket.requestIdBuf
1276
+ )
1277
+ );
1278
+ if (existingConn) {
1279
+ this.rLog.debug({
1280
+ msg: "reconnecting hibernatable websocket connection",
1281
+ connectionId: existingConn.id,
1282
+ requestId: socket.requestId
1283
+ });
1284
+ if (existingConn.__driverState) {
1285
+ this.#rLog.warn({
1286
+ msg: "found existing driver state on hibernatable websocket",
1287
+ connectionId: existingConn.id,
1288
+ requestId: socket.requestId
1289
+ });
1290
+ const driverKind = getConnDriverKindFromState(
1291
+ existingConn.__driverState
1292
+ );
1293
+ const driver = CONN_DRIVERS[driverKind];
1294
+ if (driver.disconnect) {
1295
+ driver.disconnect(
1296
+ this,
1297
+ existingConn,
1298
+ existingConn.__driverState[driverKind],
1299
+ "Reconnecting hibernatable websocket with new driver state"
1300
+ );
1301
+ }
1302
+ }
1303
+ existingConn.__socket = socket;
1304
+ existingConn.__persist.lastSeen = Date.now();
1305
+ this.#resetSleepTimer();
1306
+ this.inspector.emitter.emit("connectionUpdated");
1307
+ return existingConn;
1308
+ } else {
1309
+ this.rLog.debug({
1310
+ msg: "no existing hibernatable connection found, creating new connection",
1311
+ requestId: socket.requestId
1312
+ });
1313
+ }
1314
+ }
1483
1315
  if (connectionId && connectionToken) {
1484
1316
  this.rLog.debug({
1485
1317
  msg: "checking for existing connection",
@@ -1525,11 +1357,12 @@ var ActorInstance = class {
1525
1357
  )
1526
1358
  );
1527
1359
  return existingConn;
1360
+ } else {
1361
+ this.rLog.debug({
1362
+ msg: "connection not found or token mismatch, creating new connection",
1363
+ connectionId
1364
+ });
1528
1365
  }
1529
- this.rLog.debug({
1530
- msg: "connection not found or token mismatch, creating new connection",
1531
- connectionId
1532
- });
1533
1366
  }
1534
1367
  const newConnId = generateConnId();
1535
1368
  const newConnToken = generateConnToken();
@@ -1578,6 +1411,14 @@ var ActorInstance = class {
1578
1411
  lastSeen: Date.now(),
1579
1412
  subscriptions: []
1580
1413
  };
1414
+ if (socket.requestIdBuf) {
1415
+ const isHibernatable = this.#persist.hibernatableWebSocket.findIndex(
1416
+ (ws) => arrayBuffersEqual(ws.requestId, socket.requestIdBuf)
1417
+ ) !== -1;
1418
+ if (isHibernatable) {
1419
+ persist.hibernatableRequestId = socket.requestIdBuf;
1420
+ }
1421
+ }
1581
1422
  const conn = new Conn(this, persist);
1582
1423
  conn.__socket = socket;
1583
1424
  this.#connections.set(conn.id, conn);
@@ -2117,7 +1958,7 @@ var ActorInstance = class {
2117
1958
  tag: "Event",
2118
1959
  val: {
2119
1960
  name,
2120
- args: bufferToArrayBuffer(cbor2.encode(args))
1961
+ args: bufferToArrayBuffer(cbor.encode(args))
2121
1962
  }
2122
1963
  }
2123
1964
  },
@@ -2157,6 +1998,12 @@ var ActorInstance = class {
2157
1998
  */
2158
1999
  async saveState(opts) {
2159
2000
  this.#assertReady(opts.allowStoppingState);
2001
+ this.#rLog.debug({
2002
+ msg: "saveState called",
2003
+ persistChanged: this.#persistChanged,
2004
+ allowStoppingState: opts.allowStoppingState,
2005
+ immediate: opts.immediate
2006
+ });
2160
2007
  if (this.#persistChanged) {
2161
2008
  if (opts.immediate) {
2162
2009
  await this.#savePersistInner();
@@ -2203,6 +2050,7 @@ var ActorInstance = class {
2203
2050
  **/
2204
2051
  #resetSleepTimer() {
2205
2052
  if (this.#config.options.noSleep || !this.#sleepingSupported) return;
2053
+ if (this.#stopCalled) return;
2206
2054
  const canSleep = this.#canSleep();
2207
2055
  this.#rLog.debug({
2208
2056
  msg: "resetting sleep timer",
@@ -2244,8 +2092,16 @@ var ActorInstance = class {
2244
2092
  **/
2245
2093
  _startSleep() {
2246
2094
  var _a;
2095
+ if (this.#stopCalled) {
2096
+ this.#rLog.debug({
2097
+ msg: "cannot call _startSleep if actor already stopping"
2098
+ });
2099
+ return;
2100
+ }
2247
2101
  if (this.#sleepCalled) {
2248
- this.#rLog.warn({ msg: "already sleeping actor" });
2102
+ this.#rLog.warn({
2103
+ msg: "cannot call _startSleep twice, actor already sleeping"
2104
+ });
2249
2105
  return;
2250
2106
  }
2251
2107
  this.#sleepCalled = true;
@@ -2303,13 +2159,18 @@ var ActorInstance = class {
2303
2159
  }
2304
2160
  const promises = [];
2305
2161
  for (const connection of this.#connections.values()) {
2306
- promises.push(connection.disconnect());
2162
+ if (!connection.isHibernatable) {
2163
+ this.#rLog.debug({
2164
+ msg: "disconnecting non-hibernatable connection on actor stop",
2165
+ connId: connection.id
2166
+ });
2167
+ promises.push(connection.disconnect());
2168
+ }
2307
2169
  }
2308
2170
  await this.#waitBackgroundPromises(
2309
2171
  this.#config.options.waitUntilTimeout
2310
2172
  );
2311
2173
  if (this.#pendingSaveTimeout) clearTimeout(this.#pendingSaveTimeout);
2312
- if (this.#sleepTimeout) clearTimeout(this.#sleepTimeout);
2313
2174
  if (this.#checkConnLivenessInterval)
2314
2175
  clearInterval(this.#checkConnLivenessInterval);
2315
2176
  await this.saveState({ immediate: true, allowStoppingState: true });
@@ -2359,18 +2220,19 @@ var ActorInstance = class {
2359
2220
  // MARK: BARE Conversion Helpers
2360
2221
  #convertToBarePersisted(persist) {
2361
2222
  return {
2362
- input: persist.input !== void 0 ? bufferToArrayBuffer(cbor2.encode(persist.input)) : null,
2223
+ input: persist.input !== void 0 ? bufferToArrayBuffer(cbor.encode(persist.input)) : null,
2363
2224
  hasInitialized: persist.hasInitiated,
2364
- state: bufferToArrayBuffer(cbor2.encode(persist.state)),
2225
+ state: bufferToArrayBuffer(cbor.encode(persist.state)),
2365
2226
  connections: persist.connections.map((conn) => ({
2366
2227
  id: conn.connId,
2367
2228
  token: conn.token,
2368
- parameters: bufferToArrayBuffer(cbor2.encode(conn.params || {})),
2369
- state: bufferToArrayBuffer(cbor2.encode(conn.state || {})),
2229
+ parameters: bufferToArrayBuffer(cbor.encode(conn.params || {})),
2230
+ state: bufferToArrayBuffer(cbor.encode(conn.state || {})),
2370
2231
  subscriptions: conn.subscriptions.map((sub) => ({
2371
2232
  eventName: sub.eventName
2372
2233
  })),
2373
- lastSeen: BigInt(conn.lastSeen)
2234
+ lastSeen: BigInt(conn.lastSeen),
2235
+ hibernatableRequestId: conn.hibernatableRequestId ?? null
2374
2236
  })),
2375
2237
  scheduledEvents: persist.scheduledEvents.map((event) => ({
2376
2238
  eventId: event.eventId,
@@ -2392,18 +2254,19 @@ var ActorInstance = class {
2392
2254
  }
2393
2255
  #convertFromBarePersisted(bareData) {
2394
2256
  return {
2395
- input: bareData.input ? cbor2.decode(new Uint8Array(bareData.input)) : void 0,
2257
+ input: bareData.input ? cbor.decode(new Uint8Array(bareData.input)) : void 0,
2396
2258
  hasInitiated: bareData.hasInitialized,
2397
- state: cbor2.decode(new Uint8Array(bareData.state)),
2259
+ state: cbor.decode(new Uint8Array(bareData.state)),
2398
2260
  connections: bareData.connections.map((conn) => ({
2399
2261
  connId: conn.id,
2400
2262
  token: conn.token,
2401
- params: cbor2.decode(new Uint8Array(conn.parameters)),
2402
- state: cbor2.decode(new Uint8Array(conn.state)),
2263
+ params: cbor.decode(new Uint8Array(conn.parameters)),
2264
+ state: cbor.decode(new Uint8Array(conn.state)),
2403
2265
  subscriptions: conn.subscriptions.map((sub) => ({
2404
2266
  eventName: sub.eventName
2405
2267
  })),
2406
- lastSeen: Number(conn.lastSeen)
2268
+ lastSeen: Number(conn.lastSeen),
2269
+ hibernatableRequestId: conn.hibernatableRequestId ?? void 0
2407
2270
  })),
2408
2271
  scheduledEvents: bareData.scheduledEvents.map((event) => ({
2409
2272
  eventId: event.eventId,
@@ -2424,6 +2287,217 @@ var ActorInstance = class {
2424
2287
  }
2425
2288
  };
2426
2289
 
2290
+ // src/actor/conn.ts
2291
+ function generateConnId() {
2292
+ return crypto.randomUUID();
2293
+ }
2294
+ function generateConnToken() {
2295
+ return generateSecureToken(32);
2296
+ }
2297
+ function generateConnRequestId() {
2298
+ return crypto.randomUUID();
2299
+ }
2300
+ var Conn = class {
2301
+ subscriptions = /* @__PURE__ */ new Set();
2302
+ // TODO: Remove this cyclical reference
2303
+ #actor;
2304
+ /**
2305
+ * The proxied state that notifies of changes automatically.
2306
+ *
2307
+ * Any data that should be stored indefinitely should be held within this object.
2308
+ */
2309
+ __persist;
2310
+ get __driverState() {
2311
+ var _a;
2312
+ return (_a = this.__socket) == null ? void 0 : _a.driverState;
2313
+ }
2314
+ /**
2315
+ * Socket connected to this connection.
2316
+ *
2317
+ * If undefined, then nothing is connected to this.
2318
+ */
2319
+ __socket;
2320
+ get __status() {
2321
+ if (this.__socket || this.isHibernatable) {
2322
+ return "connected";
2323
+ } else {
2324
+ return "reconnecting";
2325
+ }
2326
+ }
2327
+ get params() {
2328
+ return this.__persist.params;
2329
+ }
2330
+ get __stateEnabled() {
2331
+ return this.#actor.connStateEnabled;
2332
+ }
2333
+ /**
2334
+ * Gets the current state of the connection.
2335
+ *
2336
+ * Throws an error if the state is not enabled.
2337
+ */
2338
+ get state() {
2339
+ this.#validateStateEnabled();
2340
+ if (!this.__persist.state) throw new Error("state should exists");
2341
+ return this.__persist.state;
2342
+ }
2343
+ /**
2344
+ * Sets the state of the connection.
2345
+ *
2346
+ * Throws an error if the state is not enabled.
2347
+ */
2348
+ set state(value) {
2349
+ this.#validateStateEnabled();
2350
+ this.__persist.state = value;
2351
+ }
2352
+ /**
2353
+ * Unique identifier for the connection.
2354
+ */
2355
+ get id() {
2356
+ return this.__persist.connId;
2357
+ }
2358
+ /**
2359
+ * Token used to authenticate this request.
2360
+ */
2361
+ get _token() {
2362
+ return this.__persist.token;
2363
+ }
2364
+ /**
2365
+ * Status of the connection.
2366
+ */
2367
+ get status() {
2368
+ return this.__status;
2369
+ }
2370
+ /**
2371
+ * @experimental
2372
+ *
2373
+ * If the underlying connection can hibernate.
2374
+ */
2375
+ get isHibernatable() {
2376
+ if (!this.__persist.hibernatableRequestId) {
2377
+ return false;
2378
+ }
2379
+ return this.#actor[PERSIST_SYMBOL].hibernatableWebSocket.findIndex(
2380
+ (x) => arrayBuffersEqual(
2381
+ x.requestId,
2382
+ this.__persist.hibernatableRequestId
2383
+ )
2384
+ ) > -1;
2385
+ }
2386
+ /**
2387
+ * Timestamp of the last time the connection was seen, i.e. the last time the connection was active and checked for liveness.
2388
+ */
2389
+ get lastSeen() {
2390
+ return this.__persist.lastSeen;
2391
+ }
2392
+ /**
2393
+ * Initializes a new instance of the Connection class.
2394
+ *
2395
+ * This should only be constructed by {@link Actor}.
2396
+ *
2397
+ * @protected
2398
+ */
2399
+ constructor(actor, persist) {
2400
+ this.#actor = actor;
2401
+ this.__persist = persist;
2402
+ }
2403
+ #validateStateEnabled() {
2404
+ if (!this.__stateEnabled) {
2405
+ throw new ConnStateNotEnabled();
2406
+ }
2407
+ }
2408
+ /**
2409
+ * Sends a WebSocket message to the client.
2410
+ *
2411
+ * @param message - The message to send.
2412
+ *
2413
+ * @protected
2414
+ */
2415
+ _sendMessage(message) {
2416
+ if (this.__driverState) {
2417
+ const driverKind = getConnDriverKindFromState(this.__driverState);
2418
+ const driver = CONN_DRIVERS[driverKind];
2419
+ if (driver.sendMessage) {
2420
+ driver.sendMessage(
2421
+ this.#actor,
2422
+ this,
2423
+ this.__driverState[driverKind],
2424
+ message
2425
+ );
2426
+ } else {
2427
+ this.#actor.rLog.debug({
2428
+ msg: "conn driver does not support sending messages",
2429
+ conn: this.id
2430
+ });
2431
+ }
2432
+ } else {
2433
+ this.#actor.rLog.warn({
2434
+ msg: "missing connection driver state for send message",
2435
+ conn: this.id
2436
+ });
2437
+ }
2438
+ }
2439
+ /**
2440
+ * Sends an event with arguments to the client.
2441
+ *
2442
+ * @param eventName - The name of the event.
2443
+ * @param args - The arguments for the event.
2444
+ * @see {@link https://rivet.dev/docs/events|Events Documentation}
2445
+ */
2446
+ send(eventName, ...args) {
2447
+ this.#actor.inspector.emitter.emit("eventFired", {
2448
+ type: "event",
2449
+ eventName,
2450
+ args,
2451
+ connId: this.id
2452
+ });
2453
+ this._sendMessage(
2454
+ new CachedSerializer(
2455
+ {
2456
+ body: {
2457
+ tag: "Event",
2458
+ val: {
2459
+ name: eventName,
2460
+ args: bufferToArrayBuffer(cbor2.encode(args))
2461
+ }
2462
+ }
2463
+ },
2464
+ TO_CLIENT_VERSIONED
2465
+ )
2466
+ );
2467
+ }
2468
+ /**
2469
+ * Disconnects the client with an optional reason.
2470
+ *
2471
+ * @param reason - The reason for disconnection.
2472
+ */
2473
+ async disconnect(reason) {
2474
+ if (this.__socket && this.__driverState) {
2475
+ const driverKind = getConnDriverKindFromState(this.__driverState);
2476
+ const driver = CONN_DRIVERS[driverKind];
2477
+ if (driver.disconnect) {
2478
+ driver.disconnect(
2479
+ this.#actor,
2480
+ this,
2481
+ this.__driverState[driverKind],
2482
+ reason
2483
+ );
2484
+ } else {
2485
+ this.#actor.rLog.debug({
2486
+ msg: "no disconnect handler for conn driver",
2487
+ conn: this.id
2488
+ });
2489
+ }
2490
+ this.#actor.__connDisconnected(this, true, this.__socket.requestId);
2491
+ } else {
2492
+ this.#actor.rLog.warn({
2493
+ msg: "missing connection driver state for disconnect",
2494
+ conn: this.id
2495
+ });
2496
+ }
2497
+ this.__socket = void 0;
2498
+ }
2499
+ };
2500
+
2427
2501
  // src/actor/definition.ts
2428
2502
  var ActorDefinition = class {
2429
2503
  #config;
@@ -4524,13 +4598,13 @@ var RemoteManagerDriver = class {
4524
4598
  };
4525
4599
 
4526
4600
  export {
4527
- generateConnId,
4528
- generateConnToken,
4529
- generateConnRequestId,
4530
4601
  createActorInspectorRouter,
4531
4602
  serializeActorKey,
4532
4603
  deserializeActorKey,
4533
4604
  PERSIST_SYMBOL,
4605
+ generateConnId,
4606
+ generateConnToken,
4607
+ generateConnRequestId,
4534
4608
  ActorDefinition,
4535
4609
  lookupInRegistry,
4536
4610
  ActorClientError,
@@ -4546,4 +4620,4 @@ export {
4546
4620
  updateRunnerConfig,
4547
4621
  RemoteManagerDriver
4548
4622
  };
4549
- //# sourceMappingURL=chunk-AMK3AACS.js.map
4623
+ //# sourceMappingURL=chunk-FTQ62XTN.js.map