@replit/river 0.207.2 → 0.208.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.
- package/dist/adapter-ChksXKVN.d.ts +46 -0
- package/dist/adapter-Cuc4JtfV.d.cts +46 -0
- package/dist/chunk-2JNVDUMN.js +2238 -0
- package/dist/chunk-2JNVDUMN.js.map +1 -0
- package/dist/{chunk-4HE7UYRL.js → chunk-DKW3GC3M.js} +6 -5
- package/dist/{chunk-4HE7UYRL.js.map → chunk-DKW3GC3M.js.map} +1 -1
- package/dist/{chunk-46IVOKJU.js → chunk-ETZAHFGQ.js} +80 -61
- package/dist/chunk-ETZAHFGQ.js.map +1 -0
- package/dist/codec/index.cjs +157 -23
- package/dist/codec/index.cjs.map +1 -1
- package/dist/codec/index.d.cts +5 -1
- package/dist/codec/index.d.ts +5 -1
- package/dist/codec/index.js +6 -20
- package/dist/codec/index.js.map +1 -1
- package/dist/connection-BF4zg6Qv.d.cts +35 -0
- package/dist/{connection-a18e31d5.d.ts → connection-Donr3JRB.d.ts} +4 -3
- package/dist/index-C9tpZjBN.d.cts +37 -0
- package/dist/index-D8IOd3LG.d.ts +37 -0
- package/dist/logging/index.d.cts +2 -1
- package/dist/logging/index.d.ts +2 -1
- package/dist/{message-ffacb98a.d.ts → message-Di94OL80.d.cts} +1 -35
- package/dist/message-Di94OL80.d.ts +108 -0
- package/dist/router/index.cjs +62 -43
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +27 -7
- package/dist/router/index.d.ts +27 -7
- package/dist/router/index.js +1 -1
- package/dist/testUtil/index.cjs +828 -725
- package/dist/testUtil/index.cjs.map +1 -1
- package/dist/testUtil/index.d.cts +5 -4
- package/dist/testUtil/index.d.ts +5 -4
- package/dist/testUtil/index.js +23 -25
- package/dist/testUtil/index.js.map +1 -1
- package/dist/transport/impls/ws/client.cjs +293 -233
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +6 -5
- package/dist/transport/impls/ws/client.d.ts +6 -5
- package/dist/transport/impls/ws/client.js +5 -7
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +269 -200
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +6 -5
- package/dist/transport/impls/ws/server.d.ts +6 -5
- package/dist/transport/impls/ws/server.js +5 -7
- package/dist/transport/impls/ws/server.js.map +1 -1
- package/dist/transport/index.cjs +438 -342
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +7 -6
- package/dist/transport/index.d.ts +7 -6
- package/dist/transport/index.js +5 -10
- package/dist/transport-CCaWx1Rb.d.cts +1566 -0
- package/dist/{services-43528f4b.d.ts → transport-CZb3vdB4.d.ts} +294 -293
- package/dist/{wslike-e0b32dd5.d.ts → wslike-Dng9H1C7.d.cts} +1 -1
- package/dist/wslike-Dng9H1C7.d.ts +40 -0
- package/package.json +3 -3
- package/dist/chunk-24EWYOGK.js +0 -1287
- package/dist/chunk-24EWYOGK.js.map +0 -1
- package/dist/chunk-46IVOKJU.js.map +0 -1
- package/dist/chunk-A7RGOVRV.js +0 -438
- package/dist/chunk-A7RGOVRV.js.map +0 -1
- package/dist/chunk-AJGIY2UB.js +0 -56
- package/dist/chunk-AJGIY2UB.js.map +0 -1
- package/dist/chunk-XV4RQ62N.js +0 -377
- package/dist/chunk-XV4RQ62N.js.map +0 -1
- package/dist/types-3e5768ec.d.ts +0 -20
|
@@ -186,23 +186,20 @@ var NaiveJsonCodec = {
|
|
|
186
186
|
);
|
|
187
187
|
},
|
|
188
188
|
fromBuffer: (buff) => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return val;
|
|
197
|
-
}
|
|
189
|
+
const parsed = JSON.parse(
|
|
190
|
+
decoder.decode(buff),
|
|
191
|
+
function reviver(_key, val) {
|
|
192
|
+
if (val?.$t) {
|
|
193
|
+
return base64ToUint8Array(val.$t);
|
|
194
|
+
} else {
|
|
195
|
+
return val;
|
|
198
196
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
} catch {
|
|
204
|
-
return null;
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
200
|
+
throw new Error("unpacked msg is not an object");
|
|
205
201
|
}
|
|
202
|
+
return parsed;
|
|
206
203
|
}
|
|
207
204
|
};
|
|
208
205
|
|
|
@@ -366,7 +363,8 @@ var ProtocolError = {
|
|
|
366
363
|
RetriesExceeded: "conn_retry_exceeded",
|
|
367
364
|
HandshakeFailed: "handshake_failed",
|
|
368
365
|
MessageOrderingViolated: "message_ordering_violated",
|
|
369
|
-
InvalidMessage: "invalid_message"
|
|
366
|
+
InvalidMessage: "invalid_message",
|
|
367
|
+
MessageSendFailure: "message_send_failure"
|
|
370
368
|
};
|
|
371
369
|
var EventDispatcher = class {
|
|
372
370
|
eventListeners = {};
|
|
@@ -400,7 +398,6 @@ var EventDispatcher = class {
|
|
|
400
398
|
};
|
|
401
399
|
|
|
402
400
|
// transport/sessionStateMachine/common.ts
|
|
403
|
-
var import_value = require("@sinclair/typebox/value");
|
|
404
401
|
var ERR_CONSUMED = `session state has been consumed and is no longer valid`;
|
|
405
402
|
var StateMachineState = class {
|
|
406
403
|
/*
|
|
@@ -460,34 +457,16 @@ var StateMachineState = class {
|
|
|
460
457
|
var CommonSession = class extends StateMachineState {
|
|
461
458
|
from;
|
|
462
459
|
options;
|
|
460
|
+
codec;
|
|
463
461
|
tracer;
|
|
464
462
|
log;
|
|
465
|
-
constructor({ from, options, log, tracer }) {
|
|
463
|
+
constructor({ from, options, log, tracer, codec }) {
|
|
466
464
|
super();
|
|
467
465
|
this.from = from;
|
|
468
466
|
this.options = options;
|
|
469
467
|
this.log = log;
|
|
470
468
|
this.tracer = tracer;
|
|
471
|
-
|
|
472
|
-
parseMsg(msg) {
|
|
473
|
-
const parsedMsg = this.options.codec.fromBuffer(msg);
|
|
474
|
-
if (parsedMsg === null) {
|
|
475
|
-
this.log?.error(
|
|
476
|
-
`received malformed msg: ${Buffer.from(msg).toString("base64")}`,
|
|
477
|
-
this.loggingMetadata
|
|
478
|
-
);
|
|
479
|
-
return null;
|
|
480
|
-
}
|
|
481
|
-
if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
|
|
482
|
-
this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {
|
|
483
|
-
...this.loggingMetadata,
|
|
484
|
-
validationErrors: [
|
|
485
|
-
...import_value.Value.Errors(OpaqueTransportMessageSchema, parsedMsg)
|
|
486
|
-
]
|
|
487
|
-
});
|
|
488
|
-
return null;
|
|
489
|
-
}
|
|
490
|
-
return parsedMsg;
|
|
469
|
+
this.codec = codec;
|
|
491
470
|
}
|
|
492
471
|
};
|
|
493
472
|
var IdentifiedSession = class extends CommonSession {
|
|
@@ -547,9 +526,6 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
547
526
|
return metadata;
|
|
548
527
|
}
|
|
549
528
|
constructMsg(partialMsg) {
|
|
550
|
-
if (this._isConsumed) {
|
|
551
|
-
throw new Error(ERR_CONSUMED);
|
|
552
|
-
}
|
|
553
529
|
const msg = {
|
|
554
530
|
...partialMsg,
|
|
555
531
|
id: generateId(),
|
|
@@ -567,7 +543,10 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
567
543
|
send(msg) {
|
|
568
544
|
const constructedMsg = this.constructMsg(msg);
|
|
569
545
|
this.sendBuffer.push(constructedMsg);
|
|
570
|
-
return
|
|
546
|
+
return {
|
|
547
|
+
ok: true,
|
|
548
|
+
value: constructedMsg.id
|
|
549
|
+
};
|
|
571
550
|
}
|
|
572
551
|
_handleStateExit() {
|
|
573
552
|
}
|
|
@@ -599,6 +578,23 @@ var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
|
|
|
599
578
|
super._handleClose();
|
|
600
579
|
}
|
|
601
580
|
};
|
|
581
|
+
function sendMessage(conn, codec, msg) {
|
|
582
|
+
const buff = codec.toBuffer(msg);
|
|
583
|
+
if (!buff.ok) {
|
|
584
|
+
return buff;
|
|
585
|
+
}
|
|
586
|
+
const sent = conn.send(buff.value);
|
|
587
|
+
if (!sent) {
|
|
588
|
+
return {
|
|
589
|
+
ok: false,
|
|
590
|
+
reason: "failed to send message"
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
ok: true,
|
|
595
|
+
value: msg.id
|
|
596
|
+
};
|
|
597
|
+
}
|
|
602
598
|
|
|
603
599
|
// transport/sessionStateMachine/SessionConnecting.ts
|
|
604
600
|
var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
@@ -612,13 +608,11 @@ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
|
612
608
|
this.listeners = props.listeners;
|
|
613
609
|
this.connPromise.then(
|
|
614
610
|
(conn) => {
|
|
615
|
-
if (this._isConsumed)
|
|
616
|
-
return;
|
|
611
|
+
if (this._isConsumed) return;
|
|
617
612
|
this.listeners.onConnectionEstablished(conn);
|
|
618
613
|
},
|
|
619
614
|
(err) => {
|
|
620
|
-
if (this._isConsumed)
|
|
621
|
-
return;
|
|
615
|
+
if (this._isConsumed) return;
|
|
622
616
|
this.listeners.onConnectionFailed(err);
|
|
623
617
|
}
|
|
624
618
|
);
|
|
@@ -651,8 +645,8 @@ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
|
651
645
|
}
|
|
652
646
|
}
|
|
653
647
|
_handleClose() {
|
|
654
|
-
this.bestEffortClose();
|
|
655
648
|
super._handleClose();
|
|
649
|
+
this.bestEffortClose();
|
|
656
650
|
}
|
|
657
651
|
};
|
|
658
652
|
|
|
@@ -679,7 +673,7 @@ function coerceErrorString(err) {
|
|
|
679
673
|
}
|
|
680
674
|
|
|
681
675
|
// package.json
|
|
682
|
-
var version = "0.
|
|
676
|
+
var version = "0.208.0";
|
|
683
677
|
|
|
684
678
|
// tracing/index.ts
|
|
685
679
|
function getPropagationContext(ctx) {
|
|
@@ -693,7 +687,7 @@ function getPropagationContext(ctx) {
|
|
|
693
687
|
function createSessionTelemetryInfo(tracer, sessionId, to, from, propagationCtx) {
|
|
694
688
|
const parentCtx = propagationCtx ? import_api2.propagation.extract(import_api2.context.active(), propagationCtx) : import_api2.context.active();
|
|
695
689
|
const span = tracer.startSpan(
|
|
696
|
-
`river.session
|
|
690
|
+
`river.session`,
|
|
697
691
|
{
|
|
698
692
|
attributes: {
|
|
699
693
|
component: "river",
|
|
@@ -709,7 +703,7 @@ function createSessionTelemetryInfo(tracer, sessionId, to, from, propagationCtx)
|
|
|
709
703
|
}
|
|
710
704
|
function createConnectionTelemetryInfo(tracer, connection, info) {
|
|
711
705
|
const span = tracer.startSpan(
|
|
712
|
-
`connection
|
|
706
|
+
`river.connection`,
|
|
713
707
|
{
|
|
714
708
|
attributes: {
|
|
715
709
|
component: "river",
|
|
@@ -739,9 +733,9 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
739
733
|
this.handshakeTimeout = setTimeout(() => {
|
|
740
734
|
this.listeners.onHandshakeTimeout();
|
|
741
735
|
}, this.options.handshakeTimeoutMs);
|
|
742
|
-
this.conn.
|
|
743
|
-
this.conn.
|
|
744
|
-
this.conn.
|
|
736
|
+
this.conn.setDataListener(this.onHandshakeData);
|
|
737
|
+
this.conn.setErrorListener(this.listeners.onConnectionErrored);
|
|
738
|
+
this.conn.setCloseListener(this.listeners.onConnectionClosed);
|
|
745
739
|
}
|
|
746
740
|
get loggingMetadata() {
|
|
747
741
|
return {
|
|
@@ -751,23 +745,23 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
751
745
|
};
|
|
752
746
|
}
|
|
753
747
|
onHandshakeData = (msg) => {
|
|
754
|
-
const
|
|
755
|
-
if (
|
|
748
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
749
|
+
if (!parsedMsgRes.ok) {
|
|
756
750
|
this.listeners.onInvalidHandshake(
|
|
757
|
-
|
|
751
|
+
`could not parse handshake message: ${parsedMsgRes.reason}`,
|
|
758
752
|
"MALFORMED_HANDSHAKE"
|
|
759
753
|
);
|
|
760
754
|
return;
|
|
761
755
|
}
|
|
762
|
-
this.listeners.onHandshake(
|
|
756
|
+
this.listeners.onHandshake(parsedMsgRes.value);
|
|
763
757
|
};
|
|
764
758
|
sendHandshake(msg) {
|
|
765
|
-
return this.conn
|
|
759
|
+
return sendMessage(this.conn, this.codec, msg);
|
|
766
760
|
}
|
|
767
761
|
_handleStateExit() {
|
|
768
|
-
this.conn.removeDataListener(
|
|
769
|
-
this.conn.removeErrorListener(
|
|
770
|
-
this.conn.removeCloseListener(
|
|
762
|
+
this.conn.removeDataListener();
|
|
763
|
+
this.conn.removeErrorListener();
|
|
764
|
+
this.conn.removeCloseListener();
|
|
771
765
|
clearTimeout(this.handshakeTimeout);
|
|
772
766
|
this.handshakeTimeout = void 0;
|
|
773
767
|
}
|
|
@@ -789,9 +783,9 @@ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
|
|
|
789
783
|
this.handshakeTimeout = setTimeout(() => {
|
|
790
784
|
this.listeners.onHandshakeTimeout();
|
|
791
785
|
}, this.options.handshakeTimeoutMs);
|
|
792
|
-
this.conn.
|
|
793
|
-
this.conn.
|
|
794
|
-
this.conn.
|
|
786
|
+
this.conn.setDataListener(this.onHandshakeData);
|
|
787
|
+
this.conn.setErrorListener(this.listeners.onConnectionErrored);
|
|
788
|
+
this.conn.setCloseListener(this.listeners.onConnectionClosed);
|
|
795
789
|
}
|
|
796
790
|
get loggingMetadata() {
|
|
797
791
|
return {
|
|
@@ -800,24 +794,24 @@ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
|
|
|
800
794
|
};
|
|
801
795
|
}
|
|
802
796
|
onHandshakeData = (msg) => {
|
|
803
|
-
const
|
|
804
|
-
if (
|
|
797
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
798
|
+
if (!parsedMsgRes.ok) {
|
|
805
799
|
this.listeners.onInvalidHandshake(
|
|
806
|
-
|
|
800
|
+
`could not parse handshake message: ${parsedMsgRes.reason}`,
|
|
807
801
|
"MALFORMED_HANDSHAKE"
|
|
808
802
|
);
|
|
809
803
|
return;
|
|
810
804
|
}
|
|
811
|
-
this.listeners.onHandshake(
|
|
805
|
+
this.listeners.onHandshake(parsedMsgRes.value);
|
|
812
806
|
};
|
|
813
807
|
sendHandshake(msg) {
|
|
814
|
-
return this.conn
|
|
808
|
+
return sendMessage(this.conn, this.codec, msg);
|
|
815
809
|
}
|
|
816
810
|
_handleStateExit() {
|
|
817
811
|
super._handleStateExit();
|
|
818
|
-
this.conn.removeDataListener(
|
|
819
|
-
this.conn.removeErrorListener(
|
|
820
|
-
this.conn.removeCloseListener(
|
|
812
|
+
this.conn.removeDataListener();
|
|
813
|
+
this.conn.removeErrorListener();
|
|
814
|
+
this.conn.removeCloseListener();
|
|
821
815
|
if (this.handshakeTimeout) {
|
|
822
816
|
clearTimeout(this.handshakeTimeout);
|
|
823
817
|
this.handshakeTimeout = void 0;
|
|
@@ -836,25 +830,15 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
836
830
|
conn;
|
|
837
831
|
listeners;
|
|
838
832
|
heartbeatHandle;
|
|
839
|
-
|
|
840
|
-
isActivelyHeartbeating;
|
|
841
|
-
lastConstructedMsgs = [];
|
|
842
|
-
pushLastConstructedMsgs = (msg) => {
|
|
843
|
-
const trackedMsg = {
|
|
844
|
-
id: msg.id,
|
|
845
|
-
seq: msg.seq,
|
|
846
|
-
streamId: msg.streamId,
|
|
847
|
-
stack: new Error().stack
|
|
848
|
-
};
|
|
849
|
-
this.lastConstructedMsgs.push(trackedMsg);
|
|
850
|
-
if (this.lastConstructedMsgs.length > 10) {
|
|
851
|
-
this.lastConstructedMsgs.shift();
|
|
852
|
-
}
|
|
853
|
-
};
|
|
833
|
+
heartbeatMissTimeout;
|
|
834
|
+
isActivelyHeartbeating = false;
|
|
854
835
|
updateBookkeeping(ack, seq) {
|
|
855
836
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
|
|
856
837
|
this.ack = seq + 1;
|
|
857
|
-
this.
|
|
838
|
+
if (this.heartbeatMissTimeout) {
|
|
839
|
+
clearTimeout(this.heartbeatMissTimeout);
|
|
840
|
+
}
|
|
841
|
+
this.startMissingHeartbeatTimeout();
|
|
858
842
|
}
|
|
859
843
|
assertSendOrdering(constructedMsg) {
|
|
860
844
|
if (constructedMsg.seq > this.seqSent + 1) {
|
|
@@ -862,30 +846,32 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
862
846
|
this.log?.error(msg, {
|
|
863
847
|
...this.loggingMetadata,
|
|
864
848
|
transportMessage: constructedMsg,
|
|
865
|
-
tags: ["invariant-violation"]
|
|
866
|
-
extras: {
|
|
867
|
-
lastConstructedMsgs: this.lastConstructedMsgs
|
|
868
|
-
}
|
|
849
|
+
tags: ["invariant-violation"]
|
|
869
850
|
});
|
|
870
851
|
throw new Error(msg);
|
|
871
852
|
}
|
|
872
853
|
}
|
|
873
854
|
send(msg) {
|
|
874
855
|
const constructedMsg = this.constructMsg(msg);
|
|
875
|
-
this.pushLastConstructedMsgs(constructedMsg);
|
|
876
856
|
this.assertSendOrdering(constructedMsg);
|
|
877
857
|
this.sendBuffer.push(constructedMsg);
|
|
878
|
-
this.conn
|
|
858
|
+
const res = sendMessage(this.conn, this.codec, constructedMsg);
|
|
859
|
+
if (!res.ok) {
|
|
860
|
+
this.listeners.onMessageSendFailure(constructedMsg, res.reason);
|
|
861
|
+
return res;
|
|
862
|
+
}
|
|
879
863
|
this.seqSent = constructedMsg.seq;
|
|
880
|
-
return
|
|
864
|
+
return res;
|
|
881
865
|
}
|
|
882
866
|
constructor(props) {
|
|
883
867
|
super(props);
|
|
884
868
|
this.conn = props.conn;
|
|
885
869
|
this.listeners = props.listeners;
|
|
886
|
-
this.conn.
|
|
887
|
-
this.conn.
|
|
888
|
-
this.conn.
|
|
870
|
+
this.conn.setDataListener(this.onMessageData);
|
|
871
|
+
this.conn.setCloseListener(this.listeners.onConnectionClosed);
|
|
872
|
+
this.conn.setErrorListener(this.listeners.onConnectionErrored);
|
|
873
|
+
}
|
|
874
|
+
sendBufferedMessages() {
|
|
889
875
|
if (this.sendBuffer.length > 0) {
|
|
890
876
|
this.log?.info(
|
|
891
877
|
`sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
|
|
@@ -893,30 +879,15 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
893
879
|
);
|
|
894
880
|
for (const msg of this.sendBuffer) {
|
|
895
881
|
this.assertSendOrdering(msg);
|
|
896
|
-
this.conn
|
|
882
|
+
const res = sendMessage(this.conn, this.codec, msg);
|
|
883
|
+
if (!res.ok) {
|
|
884
|
+
this.listeners.onMessageSendFailure(msg, res.reason);
|
|
885
|
+
return res;
|
|
886
|
+
}
|
|
897
887
|
this.seqSent = msg.seq;
|
|
898
888
|
}
|
|
899
889
|
}
|
|
900
|
-
|
|
901
|
-
this.heartbeatHandle = setInterval(() => {
|
|
902
|
-
const misses = this.heartbeatMisses;
|
|
903
|
-
const missDuration = misses * this.options.heartbeatIntervalMs;
|
|
904
|
-
if (misses >= this.options.heartbeatsUntilDead) {
|
|
905
|
-
this.log?.info(
|
|
906
|
-
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
907
|
-
this.loggingMetadata
|
|
908
|
-
);
|
|
909
|
-
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
910
|
-
this.conn.close();
|
|
911
|
-
clearInterval(this.heartbeatHandle);
|
|
912
|
-
this.heartbeatHandle = void 0;
|
|
913
|
-
return;
|
|
914
|
-
}
|
|
915
|
-
if (this.isActivelyHeartbeating) {
|
|
916
|
-
this.sendHeartbeat();
|
|
917
|
-
}
|
|
918
|
-
this.heartbeatMisses++;
|
|
919
|
-
}, this.options.heartbeatIntervalMs);
|
|
890
|
+
return { ok: true, value: void 0 };
|
|
920
891
|
}
|
|
921
892
|
get loggingMetadata() {
|
|
922
893
|
return {
|
|
@@ -924,25 +895,46 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
924
895
|
...this.conn.loggingMetadata
|
|
925
896
|
};
|
|
926
897
|
}
|
|
898
|
+
startMissingHeartbeatTimeout() {
|
|
899
|
+
const maxMisses = this.options.heartbeatsUntilDead;
|
|
900
|
+
const missDuration = maxMisses * this.options.heartbeatIntervalMs;
|
|
901
|
+
this.heartbeatMissTimeout = setTimeout(() => {
|
|
902
|
+
this.log?.info(
|
|
903
|
+
`closing connection to ${this.to} due to inactivity (missed ${maxMisses} heartbeats which is ${missDuration}ms)`,
|
|
904
|
+
this.loggingMetadata
|
|
905
|
+
);
|
|
906
|
+
this.telemetry.span.addEvent(
|
|
907
|
+
"closing connection due to missing heartbeat"
|
|
908
|
+
);
|
|
909
|
+
this.conn.close();
|
|
910
|
+
}, missDuration);
|
|
911
|
+
}
|
|
927
912
|
startActiveHeartbeat() {
|
|
928
913
|
this.isActivelyHeartbeating = true;
|
|
914
|
+
this.heartbeatHandle = setInterval(() => {
|
|
915
|
+
this.sendHeartbeat();
|
|
916
|
+
}, this.options.heartbeatIntervalMs);
|
|
929
917
|
}
|
|
930
918
|
sendHeartbeat() {
|
|
931
919
|
this.log?.debug("sending heartbeat", this.loggingMetadata);
|
|
932
|
-
|
|
920
|
+
const heartbeat = {
|
|
933
921
|
streamId: "heartbeat",
|
|
934
922
|
controlFlags: 1 /* AckBit */,
|
|
935
923
|
payload: {
|
|
936
924
|
type: "ACK"
|
|
937
925
|
}
|
|
938
|
-
}
|
|
926
|
+
};
|
|
927
|
+
this.send(heartbeat);
|
|
939
928
|
}
|
|
940
929
|
onMessageData = (msg) => {
|
|
941
|
-
const
|
|
942
|
-
if (
|
|
943
|
-
this.listeners.onInvalidMessage(
|
|
930
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
931
|
+
if (!parsedMsgRes.ok) {
|
|
932
|
+
this.listeners.onInvalidMessage(
|
|
933
|
+
`could not parse message: ${parsedMsgRes.reason}`
|
|
934
|
+
);
|
|
944
935
|
return;
|
|
945
936
|
}
|
|
937
|
+
const parsedMsg = parsedMsgRes.value;
|
|
946
938
|
if (parsedMsg.seq !== this.ack) {
|
|
947
939
|
if (parsedMsg.seq < this.ack) {
|
|
948
940
|
this.log?.debug(
|
|
@@ -981,20 +973,22 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
981
973
|
transportMessage: parsedMsg
|
|
982
974
|
});
|
|
983
975
|
if (!this.isActivelyHeartbeating) {
|
|
984
|
-
|
|
985
|
-
this.sendHeartbeat();
|
|
986
|
-
});
|
|
976
|
+
this.sendHeartbeat();
|
|
987
977
|
}
|
|
988
978
|
};
|
|
989
979
|
_handleStateExit() {
|
|
990
980
|
super._handleStateExit();
|
|
991
|
-
this.conn.removeDataListener(
|
|
992
|
-
this.conn.removeCloseListener(
|
|
993
|
-
this.conn.removeErrorListener(
|
|
981
|
+
this.conn.removeDataListener();
|
|
982
|
+
this.conn.removeCloseListener();
|
|
983
|
+
this.conn.removeErrorListener();
|
|
994
984
|
if (this.heartbeatHandle) {
|
|
995
985
|
clearInterval(this.heartbeatHandle);
|
|
996
986
|
this.heartbeatHandle = void 0;
|
|
997
987
|
}
|
|
988
|
+
if (this.heartbeatMissTimeout) {
|
|
989
|
+
clearTimeout(this.heartbeatMissTimeout);
|
|
990
|
+
this.heartbeatMissTimeout = void 0;
|
|
991
|
+
}
|
|
998
992
|
}
|
|
999
993
|
_handleClose() {
|
|
1000
994
|
super._handleClose();
|
|
@@ -1026,6 +1020,120 @@ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
|
|
|
1026
1020
|
}
|
|
1027
1021
|
};
|
|
1028
1022
|
|
|
1023
|
+
// codec/adapter.ts
|
|
1024
|
+
var import_value = require("@sinclair/typebox/value");
|
|
1025
|
+
|
|
1026
|
+
// transport/connection.ts
|
|
1027
|
+
var Connection = class {
|
|
1028
|
+
id;
|
|
1029
|
+
telemetry;
|
|
1030
|
+
constructor() {
|
|
1031
|
+
this.id = `conn-${generateId()}`;
|
|
1032
|
+
}
|
|
1033
|
+
get loggingMetadata() {
|
|
1034
|
+
const metadata = { connId: this.id };
|
|
1035
|
+
if (this.telemetry?.span.isRecording()) {
|
|
1036
|
+
const spanContext = this.telemetry.span.spanContext();
|
|
1037
|
+
metadata.telemetry = {
|
|
1038
|
+
traceId: spanContext.traceId,
|
|
1039
|
+
spanId: spanContext.spanId
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
return metadata;
|
|
1043
|
+
}
|
|
1044
|
+
dataListener;
|
|
1045
|
+
closeListener;
|
|
1046
|
+
errorListener;
|
|
1047
|
+
onData(msg) {
|
|
1048
|
+
this.dataListener?.(msg);
|
|
1049
|
+
}
|
|
1050
|
+
onError(err) {
|
|
1051
|
+
this.errorListener?.(err);
|
|
1052
|
+
}
|
|
1053
|
+
onClose() {
|
|
1054
|
+
this.closeListener?.();
|
|
1055
|
+
this.telemetry?.span.end();
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Set the callback for when a message is received.
|
|
1059
|
+
* @param cb The message handler callback.
|
|
1060
|
+
*/
|
|
1061
|
+
setDataListener(cb) {
|
|
1062
|
+
this.dataListener = cb;
|
|
1063
|
+
}
|
|
1064
|
+
removeDataListener() {
|
|
1065
|
+
this.dataListener = void 0;
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Set the callback for when the connection is closed.
|
|
1069
|
+
* This should also be called if an error happens and after notifying the error listener.
|
|
1070
|
+
* @param cb The callback to call when the connection is closed.
|
|
1071
|
+
*/
|
|
1072
|
+
setCloseListener(cb) {
|
|
1073
|
+
this.closeListener = cb;
|
|
1074
|
+
}
|
|
1075
|
+
removeCloseListener() {
|
|
1076
|
+
this.closeListener = void 0;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Set the callback for when an error is received.
|
|
1080
|
+
* This should only be used for logging errors, all cleanup
|
|
1081
|
+
* should be delegated to setCloseListener.
|
|
1082
|
+
*
|
|
1083
|
+
* The implementer should take care such that the implemented
|
|
1084
|
+
* connection will call both the close and error callbacks
|
|
1085
|
+
* on an error.
|
|
1086
|
+
*
|
|
1087
|
+
* @param cb The callback to call when an error is received.
|
|
1088
|
+
*/
|
|
1089
|
+
setErrorListener(cb) {
|
|
1090
|
+
this.errorListener = cb;
|
|
1091
|
+
}
|
|
1092
|
+
removeErrorListener() {
|
|
1093
|
+
this.errorListener = void 0;
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
|
|
1097
|
+
// codec/adapter.ts
|
|
1098
|
+
var CodecMessageAdapter = class {
|
|
1099
|
+
constructor(codec) {
|
|
1100
|
+
this.codec = codec;
|
|
1101
|
+
}
|
|
1102
|
+
toBuffer(msg) {
|
|
1103
|
+
try {
|
|
1104
|
+
return {
|
|
1105
|
+
ok: true,
|
|
1106
|
+
value: this.codec.toBuffer(msg)
|
|
1107
|
+
};
|
|
1108
|
+
} catch (e) {
|
|
1109
|
+
return {
|
|
1110
|
+
ok: false,
|
|
1111
|
+
reason: coerceErrorString(e)
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
fromBuffer(buf) {
|
|
1116
|
+
try {
|
|
1117
|
+
const parsedMsg = this.codec.fromBuffer(buf);
|
|
1118
|
+
if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
|
|
1119
|
+
return {
|
|
1120
|
+
ok: false,
|
|
1121
|
+
reason: "transport message schema mismatch"
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
return {
|
|
1125
|
+
ok: true,
|
|
1126
|
+
value: parsedMsg
|
|
1127
|
+
};
|
|
1128
|
+
} catch (e) {
|
|
1129
|
+
return {
|
|
1130
|
+
ok: false,
|
|
1131
|
+
reason: coerceErrorString(e)
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
|
|
1029
1137
|
// transport/sessionStateMachine/transitions.ts
|
|
1030
1138
|
function inheritSharedSession(session) {
|
|
1031
1139
|
return {
|
|
@@ -1040,7 +1148,8 @@ function inheritSharedSession(session) {
|
|
|
1040
1148
|
options: session.options,
|
|
1041
1149
|
log: session.log,
|
|
1042
1150
|
tracer: session.tracer,
|
|
1043
|
-
protocolVersion: session.protocolVersion
|
|
1151
|
+
protocolVersion: session.protocolVersion,
|
|
1152
|
+
codec: session.codec
|
|
1044
1153
|
};
|
|
1045
1154
|
}
|
|
1046
1155
|
function inheritSharedSessionWithGrace(session) {
|
|
@@ -1069,7 +1178,8 @@ var SessionStateGraph = {
|
|
|
1069
1178
|
options,
|
|
1070
1179
|
protocolVersion,
|
|
1071
1180
|
tracer,
|
|
1072
|
-
log
|
|
1181
|
+
log,
|
|
1182
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1073
1183
|
});
|
|
1074
1184
|
session.log?.info(`session ${session.id} created in NoConnection state`, {
|
|
1075
1185
|
...session.loggingMetadata,
|
|
@@ -1084,7 +1194,8 @@ var SessionStateGraph = {
|
|
|
1084
1194
|
from,
|
|
1085
1195
|
options,
|
|
1086
1196
|
tracer,
|
|
1087
|
-
log
|
|
1197
|
+
log,
|
|
1198
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1088
1199
|
});
|
|
1089
1200
|
session.log?.info(`session created in WaitingForHandshake state`, {
|
|
1090
1201
|
...session.loggingMetadata,
|
|
@@ -1162,6 +1273,7 @@ var SessionStateGraph = {
|
|
|
1162
1273
|
listeners,
|
|
1163
1274
|
...carriedState
|
|
1164
1275
|
});
|
|
1276
|
+
session.startMissingHeartbeatTimeout();
|
|
1165
1277
|
session.log?.info(
|
|
1166
1278
|
`session ${session.id} transition from Handshaking to Connected`,
|
|
1167
1279
|
{
|
|
@@ -1197,7 +1309,8 @@ var SessionStateGraph = {
|
|
|
1197
1309
|
options,
|
|
1198
1310
|
tracer: pendingSession.tracer,
|
|
1199
1311
|
log: pendingSession.log,
|
|
1200
|
-
protocolVersion
|
|
1312
|
+
protocolVersion,
|
|
1313
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1201
1314
|
}
|
|
1202
1315
|
);
|
|
1203
1316
|
pendingSession._handleStateExit();
|
|
@@ -1207,6 +1320,7 @@ var SessionStateGraph = {
|
|
|
1207
1320
|
listeners,
|
|
1208
1321
|
...carriedState
|
|
1209
1322
|
});
|
|
1323
|
+
session.startMissingHeartbeatTimeout();
|
|
1210
1324
|
conn.telemetry = createConnectionTelemetryInfo(
|
|
1211
1325
|
session.tracer,
|
|
1212
1326
|
conn,
|
|
@@ -1384,8 +1498,7 @@ var Transport = class {
|
|
|
1384
1498
|
* @param message The received message.
|
|
1385
1499
|
*/
|
|
1386
1500
|
handleMsg(message) {
|
|
1387
|
-
if (this.getStatus() !== "open")
|
|
1388
|
-
return;
|
|
1501
|
+
if (this.getStatus() !== "open") return;
|
|
1389
1502
|
this.eventDispatcher.dispatchEvent("message", message);
|
|
1390
1503
|
}
|
|
1391
1504
|
/**
|
|
@@ -1473,8 +1586,7 @@ var Transport = class {
|
|
|
1473
1586
|
});
|
|
1474
1587
|
}
|
|
1475
1588
|
deleteSession(session, options) {
|
|
1476
|
-
if (session._isConsumed)
|
|
1477
|
-
return;
|
|
1589
|
+
if (session._isConsumed) return;
|
|
1478
1590
|
const loggingMetadata = session.loggingMetadata;
|
|
1479
1591
|
if (loggingMetadata.tags && options?.unhealthy) {
|
|
1480
1592
|
loggingMetadata.tags.push("unhealthy-session");
|
|
@@ -1494,7 +1606,7 @@ var Transport = class {
|
|
|
1494
1606
|
}
|
|
1495
1607
|
// common listeners
|
|
1496
1608
|
onSessionGracePeriodElapsed(session) {
|
|
1497
|
-
this.log?.
|
|
1609
|
+
this.log?.info(
|
|
1498
1610
|
`session to ${session.to} grace period elapsed, closing`,
|
|
1499
1611
|
session.loggingMetadata
|
|
1500
1612
|
);
|
|
@@ -1547,12 +1659,16 @@ var Transport = class {
|
|
|
1547
1659
|
);
|
|
1548
1660
|
}
|
|
1549
1661
|
const sameSession = session.id === sessionId;
|
|
1550
|
-
if (!sameSession) {
|
|
1662
|
+
if (!sameSession || session._isConsumed) {
|
|
1551
1663
|
throw new Error(
|
|
1552
1664
|
`session scope for ${sessionId} has ended (transition), can't send`
|
|
1553
1665
|
);
|
|
1554
1666
|
}
|
|
1555
|
-
|
|
1667
|
+
const res = session.send(msg);
|
|
1668
|
+
if (!res.ok) {
|
|
1669
|
+
throw new Error(res.reason);
|
|
1670
|
+
}
|
|
1671
|
+
return res.value;
|
|
1556
1672
|
};
|
|
1557
1673
|
}
|
|
1558
1674
|
};
|
|
@@ -1753,13 +1869,32 @@ var ClientTransport = class extends Transport {
|
|
|
1753
1869
|
this.handleMsg(msg2);
|
|
1754
1870
|
},
|
|
1755
1871
|
onInvalidMessage: (reason) => {
|
|
1756
|
-
this.
|
|
1872
|
+
this.log?.error(`invalid message: ${reason}`, {
|
|
1873
|
+
...connectedSession.loggingMetadata,
|
|
1874
|
+
transportMessage: msg
|
|
1875
|
+
});
|
|
1757
1876
|
this.protocolError({
|
|
1758
1877
|
type: ProtocolError.InvalidMessage,
|
|
1759
1878
|
message: reason
|
|
1760
1879
|
});
|
|
1880
|
+
this.deleteSession(connectedSession, { unhealthy: true });
|
|
1881
|
+
},
|
|
1882
|
+
onMessageSendFailure: (msg2, reason) => {
|
|
1883
|
+
this.log?.error(`failed to send message: ${reason}`, {
|
|
1884
|
+
...connectedSession.loggingMetadata,
|
|
1885
|
+
transportMessage: msg2
|
|
1886
|
+
});
|
|
1887
|
+
this.protocolError({
|
|
1888
|
+
type: ProtocolError.MessageSendFailure,
|
|
1889
|
+
message: reason
|
|
1890
|
+
});
|
|
1891
|
+
this.deleteSession(connectedSession, { unhealthy: true });
|
|
1761
1892
|
}
|
|
1762
1893
|
});
|
|
1894
|
+
const res = connectedSession.sendBufferedMessages();
|
|
1895
|
+
if (!res.ok) {
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1763
1898
|
this.updateSession(connectedSession);
|
|
1764
1899
|
this.retryBudget.startRestoringBudget();
|
|
1765
1900
|
}
|
|
@@ -1898,7 +2033,18 @@ var ClientTransport = class extends Transport {
|
|
|
1898
2033
|
...session.loggingMetadata,
|
|
1899
2034
|
transportMessage: requestMsg
|
|
1900
2035
|
});
|
|
1901
|
-
session.sendHandshake(requestMsg);
|
|
2036
|
+
const res = session.sendHandshake(requestMsg);
|
|
2037
|
+
if (!res.ok) {
|
|
2038
|
+
this.log?.error(`failed to send handshake request: ${res.reason}`, {
|
|
2039
|
+
...session.loggingMetadata,
|
|
2040
|
+
transportMessage: requestMsg
|
|
2041
|
+
});
|
|
2042
|
+
this.protocolError({
|
|
2043
|
+
type: ProtocolError.MessageSendFailure,
|
|
2044
|
+
message: res.reason
|
|
2045
|
+
});
|
|
2046
|
+
this.deleteSession(session, { unhealthy: true });
|
|
2047
|
+
}
|
|
1902
2048
|
}
|
|
1903
2049
|
close() {
|
|
1904
2050
|
this.retryBudget.close();
|
|
@@ -1906,93 +2052,6 @@ var ClientTransport = class extends Transport {
|
|
|
1906
2052
|
}
|
|
1907
2053
|
};
|
|
1908
2054
|
|
|
1909
|
-
// transport/connection.ts
|
|
1910
|
-
var Connection = class {
|
|
1911
|
-
id;
|
|
1912
|
-
telemetry;
|
|
1913
|
-
constructor() {
|
|
1914
|
-
this.id = `conn-${generateId()}`;
|
|
1915
|
-
}
|
|
1916
|
-
get loggingMetadata() {
|
|
1917
|
-
const metadata = { connId: this.id };
|
|
1918
|
-
if (this.telemetry?.span.isRecording()) {
|
|
1919
|
-
const spanContext = this.telemetry.span.spanContext();
|
|
1920
|
-
metadata.telemetry = {
|
|
1921
|
-
traceId: spanContext.traceId,
|
|
1922
|
-
spanId: spanContext.spanId
|
|
1923
|
-
};
|
|
1924
|
-
}
|
|
1925
|
-
return metadata;
|
|
1926
|
-
}
|
|
1927
|
-
// can't use event emitter because we need this to work in both node + browser
|
|
1928
|
-
_dataListeners = /* @__PURE__ */ new Set();
|
|
1929
|
-
_closeListeners = /* @__PURE__ */ new Set();
|
|
1930
|
-
_errorListeners = /* @__PURE__ */ new Set();
|
|
1931
|
-
get dataListeners() {
|
|
1932
|
-
return [...this._dataListeners];
|
|
1933
|
-
}
|
|
1934
|
-
get closeListeners() {
|
|
1935
|
-
return [...this._closeListeners];
|
|
1936
|
-
}
|
|
1937
|
-
get errorListeners() {
|
|
1938
|
-
return [...this._errorListeners];
|
|
1939
|
-
}
|
|
1940
|
-
onData(msg) {
|
|
1941
|
-
for (const cb of this.dataListeners) {
|
|
1942
|
-
cb(msg);
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
onError(err) {
|
|
1946
|
-
for (const cb of this.errorListeners) {
|
|
1947
|
-
cb(err);
|
|
1948
|
-
}
|
|
1949
|
-
}
|
|
1950
|
-
onClose() {
|
|
1951
|
-
for (const cb of this.closeListeners) {
|
|
1952
|
-
cb();
|
|
1953
|
-
}
|
|
1954
|
-
this.telemetry?.span.end();
|
|
1955
|
-
}
|
|
1956
|
-
/**
|
|
1957
|
-
* Handle adding a callback for when a message is received.
|
|
1958
|
-
* @param msg The message that was received.
|
|
1959
|
-
*/
|
|
1960
|
-
addDataListener(cb) {
|
|
1961
|
-
this._dataListeners.add(cb);
|
|
1962
|
-
}
|
|
1963
|
-
removeDataListener(cb) {
|
|
1964
|
-
this._dataListeners.delete(cb);
|
|
1965
|
-
}
|
|
1966
|
-
/**
|
|
1967
|
-
* Handle adding a callback for when the connection is closed.
|
|
1968
|
-
* This should also be called if an error happens and after notifying all the error listeners.
|
|
1969
|
-
* @param cb The callback to call when the connection is closed.
|
|
1970
|
-
*/
|
|
1971
|
-
addCloseListener(cb) {
|
|
1972
|
-
this._closeListeners.add(cb);
|
|
1973
|
-
}
|
|
1974
|
-
removeCloseListener(cb) {
|
|
1975
|
-
this._closeListeners.delete(cb);
|
|
1976
|
-
}
|
|
1977
|
-
/**
|
|
1978
|
-
* Handle adding a callback for when an error is received.
|
|
1979
|
-
* This should only be used for this.logging errors, all cleanup
|
|
1980
|
-
* should be delegated to addCloseListener.
|
|
1981
|
-
*
|
|
1982
|
-
* The implementer should take care such that the implemented
|
|
1983
|
-
* connection will call both the close and error callbacks
|
|
1984
|
-
* on an error.
|
|
1985
|
-
*
|
|
1986
|
-
* @param cb The callback to call when an error is received.
|
|
1987
|
-
*/
|
|
1988
|
-
addErrorListener(cb) {
|
|
1989
|
-
this._errorListeners.add(cb);
|
|
1990
|
-
}
|
|
1991
|
-
removeErrorListener(cb) {
|
|
1992
|
-
this._errorListeners.delete(cb);
|
|
1993
|
-
}
|
|
1994
|
-
};
|
|
1995
|
-
|
|
1996
2055
|
// transport/impls/ws/connection.ts
|
|
1997
2056
|
var WS_HEALTHY_CLOSE_CODE = 1e3;
|
|
1998
2057
|
var WebSocketConnection = class extends Connection {
|
|
@@ -2028,11 +2087,12 @@ var WebSocketConnection = class extends Connection {
|
|
|
2028
2087
|
};
|
|
2029
2088
|
}
|
|
2030
2089
|
send(payload) {
|
|
2031
|
-
|
|
2090
|
+
try {
|
|
2091
|
+
this.ws.send(payload);
|
|
2092
|
+
return true;
|
|
2093
|
+
} catch {
|
|
2032
2094
|
return false;
|
|
2033
2095
|
}
|
|
2034
|
-
this.ws.send(payload);
|
|
2035
|
-
return true;
|
|
2036
2096
|
}
|
|
2037
2097
|
close() {
|
|
2038
2098
|
this.ws.close(WS_HEALTHY_CLOSE_CODE);
|