@replit/river 0.200.0-rc.7 → 0.200.0-rc.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-BZBEE2VR.js → chunk-3ROTSXAO.js} +14 -4
- package/dist/chunk-3ROTSXAO.js.map +1 -0
- package/dist/{chunk-VLW5OKZG.js → chunk-B5VE44UX.js} +2 -2
- package/dist/{chunk-CXPZSAU4.js → chunk-FAIV2RO2.js} +62 -36
- package/dist/chunk-FAIV2RO2.js.map +1 -0
- package/dist/{chunk-U4W75CMT.js → chunk-J54ZWTQM.js} +7 -6
- package/dist/chunk-J54ZWTQM.js.map +1 -0
- package/dist/{chunk-F2E7ILHW.js → chunk-XV5WUEIR.js} +70 -59
- package/dist/chunk-XV5WUEIR.js.map +1 -0
- package/dist/{chunk-3XKJOFZA.js → chunk-Y3JHOIJ7.js} +141 -50
- package/dist/chunk-Y3JHOIJ7.js.map +1 -0
- package/dist/{chunk-XIJVDPYY.js → chunk-Y4DP7WHM.js} +2 -2
- package/dist/{chunk-XIJVDPYY.js.map → chunk-Y4DP7WHM.js.map} +1 -1
- package/dist/{client-829bf1f9.d.ts → client-22a47343.d.ts} +3 -5
- package/dist/{connection-5e67d641.d.ts → connection-260e45a8.d.ts} +1 -1
- package/dist/{context-9eabf54f.d.ts → context-b4aff18f.d.ts} +90 -43
- package/dist/logging/index.d.cts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/{message-fd349b27.d.ts → message-7d135e38.d.ts} +3 -1
- package/dist/router/index.cjs +12 -3
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +9 -8
- package/dist/router/index.d.ts +9 -8
- package/dist/router/index.js +2 -2
- package/dist/{server-d82a2d9b.d.ts → server-dd6a9853.d.ts} +27 -6
- package/dist/{services-6a446f04.d.ts → services-bd2c50c0.d.ts} +3 -3
- package/dist/transport/impls/ws/client.cjs +216 -88
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +5 -4
- package/dist/transport/impls/ws/client.d.ts +5 -4
- package/dist/transport/impls/ws/client.js +8 -7
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +220 -109
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +5 -4
- package/dist/transport/impls/ws/server.d.ts +5 -4
- package/dist/transport/impls/ws/server.js +5 -5
- package/dist/transport/index.cjs +278 -141
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +5 -4
- package/dist/transport/index.d.ts +5 -4
- package/dist/transport/index.js +5 -5
- package/dist/util/testHelpers.cjs +151 -51
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +5 -4
- package/dist/util/testHelpers.d.ts +5 -4
- package/dist/util/testHelpers.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-3XKJOFZA.js.map +0 -1
- package/dist/chunk-BZBEE2VR.js.map +0 -1
- package/dist/chunk-CXPZSAU4.js.map +0 -1
- package/dist/chunk-F2E7ILHW.js.map +0 -1
- package/dist/chunk-U4W75CMT.js.map +0 -1
- /package/dist/{chunk-VLW5OKZG.js.map → chunk-B5VE44UX.js.map} +0 -0
|
@@ -197,11 +197,20 @@ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
|
|
|
197
197
|
var HandshakeErrorRetriableResponseCodes = import_typebox.Type.Union([
|
|
198
198
|
import_typebox.Type.Literal("SESSION_STATE_MISMATCH")
|
|
199
199
|
]);
|
|
200
|
+
var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox.Type.Union([
|
|
201
|
+
// The custom validation handler rejected the handler because the client is unsupported.
|
|
202
|
+
import_typebox.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
|
|
203
|
+
// The custom validation handler rejected the handshake.
|
|
204
|
+
import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
|
|
205
|
+
]);
|
|
200
206
|
var HandshakeErrorFatalResponseCodes = import_typebox.Type.Union([
|
|
207
|
+
HandshakeErrorCustomHandlerFatalResponseCodes,
|
|
208
|
+
// The ciient sent a handshake that doesn't comply with the extended handshake metadata.
|
|
201
209
|
import_typebox.Type.Literal("MALFORMED_HANDSHAKE_META"),
|
|
210
|
+
// The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
|
|
202
211
|
import_typebox.Type.Literal("MALFORMED_HANDSHAKE"),
|
|
203
|
-
|
|
204
|
-
import_typebox.Type.Literal("
|
|
212
|
+
// The client's protocol version does not match the server's.
|
|
213
|
+
import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH")
|
|
205
214
|
]);
|
|
206
215
|
var HandshakeErrorResponseCodes = import_typebox.Type.Union([
|
|
207
216
|
HandshakeErrorRetriableResponseCodes,
|
|
@@ -314,6 +323,7 @@ var defaultTransportOptions = {
|
|
|
314
323
|
sessionDisconnectGraceMs: 5e3,
|
|
315
324
|
connectionTimeoutMs: 2e3,
|
|
316
325
|
handshakeTimeoutMs: 1e3,
|
|
326
|
+
enableTransparentSessionReconnects: true,
|
|
317
327
|
codec: NaiveJsonCodec
|
|
318
328
|
};
|
|
319
329
|
var defaultConnectionRetryOptions = {
|
|
@@ -448,6 +458,7 @@ var StateMachineState = class {
|
|
|
448
458
|
}
|
|
449
459
|
if (prop === "_handleClose") {
|
|
450
460
|
return () => {
|
|
461
|
+
target._isConsumed = true;
|
|
451
462
|
target._handleStateExit();
|
|
452
463
|
target._handleClose();
|
|
453
464
|
};
|
|
@@ -530,15 +541,18 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
530
541
|
}
|
|
531
542
|
get loggingMetadata() {
|
|
532
543
|
const spanContext = this.telemetry.span.spanContext();
|
|
533
|
-
|
|
544
|
+
const metadata = {
|
|
534
545
|
clientId: this.from,
|
|
535
546
|
connectedTo: this.to,
|
|
536
|
-
sessionId: this.id
|
|
537
|
-
|
|
547
|
+
sessionId: this.id
|
|
548
|
+
};
|
|
549
|
+
if (this.telemetry.span.isRecording()) {
|
|
550
|
+
metadata.telemetry = {
|
|
538
551
|
traceId: spanContext.traceId,
|
|
539
552
|
spanId: spanContext.spanId
|
|
540
|
-
}
|
|
541
|
-
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
return metadata;
|
|
542
556
|
}
|
|
543
557
|
constructMsg(partialMsg) {
|
|
544
558
|
const msg = {
|
|
@@ -567,9 +581,32 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
567
581
|
this.telemetry.span.end();
|
|
568
582
|
}
|
|
569
583
|
};
|
|
584
|
+
var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
|
|
585
|
+
graceExpiryTime;
|
|
586
|
+
gracePeriodTimeout;
|
|
587
|
+
listeners;
|
|
588
|
+
constructor(props) {
|
|
589
|
+
super(props);
|
|
590
|
+
this.listeners = props.listeners;
|
|
591
|
+
this.graceExpiryTime = props.graceExpiryTime;
|
|
592
|
+
this.gracePeriodTimeout = setTimeout(() => {
|
|
593
|
+
this.listeners.onSessionGracePeriodElapsed();
|
|
594
|
+
}, this.graceExpiryTime - Date.now());
|
|
595
|
+
}
|
|
596
|
+
_handleStateExit() {
|
|
597
|
+
super._handleStateExit();
|
|
598
|
+
if (this.gracePeriodTimeout) {
|
|
599
|
+
clearTimeout(this.gracePeriodTimeout);
|
|
600
|
+
this.gracePeriodTimeout = void 0;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
_handleClose() {
|
|
604
|
+
super._handleClose();
|
|
605
|
+
}
|
|
606
|
+
};
|
|
570
607
|
|
|
571
608
|
// transport/sessionStateMachine/SessionConnecting.ts
|
|
572
|
-
var SessionConnecting = class extends
|
|
609
|
+
var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
573
610
|
state = "Connecting" /* Connecting */;
|
|
574
611
|
connPromise;
|
|
575
612
|
listeners;
|
|
@@ -578,9 +615,6 @@ var SessionConnecting = class extends IdentifiedSession {
|
|
|
578
615
|
super(props);
|
|
579
616
|
this.connPromise = props.connPromise;
|
|
580
617
|
this.listeners = props.listeners;
|
|
581
|
-
this.connectionTimeout = setTimeout(() => {
|
|
582
|
-
this.listeners.onConnectionTimeout();
|
|
583
|
-
}, this.options.connectionTimeoutMs);
|
|
584
618
|
this.connPromise.then(
|
|
585
619
|
(conn) => {
|
|
586
620
|
if (this._isConsumed)
|
|
@@ -593,17 +627,33 @@ var SessionConnecting = class extends IdentifiedSession {
|
|
|
593
627
|
this.listeners.onConnectionFailed(err);
|
|
594
628
|
}
|
|
595
629
|
);
|
|
630
|
+
this.connectionTimeout = setTimeout(() => {
|
|
631
|
+
this.listeners.onConnectionTimeout();
|
|
632
|
+
}, this.options.connectionTimeoutMs);
|
|
596
633
|
}
|
|
597
634
|
// close a pending connection if it resolves, ignore errors if the promise
|
|
598
635
|
// ends up rejected anyways
|
|
599
636
|
bestEffortClose() {
|
|
600
|
-
|
|
637
|
+
const logger = this.log;
|
|
638
|
+
const metadata = this.loggingMetadata;
|
|
639
|
+
this.connPromise.then((conn) => {
|
|
640
|
+
conn.close();
|
|
641
|
+
logger?.info(
|
|
642
|
+
"connection eventually resolved but session has transitioned, closed connection",
|
|
643
|
+
{
|
|
644
|
+
...metadata,
|
|
645
|
+
...conn.loggingMetadata
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
}).catch(() => {
|
|
601
649
|
});
|
|
602
650
|
}
|
|
603
651
|
_handleStateExit() {
|
|
604
652
|
super._handleStateExit();
|
|
605
|
-
|
|
606
|
-
|
|
653
|
+
if (this.connectionTimeout) {
|
|
654
|
+
clearTimeout(this.connectionTimeout);
|
|
655
|
+
this.connectionTimeout = void 0;
|
|
656
|
+
}
|
|
607
657
|
}
|
|
608
658
|
_handleClose() {
|
|
609
659
|
this.bestEffortClose();
|
|
@@ -612,26 +662,13 @@ var SessionConnecting = class extends IdentifiedSession {
|
|
|
612
662
|
};
|
|
613
663
|
|
|
614
664
|
// transport/sessionStateMachine/SessionNoConnection.ts
|
|
615
|
-
var SessionNoConnection = class extends
|
|
665
|
+
var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
|
|
616
666
|
state = "NoConnection" /* NoConnection */;
|
|
617
|
-
listeners;
|
|
618
|
-
gracePeriodTimeout;
|
|
619
|
-
constructor(props) {
|
|
620
|
-
super(props);
|
|
621
|
-
this.listeners = props.listeners;
|
|
622
|
-
this.gracePeriodTimeout = setTimeout(() => {
|
|
623
|
-
this.listeners.onSessionGracePeriodElapsed();
|
|
624
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
625
|
-
}
|
|
626
667
|
_handleClose() {
|
|
627
668
|
super._handleClose();
|
|
628
669
|
}
|
|
629
670
|
_handleStateExit() {
|
|
630
671
|
super._handleStateExit();
|
|
631
|
-
if (this.gracePeriodTimeout) {
|
|
632
|
-
clearTimeout(this.gracePeriodTimeout);
|
|
633
|
-
this.gracePeriodTimeout = void 0;
|
|
634
|
-
}
|
|
635
672
|
}
|
|
636
673
|
};
|
|
637
674
|
|
|
@@ -639,7 +676,7 @@ var SessionNoConnection = class extends IdentifiedSession {
|
|
|
639
676
|
var import_api = require("@opentelemetry/api");
|
|
640
677
|
|
|
641
678
|
// package.json
|
|
642
|
-
var version = "0.200.0-rc.
|
|
679
|
+
var version = "0.200.0-rc.8";
|
|
643
680
|
|
|
644
681
|
// tracing/index.ts
|
|
645
682
|
function createSessionTelemetryInfo(sessionId, to, from, propagationCtx) {
|
|
@@ -678,20 +715,24 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
678
715
|
this.conn.addErrorListener(this.listeners.onConnectionErrored);
|
|
679
716
|
this.conn.addCloseListener(this.listeners.onConnectionClosed);
|
|
680
717
|
}
|
|
718
|
+
get loggingMetadata() {
|
|
719
|
+
return {
|
|
720
|
+
clientId: this.from,
|
|
721
|
+
connId: this.conn.id,
|
|
722
|
+
...this.conn.loggingMetadata
|
|
723
|
+
};
|
|
724
|
+
}
|
|
681
725
|
onHandshakeData = (msg) => {
|
|
682
726
|
const parsedMsg = this.parseMsg(msg);
|
|
683
727
|
if (parsedMsg === null) {
|
|
684
|
-
this.listeners.onInvalidHandshake(
|
|
728
|
+
this.listeners.onInvalidHandshake(
|
|
729
|
+
"could not parse message",
|
|
730
|
+
"MALFORMED_HANDSHAKE"
|
|
731
|
+
);
|
|
685
732
|
return;
|
|
686
733
|
}
|
|
687
734
|
this.listeners.onHandshake(parsedMsg);
|
|
688
735
|
};
|
|
689
|
-
get loggingMetadata() {
|
|
690
|
-
return {
|
|
691
|
-
clientId: this.from,
|
|
692
|
-
connId: this.conn.id
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
736
|
sendHandshake(msg) {
|
|
696
737
|
return this.conn.send(this.options.codec.toBuffer(msg));
|
|
697
738
|
}
|
|
@@ -708,7 +749,7 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
708
749
|
};
|
|
709
750
|
|
|
710
751
|
// transport/sessionStateMachine/SessionHandshaking.ts
|
|
711
|
-
var SessionHandshaking = class extends
|
|
752
|
+
var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
|
|
712
753
|
state = "Handshaking" /* Handshaking */;
|
|
713
754
|
conn;
|
|
714
755
|
listeners;
|
|
@@ -724,10 +765,19 @@ var SessionHandshaking = class extends IdentifiedSession {
|
|
|
724
765
|
this.conn.addErrorListener(this.listeners.onConnectionErrored);
|
|
725
766
|
this.conn.addCloseListener(this.listeners.onConnectionClosed);
|
|
726
767
|
}
|
|
768
|
+
get loggingMetadata() {
|
|
769
|
+
return {
|
|
770
|
+
...super.loggingMetadata,
|
|
771
|
+
...this.conn.loggingMetadata
|
|
772
|
+
};
|
|
773
|
+
}
|
|
727
774
|
onHandshakeData = (msg) => {
|
|
728
775
|
const parsedMsg = this.parseMsg(msg);
|
|
729
776
|
if (parsedMsg === null) {
|
|
730
|
-
this.listeners.onInvalidHandshake(
|
|
777
|
+
this.listeners.onInvalidHandshake(
|
|
778
|
+
"could not parse message",
|
|
779
|
+
"MALFORMED_HANDSHAKE"
|
|
780
|
+
);
|
|
731
781
|
return;
|
|
732
782
|
}
|
|
733
783
|
this.listeners.onHandshake(parsedMsg);
|
|
@@ -740,7 +790,10 @@ var SessionHandshaking = class extends IdentifiedSession {
|
|
|
740
790
|
this.conn.removeDataListener(this.onHandshakeData);
|
|
741
791
|
this.conn.removeErrorListener(this.listeners.onConnectionErrored);
|
|
742
792
|
this.conn.removeCloseListener(this.listeners.onConnectionClosed);
|
|
743
|
-
|
|
793
|
+
if (this.handshakeTimeout) {
|
|
794
|
+
clearTimeout(this.handshakeTimeout);
|
|
795
|
+
this.handshakeTimeout = void 0;
|
|
796
|
+
}
|
|
744
797
|
}
|
|
745
798
|
_handleClose() {
|
|
746
799
|
super._handleClose();
|
|
@@ -805,6 +858,12 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
805
858
|
this.heartbeatMisses++;
|
|
806
859
|
}, this.options.heartbeatIntervalMs);
|
|
807
860
|
}
|
|
861
|
+
get loggingMetadata() {
|
|
862
|
+
return {
|
|
863
|
+
...super.loggingMetadata,
|
|
864
|
+
...this.conn.loggingMetadata
|
|
865
|
+
};
|
|
866
|
+
}
|
|
808
867
|
startActiveHeartbeat() {
|
|
809
868
|
this.isActivelyHeartbeating = true;
|
|
810
869
|
}
|
|
@@ -820,8 +879,10 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
820
879
|
}
|
|
821
880
|
onMessageData = (msg) => {
|
|
822
881
|
const parsedMsg = this.parseMsg(msg);
|
|
823
|
-
if (parsedMsg === null)
|
|
882
|
+
if (parsedMsg === null) {
|
|
883
|
+
this.listeners.onInvalidMessage("could not parse message");
|
|
824
884
|
return;
|
|
885
|
+
}
|
|
825
886
|
if (parsedMsg.seq !== this.ack) {
|
|
826
887
|
if (parsedMsg.seq < this.ack) {
|
|
827
888
|
this.log?.debug(
|
|
@@ -878,7 +939,7 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
878
939
|
};
|
|
879
940
|
|
|
880
941
|
// transport/sessionStateMachine/SessionBackingOff.ts
|
|
881
|
-
var SessionBackingOff = class extends
|
|
942
|
+
var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
|
|
882
943
|
state = "BackingOff" /* BackingOff */;
|
|
883
944
|
listeners;
|
|
884
945
|
backoffTimeout;
|
|
@@ -916,6 +977,12 @@ function inheritSharedSession(session) {
|
|
|
916
977
|
protocolVersion: session.protocolVersion
|
|
917
978
|
};
|
|
918
979
|
}
|
|
980
|
+
function inheritSharedSessionWithGrace(session) {
|
|
981
|
+
return {
|
|
982
|
+
...inheritSharedSession(session),
|
|
983
|
+
graceExpiryTime: session.graceExpiryTime
|
|
984
|
+
};
|
|
985
|
+
}
|
|
919
986
|
var SessionStateGraph = {
|
|
920
987
|
entrypoints: {
|
|
921
988
|
NoConnection: (to, from, listeners, options, protocolVersion, log) => {
|
|
@@ -929,6 +996,7 @@ var SessionStateGraph = {
|
|
|
929
996
|
to,
|
|
930
997
|
seq: 0,
|
|
931
998
|
ack: 0,
|
|
999
|
+
graceExpiryTime: Date.now() + options.sessionDisconnectGraceMs,
|
|
932
1000
|
sendBuffer,
|
|
933
1001
|
telemetry,
|
|
934
1002
|
options,
|
|
@@ -961,7 +1029,7 @@ var SessionStateGraph = {
|
|
|
961
1029
|
transition: {
|
|
962
1030
|
// happy path transitions
|
|
963
1031
|
NoConnectionToBackingOff: (oldSession, backoffMs, listeners) => {
|
|
964
|
-
const carriedState =
|
|
1032
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
965
1033
|
oldSession._handleStateExit();
|
|
966
1034
|
const session = new SessionBackingOff({
|
|
967
1035
|
backoffMs,
|
|
@@ -978,7 +1046,7 @@ var SessionStateGraph = {
|
|
|
978
1046
|
return session;
|
|
979
1047
|
},
|
|
980
1048
|
BackingOffToConnecting: (oldSession, connPromise, listeners) => {
|
|
981
|
-
const carriedState =
|
|
1049
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
982
1050
|
oldSession._handleStateExit();
|
|
983
1051
|
const session = new SessionConnecting({
|
|
984
1052
|
connPromise,
|
|
@@ -995,7 +1063,7 @@ var SessionStateGraph = {
|
|
|
995
1063
|
return session;
|
|
996
1064
|
},
|
|
997
1065
|
ConnectingToHandshaking: (oldSession, conn, listeners) => {
|
|
998
|
-
const carriedState =
|
|
1066
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
999
1067
|
oldSession._handleStateExit();
|
|
1000
1068
|
const session = new SessionHandshaking({
|
|
1001
1069
|
conn,
|
|
@@ -1073,9 +1141,12 @@ var SessionStateGraph = {
|
|
|
1073
1141
|
},
|
|
1074
1142
|
// disconnect paths
|
|
1075
1143
|
BackingOffToNoConnection: (oldSession, listeners) => {
|
|
1076
|
-
const carriedState =
|
|
1144
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
1077
1145
|
oldSession._handleStateExit();
|
|
1078
|
-
const session = new SessionNoConnection({
|
|
1146
|
+
const session = new SessionNoConnection({
|
|
1147
|
+
listeners,
|
|
1148
|
+
...carriedState
|
|
1149
|
+
});
|
|
1079
1150
|
session.log?.info(
|
|
1080
1151
|
`session ${session.id} transition from BackingOff to NoConnection`,
|
|
1081
1152
|
{
|
|
@@ -1086,10 +1157,13 @@ var SessionStateGraph = {
|
|
|
1086
1157
|
return session;
|
|
1087
1158
|
},
|
|
1088
1159
|
ConnectingToNoConnection: (oldSession, listeners) => {
|
|
1089
|
-
const carriedState =
|
|
1160
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
1090
1161
|
oldSession.bestEffortClose();
|
|
1091
1162
|
oldSession._handleStateExit();
|
|
1092
|
-
const session = new SessionNoConnection({
|
|
1163
|
+
const session = new SessionNoConnection({
|
|
1164
|
+
listeners,
|
|
1165
|
+
...carriedState
|
|
1166
|
+
});
|
|
1093
1167
|
session.log?.info(
|
|
1094
1168
|
`session ${session.id} transition from Connecting to NoConnection`,
|
|
1095
1169
|
{
|
|
@@ -1100,10 +1174,13 @@ var SessionStateGraph = {
|
|
|
1100
1174
|
return session;
|
|
1101
1175
|
},
|
|
1102
1176
|
HandshakingToNoConnection: (oldSession, listeners) => {
|
|
1103
|
-
const carriedState =
|
|
1177
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
1104
1178
|
oldSession.conn.close();
|
|
1105
1179
|
oldSession._handleStateExit();
|
|
1106
|
-
const session = new SessionNoConnection({
|
|
1180
|
+
const session = new SessionNoConnection({
|
|
1181
|
+
listeners,
|
|
1182
|
+
...carriedState
|
|
1183
|
+
});
|
|
1107
1184
|
session.log?.info(
|
|
1108
1185
|
`session ${session.id} transition from Handshaking to NoConnection`,
|
|
1109
1186
|
{
|
|
@@ -1115,9 +1192,14 @@ var SessionStateGraph = {
|
|
|
1115
1192
|
},
|
|
1116
1193
|
ConnectedToNoConnection: (oldSession, listeners) => {
|
|
1117
1194
|
const carriedState = inheritSharedSession(oldSession);
|
|
1195
|
+
const graceExpiryTime = Date.now() + oldSession.options.sessionDisconnectGraceMs;
|
|
1118
1196
|
oldSession.conn.close();
|
|
1119
1197
|
oldSession._handleStateExit();
|
|
1120
|
-
const session = new SessionNoConnection({
|
|
1198
|
+
const session = new SessionNoConnection({
|
|
1199
|
+
listeners,
|
|
1200
|
+
graceExpiryTime,
|
|
1201
|
+
...carriedState
|
|
1202
|
+
});
|
|
1121
1203
|
session.log?.info(
|
|
1122
1204
|
`session ${session.id} transition from Connected to NoConnection`,
|
|
1123
1205
|
{
|
|
@@ -1134,24 +1216,42 @@ var ClientSessionStateGraph = {
|
|
|
1134
1216
|
entrypoint: SessionStateGraph.entrypoints.NoConnection,
|
|
1135
1217
|
transition: {
|
|
1136
1218
|
// happy paths
|
|
1219
|
+
// NoConnection -> BackingOff: attempt to connect
|
|
1137
1220
|
NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,
|
|
1221
|
+
// BackingOff -> Connecting: backoff period elapsed, start connection
|
|
1138
1222
|
BackingOffToConnecting: transitions.BackingOffToConnecting,
|
|
1223
|
+
// Connecting -> Handshaking: connection established, start handshake
|
|
1139
1224
|
ConnectingToHandshaking: transitions.ConnectingToHandshaking,
|
|
1225
|
+
// Handshaking -> Connected: handshake complete, session ready
|
|
1140
1226
|
HandshakingToConnected: transitions.HandshakingToConnected,
|
|
1141
1227
|
// disconnect paths
|
|
1228
|
+
// BackingOff -> NoConnection: unused
|
|
1142
1229
|
BackingOffToNoConnection: transitions.BackingOffToNoConnection,
|
|
1230
|
+
// Connecting -> NoConnection: connection failed or connection timeout
|
|
1143
1231
|
ConnectingToNoConnection: transitions.ConnectingToNoConnection,
|
|
1232
|
+
// Handshaking -> NoConnection: connection closed or handshake timeout
|
|
1144
1233
|
HandshakingToNoConnection: transitions.HandshakingToNoConnection,
|
|
1234
|
+
// Connected -> NoConnection: connection closed
|
|
1145
1235
|
ConnectedToNoConnection: transitions.ConnectedToNoConnection
|
|
1236
|
+
// destroy/close paths
|
|
1237
|
+
// NoConnection -> x: grace period elapsed
|
|
1238
|
+
// BackingOff -> x: grace period elapsed
|
|
1239
|
+
// Connecting -> x: grace period elapsed
|
|
1240
|
+
// Handshaking -> x: grace period elapsed or invalid handshake message or handshake rejection
|
|
1241
|
+
// Connected -> x: grace period elapsed or invalid message
|
|
1146
1242
|
}
|
|
1147
1243
|
};
|
|
1148
1244
|
var ServerSessionStateGraph = {
|
|
1149
1245
|
entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,
|
|
1150
1246
|
transition: {
|
|
1151
1247
|
// happy paths
|
|
1248
|
+
// WaitingForHandshake -> Connected: handshake complete, session ready
|
|
1152
1249
|
WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,
|
|
1153
1250
|
// disconnect paths
|
|
1251
|
+
// Connected -> NoConnection: connection closed
|
|
1154
1252
|
ConnectedToNoConnection: transitions.ConnectedToNoConnection
|
|
1253
|
+
// destroy/close paths
|
|
1254
|
+
// WaitingForHandshake -> x: handshake timeout elapsed or invalid handshake message or handshake rejection or connection closed
|
|
1155
1255
|
}
|
|
1156
1256
|
};
|
|
1157
1257
|
|
|
@@ -1220,8 +1320,8 @@ var Transport = class {
|
|
|
1220
1320
|
removeEventListener(type, handler) {
|
|
1221
1321
|
this.eventDispatcher.removeEventListener(type, handler);
|
|
1222
1322
|
}
|
|
1223
|
-
protocolError(
|
|
1224
|
-
this.eventDispatcher.dispatchEvent("protocolError",
|
|
1323
|
+
protocolError(message) {
|
|
1324
|
+
this.eventDispatcher.dispatchEvent("protocolError", message);
|
|
1225
1325
|
}
|
|
1226
1326
|
/**
|
|
1227
1327
|
* Default close implementation for transports. You should override this in the downstream
|
|
@@ -1268,8 +1368,9 @@ var Transport = class {
|
|
|
1268
1368
|
status: "disconnect",
|
|
1269
1369
|
session
|
|
1270
1370
|
});
|
|
1371
|
+
const to = session.to;
|
|
1271
1372
|
session.close();
|
|
1272
|
-
this.sessions.delete(
|
|
1373
|
+
this.sessions.delete(to);
|
|
1273
1374
|
}
|
|
1274
1375
|
// common listeners
|
|
1275
1376
|
onSessionGracePeriodElapsed(session) {
|
|
@@ -1426,13 +1527,17 @@ var ServerTransport = class extends Transport {
|
|
|
1426
1527
|
receivedHandshake = true;
|
|
1427
1528
|
void this.onHandshakeRequest(pendingSession, msg);
|
|
1428
1529
|
},
|
|
1429
|
-
onInvalidHandshake: (reason) => {
|
|
1530
|
+
onInvalidHandshake: (reason, code) => {
|
|
1430
1531
|
this.log?.error(
|
|
1431
1532
|
`invalid handshake: ${reason}`,
|
|
1432
1533
|
pendingSession.loggingMetadata
|
|
1433
1534
|
);
|
|
1434
1535
|
this.deletePendingSession(pendingSession);
|
|
1435
|
-
this.protocolError(
|
|
1536
|
+
this.protocolError({
|
|
1537
|
+
type: ProtocolError.HandshakeFailed,
|
|
1538
|
+
code,
|
|
1539
|
+
message: reason
|
|
1540
|
+
});
|
|
1436
1541
|
}
|
|
1437
1542
|
},
|
|
1438
1543
|
this.options,
|
|
@@ -1457,7 +1562,11 @@ var ServerTransport = class extends Transport {
|
|
|
1457
1562
|
}
|
|
1458
1563
|
})
|
|
1459
1564
|
);
|
|
1460
|
-
this.protocolError(
|
|
1565
|
+
this.protocolError({
|
|
1566
|
+
type: ProtocolError.HandshakeFailed,
|
|
1567
|
+
code,
|
|
1568
|
+
message: reason
|
|
1569
|
+
});
|
|
1461
1570
|
this.deletePendingSession(session);
|
|
1462
1571
|
}
|
|
1463
1572
|
async onHandshakeRequest(session, msg) {
|
|
@@ -1494,19 +1603,58 @@ var ServerTransport = class extends Transport {
|
|
|
1494
1603
|
return;
|
|
1495
1604
|
}
|
|
1496
1605
|
let oldSession = this.sessions.get(msg.from);
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1606
|
+
let parsedMetadata = {};
|
|
1607
|
+
if (this.handshakeExtensions) {
|
|
1608
|
+
if (!import_value2.Value.Check(this.handshakeExtensions.schema, msg.payload.metadata)) {
|
|
1609
|
+
this.rejectHandshakeRequest(
|
|
1610
|
+
session,
|
|
1611
|
+
msg.from,
|
|
1612
|
+
"received malformed handshake metadata",
|
|
1613
|
+
"MALFORMED_HANDSHAKE_META",
|
|
1614
|
+
{
|
|
1615
|
+
...session.loggingMetadata,
|
|
1616
|
+
connectedTo: msg.from,
|
|
1617
|
+
validationErrors: [
|
|
1618
|
+
...import_value2.Value.Errors(
|
|
1619
|
+
this.handshakeExtensions.schema,
|
|
1620
|
+
msg.payload.metadata
|
|
1621
|
+
)
|
|
1622
|
+
]
|
|
1623
|
+
}
|
|
1624
|
+
);
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
const previousParsedMetadata = oldSession ? this.sessionHandshakeMetadata.get(oldSession.to) : void 0;
|
|
1628
|
+
const parsedMetadataOrFailureCode = await this.handshakeExtensions.validate(
|
|
1629
|
+
msg.payload.metadata,
|
|
1630
|
+
previousParsedMetadata
|
|
1631
|
+
);
|
|
1632
|
+
if (session._isConsumed) {
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
if (import_value2.Value.Check(
|
|
1636
|
+
HandshakeErrorCustomHandlerFatalResponseCodes,
|
|
1637
|
+
parsedMetadataOrFailureCode
|
|
1638
|
+
)) {
|
|
1639
|
+
this.rejectHandshakeRequest(
|
|
1640
|
+
session,
|
|
1641
|
+
msg.from,
|
|
1642
|
+
"rejected by handshake handler",
|
|
1643
|
+
parsedMetadataOrFailureCode,
|
|
1644
|
+
{
|
|
1645
|
+
...session.loggingMetadata,
|
|
1646
|
+
connectedTo: msg.from,
|
|
1647
|
+
clientId: this.clientId
|
|
1648
|
+
}
|
|
1649
|
+
);
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
parsedMetadata = parsedMetadataOrFailureCode;
|
|
1505
1653
|
}
|
|
1506
1654
|
let connectCase = "new session";
|
|
1507
1655
|
const clientNextExpectedSeq = msg.payload.expectedSessionState.nextExpectedSeq;
|
|
1508
1656
|
const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;
|
|
1509
|
-
if (oldSession && oldSession.id === msg.payload.sessionId) {
|
|
1657
|
+
if (this.options.enableTransparentSessionReconnects && oldSession && oldSession.id === msg.payload.sessionId) {
|
|
1510
1658
|
connectCase = "transparent reconnection";
|
|
1511
1659
|
const ourNextSeq = oldSession.nextSeq();
|
|
1512
1660
|
const ourAck = oldSession.ack;
|
|
@@ -1565,10 +1713,11 @@ var ServerTransport = class extends Transport {
|
|
|
1565
1713
|
}
|
|
1566
1714
|
if (!oldSession && (clientNextSentSeq > 0 || clientNextExpectedSeq > 0)) {
|
|
1567
1715
|
connectCase = "unknown session";
|
|
1716
|
+
const rejectionMessage = this.options.enableTransparentSessionReconnects ? `client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}` : `client is attempting a transparent reconnect to a session but the server does not support it: ${msg.payload.sessionId}`;
|
|
1568
1717
|
this.rejectHandshakeRequest(
|
|
1569
1718
|
session,
|
|
1570
1719
|
msg.from,
|
|
1571
|
-
|
|
1720
|
+
rejectionMessage,
|
|
1572
1721
|
"SESSION_STATE_MISMATCH",
|
|
1573
1722
|
{
|
|
1574
1723
|
...session.loggingMetadata,
|
|
@@ -1619,7 +1768,10 @@ var ServerTransport = class extends Transport {
|
|
|
1619
1768
|
},
|
|
1620
1769
|
onMessage: (msg2) => this.handleMsg(msg2),
|
|
1621
1770
|
onInvalidMessage: (reason) => {
|
|
1622
|
-
this.protocolError(
|
|
1771
|
+
this.protocolError({
|
|
1772
|
+
type: ProtocolError.MessageOrderingViolated,
|
|
1773
|
+
message: reason
|
|
1774
|
+
});
|
|
1623
1775
|
this.deleteSession(connectedSession);
|
|
1624
1776
|
}
|
|
1625
1777
|
},
|
|
@@ -1630,47 +1782,6 @@ var ServerTransport = class extends Transport {
|
|
|
1630
1782
|
this.pendingSessions.delete(session);
|
|
1631
1783
|
connectedSession.startActiveHeartbeat();
|
|
1632
1784
|
}
|
|
1633
|
-
async validateHandshakeMetadata(handshakingSession, existingSession, rawMetadata, from) {
|
|
1634
|
-
let parsedMetadata = {};
|
|
1635
|
-
if (this.handshakeExtensions) {
|
|
1636
|
-
if (!import_value2.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
|
|
1637
|
-
this.rejectHandshakeRequest(
|
|
1638
|
-
handshakingSession,
|
|
1639
|
-
from,
|
|
1640
|
-
"received malformed handshake metadata",
|
|
1641
|
-
"MALFORMED_HANDSHAKE_META",
|
|
1642
|
-
{
|
|
1643
|
-
...handshakingSession.loggingMetadata,
|
|
1644
|
-
connectedTo: from,
|
|
1645
|
-
validationErrors: [
|
|
1646
|
-
...import_value2.Value.Errors(this.handshakeExtensions.schema, rawMetadata)
|
|
1647
|
-
]
|
|
1648
|
-
}
|
|
1649
|
-
);
|
|
1650
|
-
return false;
|
|
1651
|
-
}
|
|
1652
|
-
const previousParsedMetadata = existingSession ? this.sessionHandshakeMetadata.get(existingSession.to) : void 0;
|
|
1653
|
-
parsedMetadata = await this.handshakeExtensions.validate(
|
|
1654
|
-
rawMetadata,
|
|
1655
|
-
previousParsedMetadata
|
|
1656
|
-
);
|
|
1657
|
-
if (parsedMetadata === false) {
|
|
1658
|
-
this.rejectHandshakeRequest(
|
|
1659
|
-
handshakingSession,
|
|
1660
|
-
from,
|
|
1661
|
-
"rejected by handshake handler",
|
|
1662
|
-
"REJECTED_BY_CUSTOM_HANDLER",
|
|
1663
|
-
{
|
|
1664
|
-
...handshakingSession.loggingMetadata,
|
|
1665
|
-
connectedTo: from,
|
|
1666
|
-
clientId: this.clientId
|
|
1667
|
-
}
|
|
1668
|
-
);
|
|
1669
|
-
return false;
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
return parsedMetadata;
|
|
1673
|
-
}
|
|
1674
1785
|
};
|
|
1675
1786
|
|
|
1676
1787
|
// transport/impls/ws/server.ts
|