@replit/river 0.25.1 → 0.26.0

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 (54) hide show
  1. package/dist/{chunk-D5O3ERJU.js → chunk-5FDAIAQ5.js} +3 -3
  2. package/dist/chunk-5FDAIAQ5.js.map +1 -0
  3. package/dist/{chunk-5CNNIOAO.js → chunk-5S64PXTU.js} +102 -95
  4. package/dist/chunk-5S64PXTU.js.map +1 -0
  5. package/dist/{chunk-PCBPPTXH.js → chunk-7ETNUCOL.js} +54 -62
  6. package/dist/chunk-7ETNUCOL.js.map +1 -0
  7. package/dist/{chunk-SGSRNAWJ.js → chunk-BNNELZM4.js} +2 -2
  8. package/dist/{chunk-SGSRNAWJ.js.map → chunk-BNNELZM4.js.map} +1 -1
  9. package/dist/{chunk-SZ5NBBX7.js → chunk-CCUYKR5C.js} +14 -4
  10. package/dist/chunk-CCUYKR5C.js.map +1 -0
  11. package/dist/{chunk-YM5Y4NAT.js → chunk-JSU2KACV.js} +199 -117
  12. package/dist/chunk-JSU2KACV.js.map +1 -0
  13. package/dist/{chunk-MBMEJIPU.js → chunk-KP4UB5NW.js} +2 -2
  14. package/dist/{client-1321630c.d.ts → client-162c509c.d.ts} +4 -2
  15. package/dist/{connection-bd907ca6.d.ts → connection-6a404bb8.d.ts} +1 -1
  16. package/dist/{handshake-3772d7ca.d.ts → handshake-3342bb94.d.ts} +132 -84
  17. package/dist/logging/index.d.cts +1 -1
  18. package/dist/logging/index.d.ts +1 -1
  19. package/dist/{message-e6c560fd.d.ts → message-1a434848.d.ts} +2 -1
  20. package/dist/router/index.cjs +12 -3
  21. package/dist/router/index.cjs.map +1 -1
  22. package/dist/router/index.d.cts +8 -8
  23. package/dist/router/index.d.ts +8 -8
  24. package/dist/router/index.js +2 -2
  25. package/dist/{server-f0fd2b98.d.ts → server-1b695374.d.ts} +9 -4
  26. package/dist/{services-8d14ae16.d.ts → services-c17f7eff.d.ts} +3 -3
  27. package/dist/transport/impls/ws/client.cjs +302 -207
  28. package/dist/transport/impls/ws/client.cjs.map +1 -1
  29. package/dist/transport/impls/ws/client.d.cts +4 -4
  30. package/dist/transport/impls/ws/client.d.ts +4 -4
  31. package/dist/transport/impls/ws/client.js +5 -5
  32. package/dist/transport/impls/ws/server.cjs +253 -174
  33. package/dist/transport/impls/ws/server.cjs.map +1 -1
  34. package/dist/transport/impls/ws/server.d.cts +4 -4
  35. package/dist/transport/impls/ws/server.d.ts +4 -4
  36. package/dist/transport/impls/ws/server.js +5 -5
  37. package/dist/transport/index.cjs +351 -264
  38. package/dist/transport/index.cjs.map +1 -1
  39. package/dist/transport/index.d.cts +4 -4
  40. package/dist/transport/index.d.ts +4 -4
  41. package/dist/transport/index.js +5 -5
  42. package/dist/util/testHelpers.cjs +208 -117
  43. package/dist/util/testHelpers.cjs.map +1 -1
  44. package/dist/util/testHelpers.d.cts +6 -5
  45. package/dist/util/testHelpers.d.ts +6 -5
  46. package/dist/util/testHelpers.js +6 -3
  47. package/dist/util/testHelpers.js.map +1 -1
  48. package/package.json +14 -13
  49. package/dist/chunk-5CNNIOAO.js.map +0 -1
  50. package/dist/chunk-D5O3ERJU.js.map +0 -1
  51. package/dist/chunk-PCBPPTXH.js.map +0 -1
  52. package/dist/chunk-SZ5NBBX7.js.map +0 -1
  53. package/dist/chunk-YM5Y4NAT.js.map +0 -1
  54. /package/dist/{chunk-MBMEJIPU.js.map → chunk-KP4UB5NW.js.map} +0 -0
@@ -183,7 +183,7 @@ var defaultTransportOptions = {
183
183
  codec: NaiveJsonCodec
184
184
  };
185
185
  var defaultConnectionRetryOptions = {
186
- baseIntervalMs: 250,
186
+ baseIntervalMs: 150,
187
187
  maxJitterMs: 200,
188
188
  maxBackoffMs: 32e3,
189
189
  attemptBudgetCapacity: 5,
@@ -255,11 +255,20 @@ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
255
255
  var HandshakeErrorRetriableResponseCodes = import_typebox.Type.Union([
256
256
  import_typebox.Type.Literal("SESSION_STATE_MISMATCH")
257
257
  ]);
258
+ var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox.Type.Union([
259
+ // The custom validation handler rejected the handler because the client is unsupported.
260
+ import_typebox.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
261
+ // The custom validation handler rejected the handshake.
262
+ import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
263
+ ]);
258
264
  var HandshakeErrorFatalResponseCodes = import_typebox.Type.Union([
265
+ HandshakeErrorCustomHandlerFatalResponseCodes,
266
+ // The ciient sent a handshake that doesn't comply with the extended handshake metadata.
259
267
  import_typebox.Type.Literal("MALFORMED_HANDSHAKE_META"),
268
+ // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
260
269
  import_typebox.Type.Literal("MALFORMED_HANDSHAKE"),
261
- import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH"),
262
- import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
270
+ // The client's protocol version does not match the server's.
271
+ import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH")
263
272
  ]);
264
273
  var HandshakeErrorResponseCodes = import_typebox.Type.Union([
265
274
  HandshakeErrorRetriableResponseCodes,
@@ -343,6 +352,7 @@ function isAck(controlFlag) {
343
352
  var import_value = require("@sinclair/typebox/value");
344
353
  var SessionState = /* @__PURE__ */ ((SessionState2) => {
345
354
  SessionState2["NoConnection"] = "NoConnection";
355
+ SessionState2["BackingOff"] = "BackingOff";
346
356
  SessionState2["Connecting"] = "Connecting";
347
357
  SessionState2["Handshaking"] = "Handshaking";
348
358
  SessionState2["Connected"] = "Connected";
@@ -400,7 +410,7 @@ var CommonSession = class extends StateMachineState {
400
410
  from;
401
411
  options;
402
412
  log;
403
- constructor(from, options, log) {
413
+ constructor({ from, options, log }) {
404
414
  super();
405
415
  this.from = from;
406
416
  this.options = options;
@@ -441,8 +451,9 @@ var IdentifiedSession = class extends CommonSession {
441
451
  */
442
452
  ack;
443
453
  sendBuffer;
444
- constructor(id, from, to, seq, ack, sendBuffer, telemetry, options, log) {
445
- super(from, options, log);
454
+ constructor(props) {
455
+ const { id, to, seq, ack, sendBuffer, telemetry, log } = props;
456
+ super(props);
446
457
  this.id = id;
447
458
  this.to = to;
448
459
  this.seq = seq;
@@ -497,23 +508,23 @@ var SessionConnecting = class extends IdentifiedSession {
497
508
  connPromise;
498
509
  listeners;
499
510
  connectionTimeout;
500
- constructor(connPromise, listeners, ...args) {
501
- super(...args);
502
- this.connPromise = connPromise;
503
- this.listeners = listeners;
511
+ constructor(props) {
512
+ super(props);
513
+ this.connPromise = props.connPromise;
514
+ this.listeners = props.listeners;
504
515
  this.connectionTimeout = setTimeout(() => {
505
- listeners.onConnectionTimeout();
516
+ this.listeners.onConnectionTimeout();
506
517
  }, this.options.connectionTimeoutMs);
507
- connPromise.then(
518
+ this.connPromise.then(
508
519
  (conn) => {
509
520
  if (this._isConsumed)
510
521
  return;
511
- listeners.onConnectionEstablished(conn);
522
+ this.listeners.onConnectionEstablished(conn);
512
523
  },
513
524
  (err) => {
514
525
  if (this._isConsumed)
515
526
  return;
516
- listeners.onConnectionFailed(err);
527
+ this.listeners.onConnectionFailed(err);
517
528
  }
518
529
  );
519
530
  }
@@ -539,9 +550,9 @@ var SessionNoConnection = class extends IdentifiedSession {
539
550
  state = "NoConnection" /* NoConnection */;
540
551
  listeners;
541
552
  gracePeriodTimeout;
542
- constructor(listeners, ...args) {
543
- super(...args);
544
- this.listeners = listeners;
553
+ constructor(props) {
554
+ super(props);
555
+ this.listeners = props.listeners;
545
556
  this.gracePeriodTimeout = setTimeout(() => {
546
557
  this.listeners.onSessionGracePeriodElapsed();
547
558
  }, this.options.sessionDisconnectGraceMs);
@@ -562,7 +573,7 @@ var SessionNoConnection = class extends IdentifiedSession {
562
573
  var import_api = require("@opentelemetry/api");
563
574
 
564
575
  // package.json
565
- var version = "0.25.1";
576
+ var version = "0.26.0";
566
577
 
567
578
  // tracing/index.ts
568
579
  function getPropagationContext(ctx) {
@@ -599,16 +610,16 @@ var SessionWaitingForHandshake = class extends CommonSession {
599
610
  conn;
600
611
  listeners;
601
612
  handshakeTimeout;
602
- constructor(conn, listeners, ...args) {
603
- super(...args);
604
- this.conn = conn;
605
- this.listeners = listeners;
613
+ constructor(props) {
614
+ super(props);
615
+ this.conn = props.conn;
616
+ this.listeners = props.listeners;
606
617
  this.handshakeTimeout = setTimeout(() => {
607
- listeners.onHandshakeTimeout();
618
+ this.listeners.onHandshakeTimeout();
608
619
  }, this.options.handshakeTimeoutMs);
609
620
  this.conn.addDataListener(this.onHandshakeData);
610
- this.conn.addErrorListener(listeners.onConnectionErrored);
611
- this.conn.addCloseListener(listeners.onConnectionClosed);
621
+ this.conn.addErrorListener(this.listeners.onConnectionErrored);
622
+ this.conn.addCloseListener(this.listeners.onConnectionClosed);
612
623
  }
613
624
  onHandshakeData = (msg) => {
614
625
  const parsedMsg = this.parseMsg(msg);
@@ -645,16 +656,16 @@ var SessionHandshaking = class extends IdentifiedSession {
645
656
  conn;
646
657
  listeners;
647
658
  handshakeTimeout;
648
- constructor(conn, listeners, ...args) {
649
- super(...args);
650
- this.conn = conn;
651
- this.listeners = listeners;
659
+ constructor(props) {
660
+ super(props);
661
+ this.conn = props.conn;
662
+ this.listeners = props.listeners;
652
663
  this.handshakeTimeout = setTimeout(() => {
653
- listeners.onHandshakeTimeout();
664
+ this.listeners.onHandshakeTimeout();
654
665
  }, this.options.handshakeTimeoutMs);
655
666
  this.conn.addDataListener(this.onHandshakeData);
656
- this.conn.addErrorListener(listeners.onConnectionErrored);
657
- this.conn.addCloseListener(listeners.onConnectionClosed);
667
+ this.conn.addErrorListener(this.listeners.onConnectionErrored);
668
+ this.conn.addCloseListener(this.listeners.onConnectionClosed);
658
669
  }
659
670
  onHandshakeData = (msg) => {
660
671
  const parsedMsg = this.parseMsg(msg);
@@ -686,16 +697,13 @@ var SessionConnected = class extends IdentifiedSession {
686
697
  state = "Connected" /* Connected */;
687
698
  conn;
688
699
  listeners;
689
- activeHeartbeatHandle;
690
- activeHeartbeatMisses = 0;
691
- passiveHeartbeatHandle;
692
- get isActivelyHeartbeating() {
693
- return this.activeHeartbeatHandle !== void 0;
694
- }
700
+ heartbeatHandle;
701
+ heartbeatMisses = 0;
702
+ isActivelyHeartbeating;
695
703
  updateBookkeeping(ack, seq) {
696
704
  this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
697
705
  this.ack = seq + 1;
698
- this.activeHeartbeatMisses = 0;
706
+ this.heartbeatMisses = 0;
699
707
  }
700
708
  send(msg) {
701
709
  const constructedMsg = this.constructMsg(msg);
@@ -703,13 +711,13 @@ var SessionConnected = class extends IdentifiedSession {
703
711
  this.conn.send(this.options.codec.toBuffer(constructedMsg));
704
712
  return constructedMsg.id;
705
713
  }
706
- constructor(conn, listeners, ...args) {
707
- super(...args);
708
- this.conn = conn;
709
- this.listeners = listeners;
714
+ constructor(props) {
715
+ super(props);
716
+ this.conn = props.conn;
717
+ this.listeners = props.listeners;
710
718
  this.conn.addDataListener(this.onMessageData);
711
- this.conn.addCloseListener(listeners.onConnectionClosed);
712
- this.conn.addErrorListener(listeners.onConnectionErrored);
719
+ this.conn.addCloseListener(this.listeners.onConnectionClosed);
720
+ this.conn.addErrorListener(this.listeners.onConnectionErrored);
713
721
  if (this.sendBuffer.length > 0) {
714
722
  this.log?.debug(
715
723
  `sending ${this.sendBuffer.length} buffered messages`,
@@ -717,12 +725,11 @@ var SessionConnected = class extends IdentifiedSession {
717
725
  );
718
726
  }
719
727
  for (const msg of this.sendBuffer) {
720
- conn.send(this.options.codec.toBuffer(msg));
728
+ this.conn.send(this.options.codec.toBuffer(msg));
721
729
  }
722
- }
723
- startActiveHeartbeat() {
724
- this.activeHeartbeatHandle = setInterval(() => {
725
- const misses = this.activeHeartbeatMisses;
730
+ this.isActivelyHeartbeating = false;
731
+ this.heartbeatHandle = setInterval(() => {
732
+ const misses = this.heartbeatMisses;
726
733
  const missDuration = misses * this.options.heartbeatIntervalMs;
727
734
  if (misses >= this.options.heartbeatsUntilDead) {
728
735
  this.log?.info(
@@ -731,29 +738,18 @@ var SessionConnected = class extends IdentifiedSession {
731
738
  );
732
739
  this.telemetry.span.addEvent("closing connection due to inactivity");
733
740
  this.conn.close();
734
- clearInterval(this.activeHeartbeatHandle);
735
- this.activeHeartbeatHandle = void 0;
741
+ clearInterval(this.heartbeatHandle);
742
+ this.heartbeatHandle = void 0;
736
743
  return;
737
744
  }
738
- this.sendHeartbeat();
739
- this.activeHeartbeatMisses++;
745
+ if (this.isActivelyHeartbeating) {
746
+ this.sendHeartbeat();
747
+ }
748
+ this.heartbeatMisses++;
740
749
  }, this.options.heartbeatIntervalMs);
741
750
  }
742
- waitForNextHeartbeat() {
743
- const duration = this.options.heartbeatsUntilDead * this.options.heartbeatIntervalMs;
744
- if (this.passiveHeartbeatHandle) {
745
- clearTimeout(this.passiveHeartbeatHandle);
746
- this.passiveHeartbeatHandle = void 0;
747
- }
748
- this.passiveHeartbeatHandle = setTimeout(() => {
749
- this.log?.info(
750
- `closing connection to ${this.to} due to not receiving a heartbeat in the last ${duration}ms`,
751
- this.loggingMetadata
752
- );
753
- this.telemetry.span.addEvent("closing connection due to inactivity");
754
- this.conn.close();
755
- this.passiveHeartbeatHandle = void 0;
756
- }, duration);
751
+ startActiveHeartbeat() {
752
+ this.isActivelyHeartbeating = true;
757
753
  }
758
754
  sendHeartbeat() {
759
755
  this.log?.debug("sending heartbeat", this.loggingMetadata);
@@ -808,7 +804,6 @@ var SessionConnected = class extends IdentifiedSession {
808
804
  });
809
805
  if (!this.isActivelyHeartbeating) {
810
806
  this.sendHeartbeat();
811
- this.waitForNextHeartbeat();
812
807
  }
813
808
  };
814
809
  _handleStateExit() {
@@ -816,10 +811,8 @@ var SessionConnected = class extends IdentifiedSession {
816
811
  this.conn.removeDataListener(this.onMessageData);
817
812
  this.conn.removeCloseListener(this.listeners.onConnectionClosed);
818
813
  this.conn.removeErrorListener(this.listeners.onConnectionErrored);
819
- clearInterval(this.activeHeartbeatHandle);
820
- clearTimeout(this.passiveHeartbeatHandle);
821
- this.activeHeartbeatHandle = void 0;
822
- this.passiveHeartbeatHandle = void 0;
814
+ clearInterval(this.heartbeatHandle);
815
+ this.heartbeatHandle = void 0;
823
816
  }
824
817
  _handleClose() {
825
818
  super._handleClose();
@@ -827,52 +820,76 @@ var SessionConnected = class extends IdentifiedSession {
827
820
  }
828
821
  };
829
822
 
823
+ // transport/sessionStateMachine/SessionBackingOff.ts
824
+ var SessionBackingOff = class extends IdentifiedSession {
825
+ state = "BackingOff" /* BackingOff */;
826
+ listeners;
827
+ backoffTimeout;
828
+ constructor(props) {
829
+ super(props);
830
+ this.listeners = props.listeners;
831
+ this.backoffTimeout = setTimeout(() => {
832
+ this.listeners.onBackoffFinished();
833
+ }, props.backoffMs);
834
+ }
835
+ _handleClose() {
836
+ super._handleClose();
837
+ }
838
+ _handleStateExit() {
839
+ super._handleStateExit();
840
+ if (this.backoffTimeout) {
841
+ clearTimeout(this.backoffTimeout);
842
+ this.backoffTimeout = void 0;
843
+ }
844
+ }
845
+ };
846
+
830
847
  // transport/sessionStateMachine/transitions.ts
831
848
  function inheritSharedSession(session) {
832
- return [
833
- session.id,
834
- session.from,
835
- session.to,
836
- session.seq,
837
- session.ack,
838
- session.sendBuffer,
839
- session.telemetry,
840
- session.options,
841
- session.log
842
- ];
849
+ return {
850
+ id: session.id,
851
+ from: session.from,
852
+ to: session.to,
853
+ seq: session.seq,
854
+ ack: session.ack,
855
+ sendBuffer: session.sendBuffer,
856
+ telemetry: session.telemetry,
857
+ options: session.options,
858
+ log: session.log
859
+ };
843
860
  }
844
861
  var SessionStateGraph = {
845
862
  entrypoints: {
846
- NoConnection(to, from, listeners, options, log) {
863
+ NoConnection: (to, from, listeners, options, log) => {
847
864
  const id = `session-${generateId()}`;
848
865
  const telemetry = createSessionTelemetryInfo(id, to, from);
849
866
  const sendBuffer = [];
850
- const session = new SessionNoConnection(
867
+ const session = new SessionNoConnection({
851
868
  listeners,
852
869
  id,
853
870
  from,
854
871
  to,
855
- 0,
856
- 0,
872
+ seq: 0,
873
+ ack: 0,
857
874
  sendBuffer,
858
875
  telemetry,
859
876
  options,
860
877
  log
861
- );
878
+ });
862
879
  session.log?.info(`session ${session.id} created in NoConnection state`, {
863
880
  ...session.loggingMetadata,
864
881
  tags: ["state-transition"]
865
882
  });
866
883
  return session;
867
884
  },
868
- WaitingForHandshake(from, conn, listeners, options, log) {
869
- const session = new SessionWaitingForHandshake(
885
+ WaitingForHandshake: (from, conn, listeners, options, log) => {
886
+ const session = new SessionWaitingForHandshake({
870
887
  conn,
871
888
  listeners,
872
889
  from,
873
890
  options,
874
891
  log
875
- );
892
+ });
876
893
  session.log?.info(`session created in WaitingForHandshake state`, {
877
894
  ...session.loggingMetadata,
878
895
  tags: ["state-transition"]
@@ -884,16 +901,33 @@ var SessionStateGraph = {
884
901
  // After a session is transitioned, any usage of the old session will throw.
885
902
  transition: {
886
903
  // happy path transitions
887
- NoConnectionToConnecting(oldSession, connPromise, listeners) {
904
+ NoConnectionToBackingOff: (oldSession, backoffMs, listeners) => {
888
905
  const carriedState = inheritSharedSession(oldSession);
889
906
  oldSession._handleStateExit();
890
- const session = new SessionConnecting(
891
- connPromise,
907
+ const session = new SessionBackingOff({
908
+ backoffMs,
892
909
  listeners,
893
910
  ...carriedState
911
+ });
912
+ session.log?.info(
913
+ `session ${session.id} transition from NoConnection to BackingOff`,
914
+ {
915
+ ...session.loggingMetadata,
916
+ tags: ["state-transition"]
917
+ }
894
918
  );
919
+ return session;
920
+ },
921
+ BackingOffToConnecting: (oldSession, connPromise, listeners) => {
922
+ const carriedState = inheritSharedSession(oldSession);
923
+ oldSession._handleStateExit();
924
+ const session = new SessionConnecting({
925
+ connPromise,
926
+ listeners,
927
+ ...carriedState
928
+ });
895
929
  session.log?.info(
896
- `session ${session.id} transition from NoConnection to Connecting`,
930
+ `session ${session.id} transition from BackingOff to Connecting`,
897
931
  {
898
932
  ...session.loggingMetadata,
899
933
  tags: ["state-transition"]
@@ -901,10 +935,14 @@ var SessionStateGraph = {
901
935
  );
902
936
  return session;
903
937
  },
904
- ConnectingToHandshaking(oldSession, conn, listeners) {
938
+ ConnectingToHandshaking: (oldSession, conn, listeners) => {
905
939
  const carriedState = inheritSharedSession(oldSession);
906
940
  oldSession._handleStateExit();
907
- const session = new SessionHandshaking(conn, listeners, ...carriedState);
941
+ const session = new SessionHandshaking({
942
+ conn,
943
+ listeners,
944
+ ...carriedState
945
+ });
908
946
  session.log?.info(
909
947
  `session ${session.id} transition from Connecting to Handshaking`,
910
948
  {
@@ -914,11 +952,15 @@ var SessionStateGraph = {
914
952
  );
915
953
  return session;
916
954
  },
917
- HandshakingToConnected(oldSession, listeners) {
955
+ HandshakingToConnected: (oldSession, listeners) => {
918
956
  const carriedState = inheritSharedSession(oldSession);
919
957
  const conn = oldSession.conn;
920
958
  oldSession._handleStateExit();
921
- const session = new SessionConnected(conn, listeners, ...carriedState);
959
+ const session = new SessionConnected({
960
+ conn,
961
+ listeners,
962
+ ...carriedState
963
+ });
922
964
  session.log?.info(
923
965
  `session ${session.id} transition from Handshaking to Connected`,
924
966
  {
@@ -928,7 +970,7 @@ var SessionStateGraph = {
928
970
  );
929
971
  return session;
930
972
  },
931
- WaitingForHandshakeToConnected(pendingSession, oldSession, sessionId, to, propagationCtx, listeners) {
973
+ WaitingForHandshakeToConnected: (pendingSession, oldSession, sessionId, to, propagationCtx, listeners) => {
932
974
  const conn = pendingSession.conn;
933
975
  const { from, options } = pendingSession;
934
976
  const carriedState = oldSession ? (
@@ -936,21 +978,30 @@ var SessionStateGraph = {
936
978
  inheritSharedSession(oldSession)
937
979
  ) : (
938
980
  // old session does not exist, create new state
939
- [
940
- sessionId,
981
+ {
982
+ id: sessionId,
941
983
  from,
942
984
  to,
943
- 0,
944
- 0,
945
- [],
946
- createSessionTelemetryInfo(sessionId, to, from, propagationCtx),
985
+ seq: 0,
986
+ ack: 0,
987
+ sendBuffer: [],
988
+ telemetry: createSessionTelemetryInfo(
989
+ sessionId,
990
+ to,
991
+ from,
992
+ propagationCtx
993
+ ),
947
994
  options,
948
- pendingSession.log
949
- ]
995
+ log: pendingSession.log
996
+ }
950
997
  );
951
998
  pendingSession._handleStateExit();
952
999
  oldSession?._handleStateExit();
953
- const session = new SessionConnected(conn, listeners, ...carriedState);
1000
+ const session = new SessionConnected({
1001
+ conn,
1002
+ listeners,
1003
+ ...carriedState
1004
+ });
954
1005
  session.log?.info(
955
1006
  `session ${session.id} transition from WaitingForHandshake to Connected`,
956
1007
  {
@@ -961,11 +1012,24 @@ var SessionStateGraph = {
961
1012
  return session;
962
1013
  },
963
1014
  // disconnect paths
964
- ConnectingToNoConnection(oldSession, listeners) {
1015
+ BackingOffToNoConnection: (oldSession, listeners) => {
1016
+ const carriedState = inheritSharedSession(oldSession);
1017
+ oldSession._handleStateExit();
1018
+ const session = new SessionNoConnection({ listeners, ...carriedState });
1019
+ session.log?.info(
1020
+ `session ${session.id} transition from BackingOff to NoConnection`,
1021
+ {
1022
+ ...session.loggingMetadata,
1023
+ tags: ["state-transition"]
1024
+ }
1025
+ );
1026
+ return session;
1027
+ },
1028
+ ConnectingToNoConnection: (oldSession, listeners) => {
965
1029
  const carriedState = inheritSharedSession(oldSession);
966
1030
  oldSession.bestEffortClose();
967
1031
  oldSession._handleStateExit();
968
- const session = new SessionNoConnection(listeners, ...carriedState);
1032
+ const session = new SessionNoConnection({ listeners, ...carriedState });
969
1033
  session.log?.info(
970
1034
  `session ${session.id} transition from Connecting to NoConnection`,
971
1035
  {
@@ -975,11 +1039,11 @@ var SessionStateGraph = {
975
1039
  );
976
1040
  return session;
977
1041
  },
978
- HandshakingToNoConnection(oldSession, listeners) {
1042
+ HandshakingToNoConnection: (oldSession, listeners) => {
979
1043
  const carriedState = inheritSharedSession(oldSession);
980
1044
  oldSession.conn.close();
981
1045
  oldSession._handleStateExit();
982
- const session = new SessionNoConnection(listeners, ...carriedState);
1046
+ const session = new SessionNoConnection({ listeners, ...carriedState });
983
1047
  session.log?.info(
984
1048
  `session ${session.id} transition from Handshaking to NoConnection`,
985
1049
  {
@@ -989,11 +1053,11 @@ var SessionStateGraph = {
989
1053
  );
990
1054
  return session;
991
1055
  },
992
- ConnectedToNoConnection(oldSession, listeners) {
1056
+ ConnectedToNoConnection: (oldSession, listeners) => {
993
1057
  const carriedState = inheritSharedSession(oldSession);
994
1058
  oldSession.conn.close();
995
1059
  oldSession._handleStateExit();
996
- const session = new SessionNoConnection(listeners, ...carriedState);
1060
+ const session = new SessionNoConnection({ listeners, ...carriedState });
997
1061
  session.log?.info(
998
1062
  `session ${session.id} transition from Connected to NoConnection`,
999
1063
  {
@@ -1005,6 +1069,31 @@ var SessionStateGraph = {
1005
1069
  }
1006
1070
  }
1007
1071
  };
1072
+ var transitions = SessionStateGraph.transition;
1073
+ var ClientSessionStateGraph = {
1074
+ entrypoint: SessionStateGraph.entrypoints.NoConnection,
1075
+ transition: {
1076
+ // happy paths
1077
+ NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,
1078
+ BackingOffToConnecting: transitions.BackingOffToConnecting,
1079
+ ConnectingToHandshaking: transitions.ConnectingToHandshaking,
1080
+ HandshakingToConnected: transitions.HandshakingToConnected,
1081
+ // disconnect paths
1082
+ BackingOffToNoConnection: transitions.BackingOffToNoConnection,
1083
+ ConnectingToNoConnection: transitions.ConnectingToNoConnection,
1084
+ HandshakingToNoConnection: transitions.HandshakingToNoConnection,
1085
+ ConnectedToNoConnection: transitions.ConnectedToNoConnection
1086
+ }
1087
+ };
1088
+ var ServerSessionStateGraph = {
1089
+ entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,
1090
+ transition: {
1091
+ // happy paths
1092
+ WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,
1093
+ // disconnect paths
1094
+ ConnectedToNoConnection: transitions.ConnectedToNoConnection
1095
+ }
1096
+ };
1008
1097
 
1009
1098
  // transport/transport.ts
1010
1099
  var Transport = class {
@@ -1163,17 +1252,17 @@ var import_api3 = require("@opentelemetry/api");
1163
1252
  // transport/rateLimit.ts
1164
1253
  var LeakyBucketRateLimit = class {
1165
1254
  budgetConsumed;
1166
- intervalHandles;
1255
+ intervalHandle;
1167
1256
  options;
1168
1257
  constructor(options) {
1169
1258
  this.options = options;
1170
- this.budgetConsumed = /* @__PURE__ */ new Map();
1171
- this.intervalHandles = /* @__PURE__ */ new Map();
1259
+ this.budgetConsumed = 0;
1172
1260
  }
1173
- getBackoffMs(user) {
1174
- if (!this.budgetConsumed.has(user))
1261
+ getBackoffMs() {
1262
+ if (this.getBudgetConsumed() === 0) {
1175
1263
  return 0;
1176
- const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
1264
+ }
1265
+ const exponent = Math.max(0, this.getBudgetConsumed() - 1);
1177
1266
  const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
1178
1267
  const backoffMs = Math.min(
1179
1268
  this.options.baseIntervalMs * 2 ** exponent,
@@ -1184,50 +1273,46 @@ var LeakyBucketRateLimit = class {
1184
1273
  get totalBudgetRestoreTime() {
1185
1274
  return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
1186
1275
  }
1187
- consumeBudget(user) {
1188
- this.stopLeak(user);
1189
- this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
1276
+ consumeBudget() {
1277
+ this.stopLeak();
1278
+ this.budgetConsumed = this.getBudgetConsumed() + 1;
1190
1279
  }
1191
- getBudgetConsumed(user) {
1192
- return this.budgetConsumed.get(user) ?? 0;
1280
+ getBudgetConsumed() {
1281
+ return this.budgetConsumed;
1193
1282
  }
1194
- hasBudget(user) {
1195
- return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
1283
+ hasBudget() {
1284
+ return this.getBudgetConsumed() < this.options.attemptBudgetCapacity;
1196
1285
  }
1197
- startRestoringBudget(user) {
1198
- if (this.intervalHandles.has(user)) {
1286
+ startRestoringBudget() {
1287
+ if (this.intervalHandle) {
1199
1288
  return;
1200
1289
  }
1201
1290
  const restoreBudgetForUser = () => {
1202
- const currentBudget = this.budgetConsumed.get(user);
1291
+ const currentBudget = this.budgetConsumed;
1203
1292
  if (!currentBudget) {
1204
- this.stopLeak(user);
1293
+ this.stopLeak();
1205
1294
  return;
1206
1295
  }
1207
1296
  const newBudget = currentBudget - 1;
1208
1297
  if (newBudget === 0) {
1209
- this.budgetConsumed.delete(user);
1210
1298
  return;
1211
1299
  }
1212
- this.budgetConsumed.set(user, newBudget);
1300
+ this.budgetConsumed = newBudget;
1213
1301
  };
1214
- const intervalHandle = setInterval(
1302
+ this.intervalHandle = setInterval(
1215
1303
  restoreBudgetForUser,
1216
1304
  this.options.budgetRestoreIntervalMs
1217
1305
  );
1218
- this.intervalHandles.set(user, intervalHandle);
1219
1306
  }
1220
- stopLeak(user) {
1221
- if (!this.intervalHandles.has(user)) {
1307
+ stopLeak() {
1308
+ if (!this.intervalHandle) {
1222
1309
  return;
1223
1310
  }
1224
- clearInterval(this.intervalHandles.get(user));
1225
- this.intervalHandles.delete(user);
1311
+ clearInterval(this.intervalHandle);
1312
+ this.intervalHandle = void 0;
1226
1313
  }
1227
1314
  close() {
1228
- for (const user of this.intervalHandles.keys()) {
1229
- this.stopLeak(user);
1230
- }
1315
+ this.stopLeak();
1231
1316
  }
1232
1317
  };
1233
1318
 
@@ -1258,8 +1343,10 @@ var ClientTransport = class extends Transport {
1258
1343
  * Optional handshake options for this client.
1259
1344
  */
1260
1345
  handshakeExtensions;
1346
+ sessions;
1261
1347
  constructor(clientId, providedOptions) {
1262
1348
  super(clientId, providedOptions);
1349
+ this.sessions = /* @__PURE__ */ new Map();
1263
1350
  this.options = {
1264
1351
  ...defaultClientTransportOptions,
1265
1352
  ...providedOptions
@@ -1291,7 +1378,7 @@ var ClientTransport = class extends Transport {
1291
1378
  return session.send(msg);
1292
1379
  }
1293
1380
  createUnconnectedSession(to) {
1294
- const session = SessionStateGraph.entrypoints.NoConnection(
1381
+ const session = ClientSessionStateGraph.entrypoint(
1295
1382
  to,
1296
1383
  this.clientId,
1297
1384
  {
@@ -1317,40 +1404,44 @@ var ClientTransport = class extends Transport {
1317
1404
  return noConnectionSession;
1318
1405
  }
1319
1406
  onConnectionEstablished(session, conn) {
1320
- const handshakingSession = SessionStateGraph.transition.ConnectingToHandshaking(session, conn, {
1321
- onConnectionErrored: (err) => {
1322
- const errStr = coerceErrorString(err);
1323
- this.log?.error(
1324
- `connection to ${handshakingSession.to} errored during handshake: ${errStr}`,
1325
- handshakingSession.loggingMetadata
1326
- );
1327
- },
1328
- onConnectionClosed: () => {
1329
- this.log?.warn(
1330
- `connection to ${handshakingSession.to} closed during handshake`,
1331
- handshakingSession.loggingMetadata
1332
- );
1333
- this.onConnClosed(handshakingSession);
1334
- },
1335
- onHandshake: (msg) => {
1336
- this.onHandshakeResponse(handshakingSession, msg);
1337
- },
1338
- onInvalidHandshake: (reason) => {
1339
- this.log?.error(
1340
- `invalid handshake: ${reason}`,
1341
- handshakingSession.loggingMetadata
1342
- );
1343
- this.deleteSession(session);
1344
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1345
- },
1346
- onHandshakeTimeout: () => {
1347
- this.log?.error(
1348
- `connection to ${handshakingSession.to} timed out during handshake`,
1349
- handshakingSession.loggingMetadata
1350
- );
1351
- this.onConnClosed(handshakingSession);
1407
+ const handshakingSession = ClientSessionStateGraph.transition.ConnectingToHandshaking(
1408
+ session,
1409
+ conn,
1410
+ {
1411
+ onConnectionErrored: (err) => {
1412
+ const errStr = coerceErrorString(err);
1413
+ this.log?.error(
1414
+ `connection to ${handshakingSession.to} errored during handshake: ${errStr}`,
1415
+ handshakingSession.loggingMetadata
1416
+ );
1417
+ },
1418
+ onConnectionClosed: () => {
1419
+ this.log?.warn(
1420
+ `connection to ${handshakingSession.to} closed during handshake`,
1421
+ handshakingSession.loggingMetadata
1422
+ );
1423
+ this.onConnClosed(handshakingSession);
1424
+ },
1425
+ onHandshake: (msg) => {
1426
+ this.onHandshakeResponse(handshakingSession, msg);
1427
+ },
1428
+ onInvalidHandshake: (reason) => {
1429
+ this.log?.error(
1430
+ `invalid handshake: ${reason}`,
1431
+ handshakingSession.loggingMetadata
1432
+ );
1433
+ this.deleteSession(session);
1434
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1435
+ },
1436
+ onHandshakeTimeout: () => {
1437
+ this.log?.error(
1438
+ `connection to ${handshakingSession.to} timed out during handshake`,
1439
+ handshakingSession.loggingMetadata
1440
+ );
1441
+ this.onConnClosed(handshakingSession);
1442
+ }
1352
1443
  }
1353
- });
1444
+ );
1354
1445
  this.updateSession(handshakingSession);
1355
1446
  void this.sendHandshake(handshakingSession);
1356
1447
  return handshakingSession;
@@ -1405,7 +1496,7 @@ var ClientTransport = class extends Transport {
1405
1496
  ...session.loggingMetadata,
1406
1497
  transportMessage: msg
1407
1498
  });
1408
- const connectedSession = SessionStateGraph.transition.HandshakingToConnected(session, {
1499
+ const connectedSession = ClientSessionStateGraph.transition.HandshakingToConnected(session, {
1409
1500
  onConnectionErrored: (err) => {
1410
1501
  const errStr = coerceErrorString(err);
1411
1502
  this.log?.warn(
@@ -1427,7 +1518,7 @@ var ClientTransport = class extends Transport {
1427
1518
  }
1428
1519
  });
1429
1520
  this.updateSession(connectedSession);
1430
- this.retryBudget.startRestoringBudget(connectedSession.to);
1521
+ this.retryBudget.startRestoringBudget();
1431
1522
  }
1432
1523
  /**
1433
1524
  * Manually attempts to connect to a client.
@@ -1450,44 +1541,49 @@ var ClientTransport = class extends Transport {
1450
1541
  );
1451
1542
  return;
1452
1543
  }
1453
- if (!this.retryBudget.hasBudget(to)) {
1454
- const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
1544
+ if (!this.retryBudget.hasBudget()) {
1545
+ const budgetConsumed = this.retryBudget.getBudgetConsumed();
1455
1546
  const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
1456
1547
  this.log?.error(errMsg, session.loggingMetadata);
1457
1548
  this.protocolError(ProtocolError.RetriesExceeded, errMsg);
1458
1549
  return;
1459
1550
  }
1460
- let sleep = Promise.resolve();
1461
- const backoffMs = this.retryBudget.getBackoffMs(to);
1462
- if (backoffMs > 0) {
1463
- sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
1464
- }
1551
+ const backoffMs = this.retryBudget.getBackoffMs();
1465
1552
  this.log?.info(
1466
1553
  `attempting connection to ${to} (${backoffMs}ms backoff)`,
1467
1554
  session.loggingMetadata
1468
1555
  );
1469
- this.retryBudget.consumeBudget(to);
1470
- const reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
1471
- try {
1472
- span.addEvent("backoff", { backoffMs });
1473
- await sleep;
1474
- if (this.getStatus() !== "open") {
1475
- throw new Error("transport state is no longer open");
1556
+ this.retryBudget.consumeBudget();
1557
+ const backingOffSession = ClientSessionStateGraph.transition.NoConnectionToBackingOff(
1558
+ session,
1559
+ backoffMs,
1560
+ {
1561
+ onBackoffFinished: () => {
1562
+ const reconnectPromise = tracing_default.startActiveSpan(
1563
+ "connect",
1564
+ async (span) => {
1565
+ try {
1566
+ return await this.createNewOutgoingConnection(to);
1567
+ } catch (err) {
1568
+ const errStr = coerceErrorString(err);
1569
+ span.recordException(errStr);
1570
+ span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
1571
+ throw err;
1572
+ } finally {
1573
+ span.end();
1574
+ }
1575
+ }
1576
+ );
1577
+ this.onBackoffFinished(backingOffSession, reconnectPromise);
1476
1578
  }
1477
- span.addEvent("connecting");
1478
- return await this.createNewOutgoingConnection(to);
1479
- } catch (err) {
1480
- const errStr = coerceErrorString(err);
1481
- span.recordException(errStr);
1482
- span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
1483
- throw err;
1484
- } finally {
1485
- span.end();
1486
1579
  }
1487
- });
1488
- const connectingSession = SessionStateGraph.transition.NoConnectionToConnecting(
1580
+ );
1581
+ this.updateSession(backingOffSession);
1582
+ }
1583
+ onBackoffFinished(session, connPromise) {
1584
+ const connectingSession = ClientSessionStateGraph.transition.BackingOffToConnecting(
1489
1585
  session,
1490
- reconnectPromise,
1586
+ connPromise,
1491
1587
  {
1492
1588
  onConnectionEstablished: (conn) => {
1493
1589
  this.log?.debug(
@@ -1559,9 +1655,11 @@ var ServerTransport = class extends Transport {
1559
1655
  * A map of session handshake data for each session.
1560
1656
  */
1561
1657
  sessionHandshakeMetadata = /* @__PURE__ */ new Map();
1658
+ sessions = /* @__PURE__ */ new Map();
1562
1659
  pendingSessions = /* @__PURE__ */ new Set();
1563
1660
  constructor(clientId, providedOptions) {
1564
1661
  super(clientId, providedOptions);
1662
+ this.sessions = /* @__PURE__ */ new Map();
1565
1663
  this.options = {
1566
1664
  ...defaultServerTransportOptions,
1567
1665
  ...providedOptions
@@ -1612,7 +1710,7 @@ var ServerTransport = class extends Transport {
1612
1710
  clientId: this.clientId
1613
1711
  });
1614
1712
  let receivedHandshake = false;
1615
- const pendingSession = SessionStateGraph.entrypoints.WaitingForHandshake(
1713
+ const pendingSession = ServerSessionStateGraph.entrypoint(
1616
1714
  this.clientId,
1617
1715
  conn,
1618
1716
  {
@@ -1766,26 +1864,15 @@ var ServerTransport = class extends Transport {
1766
1864
  );
1767
1865
  return;
1768
1866
  }
1769
- if (oldSession.state === "Connected" /* Connected */) {
1770
- const noConnectionSession = SessionStateGraph.transition.ConnectedToNoConnection(oldSession, {
1771
- onSessionGracePeriodElapsed: () => {
1772
- this.onSessionGracePeriodElapsed(noConnectionSession);
1773
- }
1774
- });
1775
- oldSession = noConnectionSession;
1776
- } else if (oldSession.state === "Handshaking" /* Handshaking */) {
1777
- const noConnectionSession = SessionStateGraph.transition.HandshakingToNoConnection(oldSession, {
1778
- onSessionGracePeriodElapsed: () => {
1779
- this.onSessionGracePeriodElapsed(noConnectionSession);
1780
- }
1781
- });
1782
- oldSession = noConnectionSession;
1783
- } else if (oldSession.state === "Connecting" /* Connecting */) {
1784
- const noConnectionSession = SessionStateGraph.transition.ConnectingToNoConnection(oldSession, {
1785
- onSessionGracePeriodElapsed: () => {
1786
- this.onSessionGracePeriodElapsed(noConnectionSession);
1867
+ if (oldSession.state !== "NoConnection" /* NoConnection */) {
1868
+ const noConnectionSession = ServerSessionStateGraph.transition.ConnectedToNoConnection(
1869
+ oldSession,
1870
+ {
1871
+ onSessionGracePeriodElapsed: () => {
1872
+ this.onSessionGracePeriodElapsed(noConnectionSession);
1873
+ }
1787
1874
  }
1788
- });
1875
+ );
1789
1876
  oldSession = noConnectionSession;
1790
1877
  }
1791
1878
  this.updateSession(oldSession);
@@ -1834,7 +1921,7 @@ var ServerTransport = class extends Transport {
1834
1921
  }
1835
1922
  });
1836
1923
  session.sendHandshake(responseMsg);
1837
- const connectedSession = SessionStateGraph.transition.WaitingForHandshakeToConnected(
1924
+ const connectedSession = ServerSessionStateGraph.transition.WaitingForHandshakeToConnected(
1838
1925
  session,
1839
1926
  // by this point oldSession is either no connection or we dont have an old session
1840
1927
  oldSession,
@@ -1869,43 +1956,43 @@ var ServerTransport = class extends Transport {
1869
1956
  connectedSession.startActiveHeartbeat();
1870
1957
  }
1871
1958
  async validateHandshakeMetadata(handshakingSession, existingSession, rawMetadata, from) {
1872
- let parsedMetadata = {};
1873
- if (this.handshakeExtensions) {
1874
- if (!import_value3.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1875
- this.rejectHandshakeRequest(
1876
- handshakingSession,
1877
- from,
1878
- "received malformed handshake metadata",
1879
- "MALFORMED_HANDSHAKE_META",
1880
- {
1881
- ...handshakingSession.loggingMetadata,
1882
- connectedTo: from,
1883
- validationErrors: [
1884
- ...import_value3.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1885
- ]
1886
- }
1887
- );
1888
- return false;
1889
- }
1890
- const previousParsedMetadata = existingSession ? this.sessionHandshakeMetadata.get(existingSession.to) : void 0;
1891
- parsedMetadata = await this.handshakeExtensions.validate(
1892
- rawMetadata,
1893
- previousParsedMetadata
1959
+ if (!this.handshakeExtensions) {
1960
+ return {};
1961
+ }
1962
+ if (!import_value3.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1963
+ this.rejectHandshakeRequest(
1964
+ handshakingSession,
1965
+ from,
1966
+ "received malformed handshake metadata",
1967
+ "MALFORMED_HANDSHAKE_META",
1968
+ {
1969
+ ...handshakingSession.loggingMetadata,
1970
+ connectedTo: from,
1971
+ validationErrors: [
1972
+ ...import_value3.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1973
+ ]
1974
+ }
1894
1975
  );
1895
- if (parsedMetadata === false) {
1896
- this.rejectHandshakeRequest(
1897
- handshakingSession,
1898
- from,
1899
- "rejected by handshake handler",
1900
- "REJECTED_BY_CUSTOM_HANDLER",
1901
- {
1902
- ...handshakingSession.loggingMetadata,
1903
- connectedTo: from,
1904
- clientId: this.clientId
1905
- }
1906
- );
1907
- return false;
1908
- }
1976
+ return false;
1977
+ }
1978
+ const previousParsedMetadata = existingSession ? this.sessionHandshakeMetadata.get(existingSession.to) : void 0;
1979
+ const parsedMetadata = await this.handshakeExtensions.validate(
1980
+ rawMetadata,
1981
+ previousParsedMetadata
1982
+ );
1983
+ if (import_value3.Value.Check(HandshakeErrorCustomHandlerFatalResponseCodes, parsedMetadata)) {
1984
+ this.rejectHandshakeRequest(
1985
+ handshakingSession,
1986
+ from,
1987
+ "rejected by handshake handler",
1988
+ parsedMetadata,
1989
+ {
1990
+ ...handshakingSession.loggingMetadata,
1991
+ connectedTo: from,
1992
+ clientId: this.clientId
1993
+ }
1994
+ );
1995
+ return false;
1909
1996
  }
1910
1997
  return parsedMetadata;
1911
1998
  }