@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
|
@@ -49,60 +49,44 @@ var Connection = class {
|
|
|
49
49
|
}
|
|
50
50
|
return metadata;
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
_errorListeners = /* @__PURE__ */ new Set();
|
|
56
|
-
get dataListeners() {
|
|
57
|
-
return [...this._dataListeners];
|
|
58
|
-
}
|
|
59
|
-
get closeListeners() {
|
|
60
|
-
return [...this._closeListeners];
|
|
61
|
-
}
|
|
62
|
-
get errorListeners() {
|
|
63
|
-
return [...this._errorListeners];
|
|
64
|
-
}
|
|
52
|
+
dataListener;
|
|
53
|
+
closeListener;
|
|
54
|
+
errorListener;
|
|
65
55
|
onData(msg) {
|
|
66
|
-
|
|
67
|
-
cb(msg);
|
|
68
|
-
}
|
|
56
|
+
this.dataListener?.(msg);
|
|
69
57
|
}
|
|
70
58
|
onError(err) {
|
|
71
|
-
|
|
72
|
-
cb(err);
|
|
73
|
-
}
|
|
59
|
+
this.errorListener?.(err);
|
|
74
60
|
}
|
|
75
61
|
onClose() {
|
|
76
|
-
|
|
77
|
-
cb();
|
|
78
|
-
}
|
|
62
|
+
this.closeListener?.();
|
|
79
63
|
this.telemetry?.span.end();
|
|
80
64
|
}
|
|
81
65
|
/**
|
|
82
|
-
*
|
|
83
|
-
* @param
|
|
66
|
+
* Set the callback for when a message is received.
|
|
67
|
+
* @param cb The message handler callback.
|
|
84
68
|
*/
|
|
85
|
-
|
|
86
|
-
this.
|
|
69
|
+
setDataListener(cb) {
|
|
70
|
+
this.dataListener = cb;
|
|
87
71
|
}
|
|
88
|
-
removeDataListener(
|
|
89
|
-
this.
|
|
72
|
+
removeDataListener() {
|
|
73
|
+
this.dataListener = void 0;
|
|
90
74
|
}
|
|
91
75
|
/**
|
|
92
|
-
*
|
|
93
|
-
* This should also be called if an error happens and after notifying
|
|
76
|
+
* Set the callback for when the connection is closed.
|
|
77
|
+
* This should also be called if an error happens and after notifying the error listener.
|
|
94
78
|
* @param cb The callback to call when the connection is closed.
|
|
95
79
|
*/
|
|
96
|
-
|
|
97
|
-
this.
|
|
80
|
+
setCloseListener(cb) {
|
|
81
|
+
this.closeListener = cb;
|
|
98
82
|
}
|
|
99
|
-
removeCloseListener(
|
|
100
|
-
this.
|
|
83
|
+
removeCloseListener() {
|
|
84
|
+
this.closeListener = void 0;
|
|
101
85
|
}
|
|
102
86
|
/**
|
|
103
|
-
*
|
|
104
|
-
* This should only be used for
|
|
105
|
-
* should be delegated to
|
|
87
|
+
* Set the callback for when an error is received.
|
|
88
|
+
* This should only be used for logging errors, all cleanup
|
|
89
|
+
* should be delegated to setCloseListener.
|
|
106
90
|
*
|
|
107
91
|
* The implementer should take care such that the implemented
|
|
108
92
|
* connection will call both the close and error callbacks
|
|
@@ -110,11 +94,11 @@ var Connection = class {
|
|
|
110
94
|
*
|
|
111
95
|
* @param cb The callback to call when an error is received.
|
|
112
96
|
*/
|
|
113
|
-
|
|
114
|
-
this.
|
|
97
|
+
setErrorListener(cb) {
|
|
98
|
+
this.errorListener = cb;
|
|
115
99
|
}
|
|
116
|
-
removeErrorListener(
|
|
117
|
-
this.
|
|
100
|
+
removeErrorListener() {
|
|
101
|
+
this.errorListener = void 0;
|
|
118
102
|
}
|
|
119
103
|
};
|
|
120
104
|
|
|
@@ -153,11 +137,12 @@ var WebSocketConnection = class extends Connection {
|
|
|
153
137
|
};
|
|
154
138
|
}
|
|
155
139
|
send(payload) {
|
|
156
|
-
|
|
140
|
+
try {
|
|
141
|
+
this.ws.send(payload);
|
|
142
|
+
return true;
|
|
143
|
+
} catch {
|
|
157
144
|
return false;
|
|
158
145
|
}
|
|
159
|
-
this.ws.send(payload);
|
|
160
|
-
return true;
|
|
161
146
|
}
|
|
162
147
|
close() {
|
|
163
148
|
this.ws.close(WS_HEALTHY_CLOSE_CODE);
|
|
@@ -314,23 +299,20 @@ var NaiveJsonCodec = {
|
|
|
314
299
|
);
|
|
315
300
|
},
|
|
316
301
|
fromBuffer: (buff) => {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return val;
|
|
325
|
-
}
|
|
302
|
+
const parsed = JSON.parse(
|
|
303
|
+
decoder.decode(buff),
|
|
304
|
+
function reviver(_key, val) {
|
|
305
|
+
if (val?.$t) {
|
|
306
|
+
return base64ToUint8Array(val.$t);
|
|
307
|
+
} else {
|
|
308
|
+
return val;
|
|
326
309
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
} catch {
|
|
332
|
-
return null;
|
|
310
|
+
}
|
|
311
|
+
);
|
|
312
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
313
|
+
throw new Error("unpacked msg is not an object");
|
|
333
314
|
}
|
|
315
|
+
return parsed;
|
|
334
316
|
}
|
|
335
317
|
};
|
|
336
318
|
|
|
@@ -427,7 +409,8 @@ var ProtocolError = {
|
|
|
427
409
|
RetriesExceeded: "conn_retry_exceeded",
|
|
428
410
|
HandshakeFailed: "handshake_failed",
|
|
429
411
|
MessageOrderingViolated: "message_ordering_violated",
|
|
430
|
-
InvalidMessage: "invalid_message"
|
|
412
|
+
InvalidMessage: "invalid_message",
|
|
413
|
+
MessageSendFailure: "message_send_failure"
|
|
431
414
|
};
|
|
432
415
|
var EventDispatcher = class {
|
|
433
416
|
eventListeners = {};
|
|
@@ -461,7 +444,6 @@ var EventDispatcher = class {
|
|
|
461
444
|
};
|
|
462
445
|
|
|
463
446
|
// transport/sessionStateMachine/common.ts
|
|
464
|
-
var import_value = require("@sinclair/typebox/value");
|
|
465
447
|
var ERR_CONSUMED = `session state has been consumed and is no longer valid`;
|
|
466
448
|
var StateMachineState = class {
|
|
467
449
|
/*
|
|
@@ -521,34 +503,16 @@ var StateMachineState = class {
|
|
|
521
503
|
var CommonSession = class extends StateMachineState {
|
|
522
504
|
from;
|
|
523
505
|
options;
|
|
506
|
+
codec;
|
|
524
507
|
tracer;
|
|
525
508
|
log;
|
|
526
|
-
constructor({ from, options, log, tracer }) {
|
|
509
|
+
constructor({ from, options, log, tracer, codec }) {
|
|
527
510
|
super();
|
|
528
511
|
this.from = from;
|
|
529
512
|
this.options = options;
|
|
530
513
|
this.log = log;
|
|
531
514
|
this.tracer = tracer;
|
|
532
|
-
|
|
533
|
-
parseMsg(msg) {
|
|
534
|
-
const parsedMsg = this.options.codec.fromBuffer(msg);
|
|
535
|
-
if (parsedMsg === null) {
|
|
536
|
-
this.log?.error(
|
|
537
|
-
`received malformed msg: ${Buffer.from(msg).toString("base64")}`,
|
|
538
|
-
this.loggingMetadata
|
|
539
|
-
);
|
|
540
|
-
return null;
|
|
541
|
-
}
|
|
542
|
-
if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
|
|
543
|
-
this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {
|
|
544
|
-
...this.loggingMetadata,
|
|
545
|
-
validationErrors: [
|
|
546
|
-
...import_value.Value.Errors(OpaqueTransportMessageSchema, parsedMsg)
|
|
547
|
-
]
|
|
548
|
-
});
|
|
549
|
-
return null;
|
|
550
|
-
}
|
|
551
|
-
return parsedMsg;
|
|
515
|
+
this.codec = codec;
|
|
552
516
|
}
|
|
553
517
|
};
|
|
554
518
|
var IdentifiedSession = class extends CommonSession {
|
|
@@ -608,9 +572,6 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
608
572
|
return metadata;
|
|
609
573
|
}
|
|
610
574
|
constructMsg(partialMsg) {
|
|
611
|
-
if (this._isConsumed) {
|
|
612
|
-
throw new Error(ERR_CONSUMED);
|
|
613
|
-
}
|
|
614
575
|
const msg = {
|
|
615
576
|
...partialMsg,
|
|
616
577
|
id: generateId(),
|
|
@@ -628,7 +589,10 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
628
589
|
send(msg) {
|
|
629
590
|
const constructedMsg = this.constructMsg(msg);
|
|
630
591
|
this.sendBuffer.push(constructedMsg);
|
|
631
|
-
return
|
|
592
|
+
return {
|
|
593
|
+
ok: true,
|
|
594
|
+
value: constructedMsg.id
|
|
595
|
+
};
|
|
632
596
|
}
|
|
633
597
|
_handleStateExit() {
|
|
634
598
|
}
|
|
@@ -660,6 +624,23 @@ var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
|
|
|
660
624
|
super._handleClose();
|
|
661
625
|
}
|
|
662
626
|
};
|
|
627
|
+
function sendMessage(conn, codec, msg) {
|
|
628
|
+
const buff = codec.toBuffer(msg);
|
|
629
|
+
if (!buff.ok) {
|
|
630
|
+
return buff;
|
|
631
|
+
}
|
|
632
|
+
const sent = conn.send(buff.value);
|
|
633
|
+
if (!sent) {
|
|
634
|
+
return {
|
|
635
|
+
ok: false,
|
|
636
|
+
reason: "failed to send message"
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
return {
|
|
640
|
+
ok: true,
|
|
641
|
+
value: msg.id
|
|
642
|
+
};
|
|
643
|
+
}
|
|
663
644
|
|
|
664
645
|
// transport/sessionStateMachine/SessionConnecting.ts
|
|
665
646
|
var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
@@ -673,13 +654,11 @@ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
|
673
654
|
this.listeners = props.listeners;
|
|
674
655
|
this.connPromise.then(
|
|
675
656
|
(conn) => {
|
|
676
|
-
if (this._isConsumed)
|
|
677
|
-
return;
|
|
657
|
+
if (this._isConsumed) return;
|
|
678
658
|
this.listeners.onConnectionEstablished(conn);
|
|
679
659
|
},
|
|
680
660
|
(err) => {
|
|
681
|
-
if (this._isConsumed)
|
|
682
|
-
return;
|
|
661
|
+
if (this._isConsumed) return;
|
|
683
662
|
this.listeners.onConnectionFailed(err);
|
|
684
663
|
}
|
|
685
664
|
);
|
|
@@ -712,8 +691,8 @@ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
|
712
691
|
}
|
|
713
692
|
}
|
|
714
693
|
_handleClose() {
|
|
715
|
-
this.bestEffortClose();
|
|
716
694
|
super._handleClose();
|
|
695
|
+
this.bestEffortClose();
|
|
717
696
|
}
|
|
718
697
|
};
|
|
719
698
|
|
|
@@ -740,13 +719,13 @@ function coerceErrorString(err) {
|
|
|
740
719
|
}
|
|
741
720
|
|
|
742
721
|
// package.json
|
|
743
|
-
var version = "0.
|
|
722
|
+
var version = "0.208.0";
|
|
744
723
|
|
|
745
724
|
// tracing/index.ts
|
|
746
725
|
function createSessionTelemetryInfo(tracer, sessionId, to, from, propagationCtx) {
|
|
747
726
|
const parentCtx = propagationCtx ? import_api2.propagation.extract(import_api2.context.active(), propagationCtx) : import_api2.context.active();
|
|
748
727
|
const span = tracer.startSpan(
|
|
749
|
-
`river.session
|
|
728
|
+
`river.session`,
|
|
750
729
|
{
|
|
751
730
|
attributes: {
|
|
752
731
|
component: "river",
|
|
@@ -762,7 +741,7 @@ function createSessionTelemetryInfo(tracer, sessionId, to, from, propagationCtx)
|
|
|
762
741
|
}
|
|
763
742
|
function createConnectionTelemetryInfo(tracer, connection, info) {
|
|
764
743
|
const span = tracer.startSpan(
|
|
765
|
-
`connection
|
|
744
|
+
`river.connection`,
|
|
766
745
|
{
|
|
767
746
|
attributes: {
|
|
768
747
|
component: "river",
|
|
@@ -792,9 +771,9 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
792
771
|
this.handshakeTimeout = setTimeout(() => {
|
|
793
772
|
this.listeners.onHandshakeTimeout();
|
|
794
773
|
}, this.options.handshakeTimeoutMs);
|
|
795
|
-
this.conn.
|
|
796
|
-
this.conn.
|
|
797
|
-
this.conn.
|
|
774
|
+
this.conn.setDataListener(this.onHandshakeData);
|
|
775
|
+
this.conn.setErrorListener(this.listeners.onConnectionErrored);
|
|
776
|
+
this.conn.setCloseListener(this.listeners.onConnectionClosed);
|
|
798
777
|
}
|
|
799
778
|
get loggingMetadata() {
|
|
800
779
|
return {
|
|
@@ -804,23 +783,23 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
804
783
|
};
|
|
805
784
|
}
|
|
806
785
|
onHandshakeData = (msg) => {
|
|
807
|
-
const
|
|
808
|
-
if (
|
|
786
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
787
|
+
if (!parsedMsgRes.ok) {
|
|
809
788
|
this.listeners.onInvalidHandshake(
|
|
810
|
-
|
|
789
|
+
`could not parse handshake message: ${parsedMsgRes.reason}`,
|
|
811
790
|
"MALFORMED_HANDSHAKE"
|
|
812
791
|
);
|
|
813
792
|
return;
|
|
814
793
|
}
|
|
815
|
-
this.listeners.onHandshake(
|
|
794
|
+
this.listeners.onHandshake(parsedMsgRes.value);
|
|
816
795
|
};
|
|
817
796
|
sendHandshake(msg) {
|
|
818
|
-
return this.conn
|
|
797
|
+
return sendMessage(this.conn, this.codec, msg);
|
|
819
798
|
}
|
|
820
799
|
_handleStateExit() {
|
|
821
|
-
this.conn.removeDataListener(
|
|
822
|
-
this.conn.removeErrorListener(
|
|
823
|
-
this.conn.removeCloseListener(
|
|
800
|
+
this.conn.removeDataListener();
|
|
801
|
+
this.conn.removeErrorListener();
|
|
802
|
+
this.conn.removeCloseListener();
|
|
824
803
|
clearTimeout(this.handshakeTimeout);
|
|
825
804
|
this.handshakeTimeout = void 0;
|
|
826
805
|
}
|
|
@@ -842,9 +821,9 @@ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
|
|
|
842
821
|
this.handshakeTimeout = setTimeout(() => {
|
|
843
822
|
this.listeners.onHandshakeTimeout();
|
|
844
823
|
}, this.options.handshakeTimeoutMs);
|
|
845
|
-
this.conn.
|
|
846
|
-
this.conn.
|
|
847
|
-
this.conn.
|
|
824
|
+
this.conn.setDataListener(this.onHandshakeData);
|
|
825
|
+
this.conn.setErrorListener(this.listeners.onConnectionErrored);
|
|
826
|
+
this.conn.setCloseListener(this.listeners.onConnectionClosed);
|
|
848
827
|
}
|
|
849
828
|
get loggingMetadata() {
|
|
850
829
|
return {
|
|
@@ -853,24 +832,24 @@ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
|
|
|
853
832
|
};
|
|
854
833
|
}
|
|
855
834
|
onHandshakeData = (msg) => {
|
|
856
|
-
const
|
|
857
|
-
if (
|
|
835
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
836
|
+
if (!parsedMsgRes.ok) {
|
|
858
837
|
this.listeners.onInvalidHandshake(
|
|
859
|
-
|
|
838
|
+
`could not parse handshake message: ${parsedMsgRes.reason}`,
|
|
860
839
|
"MALFORMED_HANDSHAKE"
|
|
861
840
|
);
|
|
862
841
|
return;
|
|
863
842
|
}
|
|
864
|
-
this.listeners.onHandshake(
|
|
843
|
+
this.listeners.onHandshake(parsedMsgRes.value);
|
|
865
844
|
};
|
|
866
845
|
sendHandshake(msg) {
|
|
867
|
-
return this.conn
|
|
846
|
+
return sendMessage(this.conn, this.codec, msg);
|
|
868
847
|
}
|
|
869
848
|
_handleStateExit() {
|
|
870
849
|
super._handleStateExit();
|
|
871
|
-
this.conn.removeDataListener(
|
|
872
|
-
this.conn.removeErrorListener(
|
|
873
|
-
this.conn.removeCloseListener(
|
|
850
|
+
this.conn.removeDataListener();
|
|
851
|
+
this.conn.removeErrorListener();
|
|
852
|
+
this.conn.removeCloseListener();
|
|
874
853
|
if (this.handshakeTimeout) {
|
|
875
854
|
clearTimeout(this.handshakeTimeout);
|
|
876
855
|
this.handshakeTimeout = void 0;
|
|
@@ -889,25 +868,15 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
889
868
|
conn;
|
|
890
869
|
listeners;
|
|
891
870
|
heartbeatHandle;
|
|
892
|
-
|
|
893
|
-
isActivelyHeartbeating;
|
|
894
|
-
lastConstructedMsgs = [];
|
|
895
|
-
pushLastConstructedMsgs = (msg) => {
|
|
896
|
-
const trackedMsg = {
|
|
897
|
-
id: msg.id,
|
|
898
|
-
seq: msg.seq,
|
|
899
|
-
streamId: msg.streamId,
|
|
900
|
-
stack: new Error().stack
|
|
901
|
-
};
|
|
902
|
-
this.lastConstructedMsgs.push(trackedMsg);
|
|
903
|
-
if (this.lastConstructedMsgs.length > 10) {
|
|
904
|
-
this.lastConstructedMsgs.shift();
|
|
905
|
-
}
|
|
906
|
-
};
|
|
871
|
+
heartbeatMissTimeout;
|
|
872
|
+
isActivelyHeartbeating = false;
|
|
907
873
|
updateBookkeeping(ack, seq) {
|
|
908
874
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
|
|
909
875
|
this.ack = seq + 1;
|
|
910
|
-
this.
|
|
876
|
+
if (this.heartbeatMissTimeout) {
|
|
877
|
+
clearTimeout(this.heartbeatMissTimeout);
|
|
878
|
+
}
|
|
879
|
+
this.startMissingHeartbeatTimeout();
|
|
911
880
|
}
|
|
912
881
|
assertSendOrdering(constructedMsg) {
|
|
913
882
|
if (constructedMsg.seq > this.seqSent + 1) {
|
|
@@ -915,30 +884,32 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
915
884
|
this.log?.error(msg, {
|
|
916
885
|
...this.loggingMetadata,
|
|
917
886
|
transportMessage: constructedMsg,
|
|
918
|
-
tags: ["invariant-violation"]
|
|
919
|
-
extras: {
|
|
920
|
-
lastConstructedMsgs: this.lastConstructedMsgs
|
|
921
|
-
}
|
|
887
|
+
tags: ["invariant-violation"]
|
|
922
888
|
});
|
|
923
889
|
throw new Error(msg);
|
|
924
890
|
}
|
|
925
891
|
}
|
|
926
892
|
send(msg) {
|
|
927
893
|
const constructedMsg = this.constructMsg(msg);
|
|
928
|
-
this.pushLastConstructedMsgs(constructedMsg);
|
|
929
894
|
this.assertSendOrdering(constructedMsg);
|
|
930
895
|
this.sendBuffer.push(constructedMsg);
|
|
931
|
-
this.conn
|
|
896
|
+
const res = sendMessage(this.conn, this.codec, constructedMsg);
|
|
897
|
+
if (!res.ok) {
|
|
898
|
+
this.listeners.onMessageSendFailure(constructedMsg, res.reason);
|
|
899
|
+
return res;
|
|
900
|
+
}
|
|
932
901
|
this.seqSent = constructedMsg.seq;
|
|
933
|
-
return
|
|
902
|
+
return res;
|
|
934
903
|
}
|
|
935
904
|
constructor(props) {
|
|
936
905
|
super(props);
|
|
937
906
|
this.conn = props.conn;
|
|
938
907
|
this.listeners = props.listeners;
|
|
939
|
-
this.conn.
|
|
940
|
-
this.conn.
|
|
941
|
-
this.conn.
|
|
908
|
+
this.conn.setDataListener(this.onMessageData);
|
|
909
|
+
this.conn.setCloseListener(this.listeners.onConnectionClosed);
|
|
910
|
+
this.conn.setErrorListener(this.listeners.onConnectionErrored);
|
|
911
|
+
}
|
|
912
|
+
sendBufferedMessages() {
|
|
942
913
|
if (this.sendBuffer.length > 0) {
|
|
943
914
|
this.log?.info(
|
|
944
915
|
`sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
|
|
@@ -946,30 +917,15 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
946
917
|
);
|
|
947
918
|
for (const msg of this.sendBuffer) {
|
|
948
919
|
this.assertSendOrdering(msg);
|
|
949
|
-
this.conn
|
|
920
|
+
const res = sendMessage(this.conn, this.codec, msg);
|
|
921
|
+
if (!res.ok) {
|
|
922
|
+
this.listeners.onMessageSendFailure(msg, res.reason);
|
|
923
|
+
return res;
|
|
924
|
+
}
|
|
950
925
|
this.seqSent = msg.seq;
|
|
951
926
|
}
|
|
952
927
|
}
|
|
953
|
-
|
|
954
|
-
this.heartbeatHandle = setInterval(() => {
|
|
955
|
-
const misses = this.heartbeatMisses;
|
|
956
|
-
const missDuration = misses * this.options.heartbeatIntervalMs;
|
|
957
|
-
if (misses >= this.options.heartbeatsUntilDead) {
|
|
958
|
-
this.log?.info(
|
|
959
|
-
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
960
|
-
this.loggingMetadata
|
|
961
|
-
);
|
|
962
|
-
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
963
|
-
this.conn.close();
|
|
964
|
-
clearInterval(this.heartbeatHandle);
|
|
965
|
-
this.heartbeatHandle = void 0;
|
|
966
|
-
return;
|
|
967
|
-
}
|
|
968
|
-
if (this.isActivelyHeartbeating) {
|
|
969
|
-
this.sendHeartbeat();
|
|
970
|
-
}
|
|
971
|
-
this.heartbeatMisses++;
|
|
972
|
-
}, this.options.heartbeatIntervalMs);
|
|
928
|
+
return { ok: true, value: void 0 };
|
|
973
929
|
}
|
|
974
930
|
get loggingMetadata() {
|
|
975
931
|
return {
|
|
@@ -977,25 +933,46 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
977
933
|
...this.conn.loggingMetadata
|
|
978
934
|
};
|
|
979
935
|
}
|
|
936
|
+
startMissingHeartbeatTimeout() {
|
|
937
|
+
const maxMisses = this.options.heartbeatsUntilDead;
|
|
938
|
+
const missDuration = maxMisses * this.options.heartbeatIntervalMs;
|
|
939
|
+
this.heartbeatMissTimeout = setTimeout(() => {
|
|
940
|
+
this.log?.info(
|
|
941
|
+
`closing connection to ${this.to} due to inactivity (missed ${maxMisses} heartbeats which is ${missDuration}ms)`,
|
|
942
|
+
this.loggingMetadata
|
|
943
|
+
);
|
|
944
|
+
this.telemetry.span.addEvent(
|
|
945
|
+
"closing connection due to missing heartbeat"
|
|
946
|
+
);
|
|
947
|
+
this.conn.close();
|
|
948
|
+
}, missDuration);
|
|
949
|
+
}
|
|
980
950
|
startActiveHeartbeat() {
|
|
981
951
|
this.isActivelyHeartbeating = true;
|
|
952
|
+
this.heartbeatHandle = setInterval(() => {
|
|
953
|
+
this.sendHeartbeat();
|
|
954
|
+
}, this.options.heartbeatIntervalMs);
|
|
982
955
|
}
|
|
983
956
|
sendHeartbeat() {
|
|
984
957
|
this.log?.debug("sending heartbeat", this.loggingMetadata);
|
|
985
|
-
|
|
958
|
+
const heartbeat = {
|
|
986
959
|
streamId: "heartbeat",
|
|
987
960
|
controlFlags: 1 /* AckBit */,
|
|
988
961
|
payload: {
|
|
989
962
|
type: "ACK"
|
|
990
963
|
}
|
|
991
|
-
}
|
|
964
|
+
};
|
|
965
|
+
this.send(heartbeat);
|
|
992
966
|
}
|
|
993
967
|
onMessageData = (msg) => {
|
|
994
|
-
const
|
|
995
|
-
if (
|
|
996
|
-
this.listeners.onInvalidMessage(
|
|
968
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
969
|
+
if (!parsedMsgRes.ok) {
|
|
970
|
+
this.listeners.onInvalidMessage(
|
|
971
|
+
`could not parse message: ${parsedMsgRes.reason}`
|
|
972
|
+
);
|
|
997
973
|
return;
|
|
998
974
|
}
|
|
975
|
+
const parsedMsg = parsedMsgRes.value;
|
|
999
976
|
if (parsedMsg.seq !== this.ack) {
|
|
1000
977
|
if (parsedMsg.seq < this.ack) {
|
|
1001
978
|
this.log?.debug(
|
|
@@ -1034,20 +1011,22 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
1034
1011
|
transportMessage: parsedMsg
|
|
1035
1012
|
});
|
|
1036
1013
|
if (!this.isActivelyHeartbeating) {
|
|
1037
|
-
|
|
1038
|
-
this.sendHeartbeat();
|
|
1039
|
-
});
|
|
1014
|
+
this.sendHeartbeat();
|
|
1040
1015
|
}
|
|
1041
1016
|
};
|
|
1042
1017
|
_handleStateExit() {
|
|
1043
1018
|
super._handleStateExit();
|
|
1044
|
-
this.conn.removeDataListener(
|
|
1045
|
-
this.conn.removeCloseListener(
|
|
1046
|
-
this.conn.removeErrorListener(
|
|
1019
|
+
this.conn.removeDataListener();
|
|
1020
|
+
this.conn.removeCloseListener();
|
|
1021
|
+
this.conn.removeErrorListener();
|
|
1047
1022
|
if (this.heartbeatHandle) {
|
|
1048
1023
|
clearInterval(this.heartbeatHandle);
|
|
1049
1024
|
this.heartbeatHandle = void 0;
|
|
1050
1025
|
}
|
|
1026
|
+
if (this.heartbeatMissTimeout) {
|
|
1027
|
+
clearTimeout(this.heartbeatMissTimeout);
|
|
1028
|
+
this.heartbeatMissTimeout = void 0;
|
|
1029
|
+
}
|
|
1051
1030
|
}
|
|
1052
1031
|
_handleClose() {
|
|
1053
1032
|
super._handleClose();
|
|
@@ -1079,6 +1058,47 @@ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
|
|
|
1079
1058
|
}
|
|
1080
1059
|
};
|
|
1081
1060
|
|
|
1061
|
+
// codec/adapter.ts
|
|
1062
|
+
var import_value = require("@sinclair/typebox/value");
|
|
1063
|
+
var CodecMessageAdapter = class {
|
|
1064
|
+
constructor(codec) {
|
|
1065
|
+
this.codec = codec;
|
|
1066
|
+
}
|
|
1067
|
+
toBuffer(msg) {
|
|
1068
|
+
try {
|
|
1069
|
+
return {
|
|
1070
|
+
ok: true,
|
|
1071
|
+
value: this.codec.toBuffer(msg)
|
|
1072
|
+
};
|
|
1073
|
+
} catch (e) {
|
|
1074
|
+
return {
|
|
1075
|
+
ok: false,
|
|
1076
|
+
reason: coerceErrorString(e)
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
fromBuffer(buf) {
|
|
1081
|
+
try {
|
|
1082
|
+
const parsedMsg = this.codec.fromBuffer(buf);
|
|
1083
|
+
if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
|
|
1084
|
+
return {
|
|
1085
|
+
ok: false,
|
|
1086
|
+
reason: "transport message schema mismatch"
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
return {
|
|
1090
|
+
ok: true,
|
|
1091
|
+
value: parsedMsg
|
|
1092
|
+
};
|
|
1093
|
+
} catch (e) {
|
|
1094
|
+
return {
|
|
1095
|
+
ok: false,
|
|
1096
|
+
reason: coerceErrorString(e)
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
|
|
1082
1102
|
// transport/sessionStateMachine/transitions.ts
|
|
1083
1103
|
function inheritSharedSession(session) {
|
|
1084
1104
|
return {
|
|
@@ -1093,7 +1113,8 @@ function inheritSharedSession(session) {
|
|
|
1093
1113
|
options: session.options,
|
|
1094
1114
|
log: session.log,
|
|
1095
1115
|
tracer: session.tracer,
|
|
1096
|
-
protocolVersion: session.protocolVersion
|
|
1116
|
+
protocolVersion: session.protocolVersion,
|
|
1117
|
+
codec: session.codec
|
|
1097
1118
|
};
|
|
1098
1119
|
}
|
|
1099
1120
|
function inheritSharedSessionWithGrace(session) {
|
|
@@ -1122,7 +1143,8 @@ var SessionStateGraph = {
|
|
|
1122
1143
|
options,
|
|
1123
1144
|
protocolVersion,
|
|
1124
1145
|
tracer,
|
|
1125
|
-
log
|
|
1146
|
+
log,
|
|
1147
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1126
1148
|
});
|
|
1127
1149
|
session.log?.info(`session ${session.id} created in NoConnection state`, {
|
|
1128
1150
|
...session.loggingMetadata,
|
|
@@ -1137,7 +1159,8 @@ var SessionStateGraph = {
|
|
|
1137
1159
|
from,
|
|
1138
1160
|
options,
|
|
1139
1161
|
tracer,
|
|
1140
|
-
log
|
|
1162
|
+
log,
|
|
1163
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1141
1164
|
});
|
|
1142
1165
|
session.log?.info(`session created in WaitingForHandshake state`, {
|
|
1143
1166
|
...session.loggingMetadata,
|
|
@@ -1215,6 +1238,7 @@ var SessionStateGraph = {
|
|
|
1215
1238
|
listeners,
|
|
1216
1239
|
...carriedState
|
|
1217
1240
|
});
|
|
1241
|
+
session.startMissingHeartbeatTimeout();
|
|
1218
1242
|
session.log?.info(
|
|
1219
1243
|
`session ${session.id} transition from Handshaking to Connected`,
|
|
1220
1244
|
{
|
|
@@ -1250,7 +1274,8 @@ var SessionStateGraph = {
|
|
|
1250
1274
|
options,
|
|
1251
1275
|
tracer: pendingSession.tracer,
|
|
1252
1276
|
log: pendingSession.log,
|
|
1253
|
-
protocolVersion
|
|
1277
|
+
protocolVersion,
|
|
1278
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1254
1279
|
}
|
|
1255
1280
|
);
|
|
1256
1281
|
pendingSession._handleStateExit();
|
|
@@ -1260,6 +1285,7 @@ var SessionStateGraph = {
|
|
|
1260
1285
|
listeners,
|
|
1261
1286
|
...carriedState
|
|
1262
1287
|
});
|
|
1288
|
+
session.startMissingHeartbeatTimeout();
|
|
1263
1289
|
conn.telemetry = createConnectionTelemetryInfo(
|
|
1264
1290
|
session.tracer,
|
|
1265
1291
|
conn,
|
|
@@ -1437,8 +1463,7 @@ var Transport = class {
|
|
|
1437
1463
|
* @param message The received message.
|
|
1438
1464
|
*/
|
|
1439
1465
|
handleMsg(message) {
|
|
1440
|
-
if (this.getStatus() !== "open")
|
|
1441
|
-
return;
|
|
1466
|
+
if (this.getStatus() !== "open") return;
|
|
1442
1467
|
this.eventDispatcher.dispatchEvent("message", message);
|
|
1443
1468
|
}
|
|
1444
1469
|
/**
|
|
@@ -1526,8 +1551,7 @@ var Transport = class {
|
|
|
1526
1551
|
});
|
|
1527
1552
|
}
|
|
1528
1553
|
deleteSession(session, options) {
|
|
1529
|
-
if (session._isConsumed)
|
|
1530
|
-
return;
|
|
1554
|
+
if (session._isConsumed) return;
|
|
1531
1555
|
const loggingMetadata = session.loggingMetadata;
|
|
1532
1556
|
if (loggingMetadata.tags && options?.unhealthy) {
|
|
1533
1557
|
loggingMetadata.tags.push("unhealthy-session");
|
|
@@ -1547,7 +1571,7 @@ var Transport = class {
|
|
|
1547
1571
|
}
|
|
1548
1572
|
// common listeners
|
|
1549
1573
|
onSessionGracePeriodElapsed(session) {
|
|
1550
|
-
this.log?.
|
|
1574
|
+
this.log?.info(
|
|
1551
1575
|
`session to ${session.to} grace period elapsed, closing`,
|
|
1552
1576
|
session.loggingMetadata
|
|
1553
1577
|
);
|
|
@@ -1600,12 +1624,16 @@ var Transport = class {
|
|
|
1600
1624
|
);
|
|
1601
1625
|
}
|
|
1602
1626
|
const sameSession = session.id === sessionId;
|
|
1603
|
-
if (!sameSession) {
|
|
1627
|
+
if (!sameSession || session._isConsumed) {
|
|
1604
1628
|
throw new Error(
|
|
1605
1629
|
`session scope for ${sessionId} has ended (transition), can't send`
|
|
1606
1630
|
);
|
|
1607
1631
|
}
|
|
1608
|
-
|
|
1632
|
+
const res = session.send(msg);
|
|
1633
|
+
if (!res.ok) {
|
|
1634
|
+
throw new Error(res.reason);
|
|
1635
|
+
}
|
|
1636
|
+
return res.value;
|
|
1609
1637
|
};
|
|
1610
1638
|
}
|
|
1611
1639
|
};
|
|
@@ -1651,8 +1679,7 @@ var ServerTransport = class extends Transport {
|
|
|
1651
1679
|
super.deleteSession(session, options);
|
|
1652
1680
|
}
|
|
1653
1681
|
handleConnection(conn) {
|
|
1654
|
-
if (this.getStatus() !== "open")
|
|
1655
|
-
return;
|
|
1682
|
+
if (this.getStatus() !== "open") return;
|
|
1656
1683
|
this.log?.info(`new incoming connection`, {
|
|
1657
1684
|
...conn.loggingMetadata,
|
|
1658
1685
|
clientId: this.clientId
|
|
@@ -1725,17 +1752,28 @@ var ServerTransport = class extends Transport {
|
|
|
1725
1752
|
message: reason
|
|
1726
1753
|
});
|
|
1727
1754
|
this.log?.warn(reason, metadata);
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
)
|
|
1755
|
+
const responseMsg = handshakeResponseMessage({
|
|
1756
|
+
from: this.clientId,
|
|
1757
|
+
to,
|
|
1758
|
+
status: {
|
|
1759
|
+
ok: false,
|
|
1760
|
+
code,
|
|
1761
|
+
reason
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
const res = session.sendHandshake(responseMsg);
|
|
1765
|
+
if (!res.ok) {
|
|
1766
|
+
this.log?.error(`failed to send handshake response: ${res.reason}`, {
|
|
1767
|
+
...session.loggingMetadata,
|
|
1768
|
+
transportMessage: responseMsg
|
|
1769
|
+
});
|
|
1770
|
+
this.protocolError({
|
|
1771
|
+
type: ProtocolError.MessageSendFailure,
|
|
1772
|
+
message: res.reason
|
|
1773
|
+
});
|
|
1774
|
+
this.deletePendingSession(session);
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1739
1777
|
this.protocolError({
|
|
1740
1778
|
type: ProtocolError.HandshakeFailed,
|
|
1741
1779
|
code,
|
|
@@ -1919,7 +1957,20 @@ var ServerTransport = class extends Transport {
|
|
|
1919
1957
|
sessionId
|
|
1920
1958
|
}
|
|
1921
1959
|
});
|
|
1922
|
-
session.sendHandshake(responseMsg);
|
|
1960
|
+
const res = session.sendHandshake(responseMsg);
|
|
1961
|
+
if (!res.ok) {
|
|
1962
|
+
this.log?.error(`failed to send handshake response: ${res.reason}`, {
|
|
1963
|
+
...session.loggingMetadata,
|
|
1964
|
+
transportMessage: responseMsg
|
|
1965
|
+
});
|
|
1966
|
+
this.protocolError({
|
|
1967
|
+
type: ProtocolError.MessageSendFailure,
|
|
1968
|
+
message: res.reason
|
|
1969
|
+
});
|
|
1970
|
+
this.deletePendingSession(session);
|
|
1971
|
+
return;
|
|
1972
|
+
}
|
|
1973
|
+
this.pendingSessions.delete(session);
|
|
1923
1974
|
const connectedSession = ServerSessionStateGraph.transition.WaitingForHandshakeToConnected(
|
|
1924
1975
|
session,
|
|
1925
1976
|
// by this point oldSession is either no connection or we dont have an old session
|
|
@@ -1946,22 +1997,40 @@ var ServerTransport = class extends Transport {
|
|
|
1946
1997
|
this.handleMsg(msg2);
|
|
1947
1998
|
},
|
|
1948
1999
|
onInvalidMessage: (reason) => {
|
|
2000
|
+
this.log?.error(`invalid message: ${reason}`, {
|
|
2001
|
+
...connectedSession.loggingMetadata,
|
|
2002
|
+
transportMessage: msg
|
|
2003
|
+
});
|
|
1949
2004
|
this.protocolError({
|
|
1950
2005
|
type: ProtocolError.InvalidMessage,
|
|
1951
2006
|
message: reason
|
|
1952
2007
|
});
|
|
1953
2008
|
this.deleteSession(connectedSession, { unhealthy: true });
|
|
2009
|
+
},
|
|
2010
|
+
onMessageSendFailure: (msg2, reason) => {
|
|
2011
|
+
this.log?.error(`failed to send message: ${reason}`, {
|
|
2012
|
+
...connectedSession.loggingMetadata,
|
|
2013
|
+
transportMessage: msg2
|
|
2014
|
+
});
|
|
2015
|
+
this.protocolError({
|
|
2016
|
+
type: ProtocolError.MessageSendFailure,
|
|
2017
|
+
message: reason
|
|
2018
|
+
});
|
|
2019
|
+
this.deleteSession(connectedSession, { unhealthy: true });
|
|
1954
2020
|
}
|
|
1955
2021
|
},
|
|
1956
2022
|
gotVersion
|
|
1957
2023
|
);
|
|
2024
|
+
const bufferSendRes = connectedSession.sendBufferedMessages();
|
|
2025
|
+
if (!bufferSendRes.ok) {
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
1958
2028
|
this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);
|
|
1959
2029
|
if (oldSession) {
|
|
1960
2030
|
this.updateSession(connectedSession);
|
|
1961
2031
|
} else {
|
|
1962
2032
|
this.createSession(connectedSession);
|
|
1963
2033
|
}
|
|
1964
|
-
this.pendingSessions.delete(session);
|
|
1965
2034
|
connectedSession.startActiveHeartbeat();
|
|
1966
2035
|
}
|
|
1967
2036
|
};
|