@replit/river 0.207.1 → 0.207.3
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-f2b6e211.d.ts +46 -0
- package/dist/{chunk-7LMZNSVC.js → chunk-B7REV3ZV.js} +6 -5
- package/dist/{chunk-7LMZNSVC.js.map → chunk-B7REV3ZV.js.map} +1 -1
- package/dist/{chunk-QMAVXV4Z.js → chunk-BO7MFCO6.js} +1136 -132
- package/dist/chunk-BO7MFCO6.js.map +1 -0
- package/dist/{chunk-BCCZA7SX.js → chunk-QGPYCXV4.js} +2 -2
- package/dist/{chunk-BCCZA7SX.js.map → chunk-QGPYCXV4.js.map} +1 -1
- 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-933c87b2.d.ts → connection-06d72f2e.d.ts} +3 -2
- package/dist/index-02554794.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-01c3e85a.d.ts} +1 -35
- package/dist/router/index.cjs +1 -1
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +6 -5
- package/dist/router/index.d.ts +6 -5
- package/dist/router/index.js +1 -1
- package/dist/{services-4cd29829.d.ts → services-87887bc5.d.ts} +16 -11
- package/dist/testUtil/index.cjs +992 -829
- package/dist/testUtil/index.cjs.map +1 -1
- package/dist/testUtil/index.d.cts +4 -3
- package/dist/testUtil/index.d.ts +4 -3
- package/dist/testUtil/index.js +18 -13
- package/dist/testUtil/index.js.map +1 -1
- package/dist/transport/impls/ws/client.cjs +293 -193
- 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 +5 -7
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +230 -117
- 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 -7
- package/dist/transport/impls/ws/server.js.map +1 -1
- package/dist/transport/index.cjs +408 -259
- 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 +4 -9
- package/package.json +1 -1
- package/dist/chunk-AJGIY2UB.js +0 -56
- package/dist/chunk-AJGIY2UB.js.map +0 -1
- package/dist/chunk-CRD3HDVN.js +0 -438
- package/dist/chunk-CRD3HDVN.js.map +0 -1
- package/dist/chunk-I27WBSMZ.js +0 -377
- package/dist/chunk-I27WBSMZ.js.map +0 -1
- package/dist/chunk-QMAVXV4Z.js.map +0 -1
- package/dist/types-3e5768ec.d.ts +0 -20
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { C as ClientTransport, P as ProvidedClientTransportOptions } from '../../../services-
|
|
2
|
-
import { T as TransportClientId } from '../../../message-
|
|
3
|
-
import { W as WebSocketConnection } from '../../../connection-
|
|
1
|
+
import { C as ClientTransport, P as ProvidedClientTransportOptions } from '../../../services-87887bc5.js';
|
|
2
|
+
import { T as TransportClientId } from '../../../message-01c3e85a.js';
|
|
3
|
+
import { W as WebSocketConnection } from '../../../connection-06d72f2e.js';
|
|
4
4
|
import { W as WsLike } from '../../../wslike-e0b32dd5.js';
|
|
5
5
|
import '@sinclair/typebox';
|
|
6
6
|
import '@opentelemetry/api';
|
|
7
|
-
import '../../../
|
|
7
|
+
import '../../../index-02554794.js';
|
|
8
|
+
import '../../../adapter-f2b6e211.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* A transport implementation that uses a WebSocket connection with automatic reconnection.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { C as ClientTransport, P as ProvidedClientTransportOptions } from '../../../services-
|
|
2
|
-
import { T as TransportClientId } from '../../../message-
|
|
3
|
-
import { W as WebSocketConnection } from '../../../connection-
|
|
1
|
+
import { C as ClientTransport, P as ProvidedClientTransportOptions } from '../../../services-87887bc5.js';
|
|
2
|
+
import { T as TransportClientId } from '../../../message-01c3e85a.js';
|
|
3
|
+
import { W as WebSocketConnection } from '../../../connection-06d72f2e.js';
|
|
4
4
|
import { W as WsLike } from '../../../wslike-e0b32dd5.js';
|
|
5
5
|
import '@sinclair/typebox';
|
|
6
6
|
import '@opentelemetry/api';
|
|
7
|
-
import '../../../
|
|
7
|
+
import '../../../index-02554794.js';
|
|
8
|
+
import '../../../adapter-f2b6e211.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* A transport implementation that uses a WebSocket connection with automatic reconnection.
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ClientTransport
|
|
3
|
-
} from "../../../chunk-CRD3HDVN.js";
|
|
4
1
|
import {
|
|
5
2
|
WebSocketConnection
|
|
6
|
-
} from "../../../chunk-
|
|
7
|
-
import
|
|
8
|
-
|
|
3
|
+
} from "../../../chunk-B7REV3ZV.js";
|
|
4
|
+
import {
|
|
5
|
+
ClientTransport
|
|
6
|
+
} from "../../../chunk-BO7MFCO6.js";
|
|
7
|
+
import "../../../chunk-QGPYCXV4.js";
|
|
9
8
|
import "../../../chunk-CC7RN7GI.js";
|
|
10
|
-
import "../../../chunk-AJGIY2UB.js";
|
|
11
9
|
|
|
12
10
|
// transport/impls/ws/client.ts
|
|
13
11
|
var WebSocketClientTransport = class extends ClientTransport {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../transport/impls/ws/client.ts"],"sourcesContent":["import { ClientTransport } from '../../client';\nimport { TransportClientId } from '../../message';\nimport { ProvidedClientTransportOptions } from '../../options';\nimport { WebSocketConnection } from './connection';\nimport { WsLike } from './wslike';\n\n/**\n * A transport implementation that uses a WebSocket connection with automatic reconnection.\n * @class\n * @extends Transport\n */\nexport class WebSocketClientTransport extends ClientTransport<WebSocketConnection> {\n /**\n * A function that returns a Promise that resolves to a websocket URL.\n */\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike;\n\n /**\n * Creates a new WebSocketClientTransport instance.\n * @param wsGetter A function that returns a Promise that resolves to a WebSocket instance.\n * @param clientId The ID of the client using the transport. This should be unique per session.\n * @param serverId The ID of the server this transport is connecting to.\n * @param providedOptions An optional object containing configuration options for the transport.\n */\n constructor(\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike,\n clientId: TransportClientId,\n providedOptions?: ProvidedClientTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.wsGetter = wsGetter;\n }\n\n async createNewOutgoingConnection(to: string) {\n this.log?.info(`establishing a new websocket to ${to}`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n\n const ws = await this.wsGetter(to);\n\n await new Promise<void>((resolve, reject) => {\n if (ws.readyState === ws.OPEN) {\n resolve();\n\n return;\n }\n\n if (ws.readyState === ws.CLOSING || ws.readyState === ws.CLOSED) {\n reject(new Error('ws is closing or closed'));\n\n return;\n }\n\n ws.onopen = () => {\n resolve();\n };\n\n ws.onclose = (evt) => {\n reject(new Error(evt.reason));\n };\n\n ws.onerror = (err) => {\n reject(new Error(err.message));\n };\n });\n\n const conn = new WebSocketConnection(ws);\n this.log?.info(`raw websocket to ${to} ok`, {\n clientId: this.clientId,\n connectedTo: to,\n ...conn.loggingMetadata,\n });\n\n return conn;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../transport/impls/ws/client.ts"],"sourcesContent":["import { ClientTransport } from '../../client';\nimport { TransportClientId } from '../../message';\nimport { ProvidedClientTransportOptions } from '../../options';\nimport { WebSocketConnection } from './connection';\nimport { WsLike } from './wslike';\n\n/**\n * A transport implementation that uses a WebSocket connection with automatic reconnection.\n * @class\n * @extends Transport\n */\nexport class WebSocketClientTransport extends ClientTransport<WebSocketConnection> {\n /**\n * A function that returns a Promise that resolves to a websocket URL.\n */\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike;\n\n /**\n * Creates a new WebSocketClientTransport instance.\n * @param wsGetter A function that returns a Promise that resolves to a WebSocket instance.\n * @param clientId The ID of the client using the transport. This should be unique per session.\n * @param serverId The ID of the server this transport is connecting to.\n * @param providedOptions An optional object containing configuration options for the transport.\n */\n constructor(\n wsGetter: (to: TransportClientId) => Promise<WsLike> | WsLike,\n clientId: TransportClientId,\n providedOptions?: ProvidedClientTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.wsGetter = wsGetter;\n }\n\n async createNewOutgoingConnection(to: string) {\n this.log?.info(`establishing a new websocket to ${to}`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n\n const ws = await this.wsGetter(to);\n\n await new Promise<void>((resolve, reject) => {\n if (ws.readyState === ws.OPEN) {\n resolve();\n\n return;\n }\n\n if (ws.readyState === ws.CLOSING || ws.readyState === ws.CLOSED) {\n reject(new Error('ws is closing or closed'));\n\n return;\n }\n\n ws.onopen = () => {\n resolve();\n };\n\n ws.onclose = (evt) => {\n reject(new Error(evt.reason));\n };\n\n ws.onerror = (err) => {\n reject(new Error(err.message));\n };\n });\n\n const conn = new WebSocketConnection(ws);\n this.log?.info(`raw websocket to ${to} ok`, {\n clientId: this.clientId,\n connectedTo: to,\n ...conn.loggingMetadata,\n });\n\n return conn;\n }\n}\n"],"mappings":";;;;;;;;;;AAWO,IAAM,2BAAN,cAAuC,gBAAqC;AAAA;AAAA;AAAA;AAAA,EAIjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACE,UACA,UACA,iBACA;AACA,UAAM,UAAU,eAAe;AAC/B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAM,4BAA4B,IAAY;AAC5C,SAAK,KAAK,KAAK,mCAAmC,EAAE,IAAI;AAAA,MACtD,UAAU,KAAK;AAAA,MACf,aAAa;AAAA,IACf,CAAC;AAED,UAAM,KAAK,MAAM,KAAK,SAAS,EAAE;AAEjC,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,UAAI,GAAG,eAAe,GAAG,MAAM;AAC7B,gBAAQ;AAER;AAAA,MACF;AAEA,UAAI,GAAG,eAAe,GAAG,WAAW,GAAG,eAAe,GAAG,QAAQ;AAC/D,eAAO,IAAI,MAAM,yBAAyB,CAAC;AAE3C;AAAA,MACF;AAEA,SAAG,SAAS,MAAM;AAChB,gBAAQ;AAAA,MACV;AAEA,SAAG,UAAU,CAAC,QAAQ;AACpB,eAAO,IAAI,MAAM,IAAI,MAAM,CAAC;AAAA,MAC9B;AAEA,SAAG,UAAU,CAAC,QAAQ;AACpB,eAAO,IAAI,MAAM,IAAI,OAAO,CAAC;AAAA,MAC/B;AAAA,IACF,CAAC;AAED,UAAM,OAAO,IAAI,oBAAoB,EAAE;AACvC,SAAK,KAAK,KAAK,oBAAoB,EAAE,OAAO;AAAA,MAC1C,UAAU,KAAK;AAAA,MACf,aAAa;AAAA,MACb,GAAG,KAAK;AAAA,IACV,CAAC;AAED,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -153,11 +153,12 @@ var WebSocketConnection = class extends Connection {
|
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
send(payload) {
|
|
156
|
-
|
|
156
|
+
try {
|
|
157
|
+
this.ws.send(payload);
|
|
158
|
+
return true;
|
|
159
|
+
} catch {
|
|
157
160
|
return false;
|
|
158
161
|
}
|
|
159
|
-
this.ws.send(payload);
|
|
160
|
-
return true;
|
|
161
162
|
}
|
|
162
163
|
close() {
|
|
163
164
|
this.ws.close(WS_HEALTHY_CLOSE_CODE);
|
|
@@ -314,23 +315,20 @@ var NaiveJsonCodec = {
|
|
|
314
315
|
);
|
|
315
316
|
},
|
|
316
317
|
fromBuffer: (buff) => {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return val;
|
|
325
|
-
}
|
|
318
|
+
const parsed = JSON.parse(
|
|
319
|
+
decoder.decode(buff),
|
|
320
|
+
function reviver(_key, val) {
|
|
321
|
+
if (val?.$t) {
|
|
322
|
+
return base64ToUint8Array(val.$t);
|
|
323
|
+
} else {
|
|
324
|
+
return val;
|
|
326
325
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
} catch {
|
|
332
|
-
return null;
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
329
|
+
throw new Error("unpacked msg is not an object");
|
|
333
330
|
}
|
|
331
|
+
return parsed;
|
|
334
332
|
}
|
|
335
333
|
};
|
|
336
334
|
|
|
@@ -427,7 +425,8 @@ var ProtocolError = {
|
|
|
427
425
|
RetriesExceeded: "conn_retry_exceeded",
|
|
428
426
|
HandshakeFailed: "handshake_failed",
|
|
429
427
|
MessageOrderingViolated: "message_ordering_violated",
|
|
430
|
-
InvalidMessage: "invalid_message"
|
|
428
|
+
InvalidMessage: "invalid_message",
|
|
429
|
+
MessageSendFailure: "message_send_failure"
|
|
431
430
|
};
|
|
432
431
|
var EventDispatcher = class {
|
|
433
432
|
eventListeners = {};
|
|
@@ -461,7 +460,6 @@ var EventDispatcher = class {
|
|
|
461
460
|
};
|
|
462
461
|
|
|
463
462
|
// transport/sessionStateMachine/common.ts
|
|
464
|
-
var import_value = require("@sinclair/typebox/value");
|
|
465
463
|
var ERR_CONSUMED = `session state has been consumed and is no longer valid`;
|
|
466
464
|
var StateMachineState = class {
|
|
467
465
|
/*
|
|
@@ -521,34 +519,16 @@ var StateMachineState = class {
|
|
|
521
519
|
var CommonSession = class extends StateMachineState {
|
|
522
520
|
from;
|
|
523
521
|
options;
|
|
522
|
+
codec;
|
|
524
523
|
tracer;
|
|
525
524
|
log;
|
|
526
|
-
constructor({ from, options, log, tracer }) {
|
|
525
|
+
constructor({ from, options, log, tracer, codec }) {
|
|
527
526
|
super();
|
|
528
527
|
this.from = from;
|
|
529
528
|
this.options = options;
|
|
530
529
|
this.log = log;
|
|
531
530
|
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;
|
|
531
|
+
this.codec = codec;
|
|
552
532
|
}
|
|
553
533
|
};
|
|
554
534
|
var IdentifiedSession = class extends CommonSession {
|
|
@@ -608,9 +588,6 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
608
588
|
return metadata;
|
|
609
589
|
}
|
|
610
590
|
constructMsg(partialMsg) {
|
|
611
|
-
if (this._isConsumed) {
|
|
612
|
-
throw new Error(ERR_CONSUMED);
|
|
613
|
-
}
|
|
614
591
|
const msg = {
|
|
615
592
|
...partialMsg,
|
|
616
593
|
id: generateId(),
|
|
@@ -628,7 +605,10 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
628
605
|
send(msg) {
|
|
629
606
|
const constructedMsg = this.constructMsg(msg);
|
|
630
607
|
this.sendBuffer.push(constructedMsg);
|
|
631
|
-
return
|
|
608
|
+
return {
|
|
609
|
+
ok: true,
|
|
610
|
+
value: constructedMsg.id
|
|
611
|
+
};
|
|
632
612
|
}
|
|
633
613
|
_handleStateExit() {
|
|
634
614
|
}
|
|
@@ -660,6 +640,23 @@ var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
|
|
|
660
640
|
super._handleClose();
|
|
661
641
|
}
|
|
662
642
|
};
|
|
643
|
+
function sendMessage(conn, codec, msg) {
|
|
644
|
+
const buff = codec.toBuffer(msg);
|
|
645
|
+
if (!buff.ok) {
|
|
646
|
+
return buff;
|
|
647
|
+
}
|
|
648
|
+
const sent = conn.send(buff.value);
|
|
649
|
+
if (!sent) {
|
|
650
|
+
return {
|
|
651
|
+
ok: false,
|
|
652
|
+
reason: "failed to send message"
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
return {
|
|
656
|
+
ok: true,
|
|
657
|
+
value: msg.id
|
|
658
|
+
};
|
|
659
|
+
}
|
|
663
660
|
|
|
664
661
|
// transport/sessionStateMachine/SessionConnecting.ts
|
|
665
662
|
var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
@@ -712,8 +709,8 @@ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
|
712
709
|
}
|
|
713
710
|
}
|
|
714
711
|
_handleClose() {
|
|
715
|
-
this.bestEffortClose();
|
|
716
712
|
super._handleClose();
|
|
713
|
+
this.bestEffortClose();
|
|
717
714
|
}
|
|
718
715
|
};
|
|
719
716
|
|
|
@@ -740,7 +737,7 @@ function coerceErrorString(err) {
|
|
|
740
737
|
}
|
|
741
738
|
|
|
742
739
|
// package.json
|
|
743
|
-
var version = "0.207.
|
|
740
|
+
var version = "0.207.3";
|
|
744
741
|
|
|
745
742
|
// tracing/index.ts
|
|
746
743
|
function createSessionTelemetryInfo(tracer, sessionId, to, from, propagationCtx) {
|
|
@@ -804,18 +801,18 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
804
801
|
};
|
|
805
802
|
}
|
|
806
803
|
onHandshakeData = (msg) => {
|
|
807
|
-
const
|
|
808
|
-
if (
|
|
804
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
805
|
+
if (!parsedMsgRes.ok) {
|
|
809
806
|
this.listeners.onInvalidHandshake(
|
|
810
|
-
|
|
807
|
+
`could not parse handshake message: ${parsedMsgRes.reason}`,
|
|
811
808
|
"MALFORMED_HANDSHAKE"
|
|
812
809
|
);
|
|
813
810
|
return;
|
|
814
811
|
}
|
|
815
|
-
this.listeners.onHandshake(
|
|
812
|
+
this.listeners.onHandshake(parsedMsgRes.value);
|
|
816
813
|
};
|
|
817
814
|
sendHandshake(msg) {
|
|
818
|
-
return this.conn
|
|
815
|
+
return sendMessage(this.conn, this.codec, msg);
|
|
819
816
|
}
|
|
820
817
|
_handleStateExit() {
|
|
821
818
|
this.conn.removeDataListener(this.onHandshakeData);
|
|
@@ -853,18 +850,18 @@ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
|
|
|
853
850
|
};
|
|
854
851
|
}
|
|
855
852
|
onHandshakeData = (msg) => {
|
|
856
|
-
const
|
|
857
|
-
if (
|
|
853
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
854
|
+
if (!parsedMsgRes.ok) {
|
|
858
855
|
this.listeners.onInvalidHandshake(
|
|
859
|
-
|
|
856
|
+
`could not parse handshake message: ${parsedMsgRes.reason}`,
|
|
860
857
|
"MALFORMED_HANDSHAKE"
|
|
861
858
|
);
|
|
862
859
|
return;
|
|
863
860
|
}
|
|
864
|
-
this.listeners.onHandshake(
|
|
861
|
+
this.listeners.onHandshake(parsedMsgRes.value);
|
|
865
862
|
};
|
|
866
863
|
sendHandshake(msg) {
|
|
867
|
-
return this.conn
|
|
864
|
+
return sendMessage(this.conn, this.codec, msg);
|
|
868
865
|
}
|
|
869
866
|
_handleStateExit() {
|
|
870
867
|
super._handleStateExit();
|
|
@@ -889,12 +886,15 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
889
886
|
conn;
|
|
890
887
|
listeners;
|
|
891
888
|
heartbeatHandle;
|
|
892
|
-
|
|
893
|
-
isActivelyHeartbeating;
|
|
889
|
+
heartbeatMissTimeout;
|
|
890
|
+
isActivelyHeartbeating = false;
|
|
894
891
|
updateBookkeeping(ack, seq) {
|
|
895
892
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
|
|
896
893
|
this.ack = seq + 1;
|
|
897
|
-
this.
|
|
894
|
+
if (this.heartbeatMissTimeout) {
|
|
895
|
+
clearTimeout(this.heartbeatMissTimeout);
|
|
896
|
+
}
|
|
897
|
+
this.startMissingHeartbeatTimeout();
|
|
898
898
|
}
|
|
899
899
|
assertSendOrdering(constructedMsg) {
|
|
900
900
|
if (constructedMsg.seq > this.seqSent + 1) {
|
|
@@ -911,9 +911,13 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
911
911
|
const constructedMsg = this.constructMsg(msg);
|
|
912
912
|
this.assertSendOrdering(constructedMsg);
|
|
913
913
|
this.sendBuffer.push(constructedMsg);
|
|
914
|
-
this.conn
|
|
914
|
+
const res = sendMessage(this.conn, this.codec, constructedMsg);
|
|
915
|
+
if (!res.ok) {
|
|
916
|
+
this.listeners.onMessageSendFailure(constructedMsg, res.reason);
|
|
917
|
+
return res;
|
|
918
|
+
}
|
|
915
919
|
this.seqSent = constructedMsg.seq;
|
|
916
|
-
return
|
|
920
|
+
return res;
|
|
917
921
|
}
|
|
918
922
|
constructor(props) {
|
|
919
923
|
super(props);
|
|
@@ -922,6 +926,8 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
922
926
|
this.conn.addDataListener(this.onMessageData);
|
|
923
927
|
this.conn.addCloseListener(this.listeners.onConnectionClosed);
|
|
924
928
|
this.conn.addErrorListener(this.listeners.onConnectionErrored);
|
|
929
|
+
}
|
|
930
|
+
sendBufferedMessages() {
|
|
925
931
|
if (this.sendBuffer.length > 0) {
|
|
926
932
|
this.log?.info(
|
|
927
933
|
`sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
|
|
@@ -929,30 +935,15 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
929
935
|
);
|
|
930
936
|
for (const msg of this.sendBuffer) {
|
|
931
937
|
this.assertSendOrdering(msg);
|
|
932
|
-
this.conn
|
|
938
|
+
const res = sendMessage(this.conn, this.codec, msg);
|
|
939
|
+
if (!res.ok) {
|
|
940
|
+
this.listeners.onMessageSendFailure(msg, res.reason);
|
|
941
|
+
return res;
|
|
942
|
+
}
|
|
933
943
|
this.seqSent = msg.seq;
|
|
934
944
|
}
|
|
935
945
|
}
|
|
936
|
-
|
|
937
|
-
this.heartbeatHandle = setInterval(() => {
|
|
938
|
-
const misses = this.heartbeatMisses;
|
|
939
|
-
const missDuration = misses * this.options.heartbeatIntervalMs;
|
|
940
|
-
if (misses >= this.options.heartbeatsUntilDead) {
|
|
941
|
-
this.log?.info(
|
|
942
|
-
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
943
|
-
this.loggingMetadata
|
|
944
|
-
);
|
|
945
|
-
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
946
|
-
this.conn.close();
|
|
947
|
-
clearInterval(this.heartbeatHandle);
|
|
948
|
-
this.heartbeatHandle = void 0;
|
|
949
|
-
return;
|
|
950
|
-
}
|
|
951
|
-
if (this.isActivelyHeartbeating) {
|
|
952
|
-
this.sendHeartbeat();
|
|
953
|
-
}
|
|
954
|
-
this.heartbeatMisses++;
|
|
955
|
-
}, this.options.heartbeatIntervalMs);
|
|
946
|
+
return { ok: true, value: void 0 };
|
|
956
947
|
}
|
|
957
948
|
get loggingMetadata() {
|
|
958
949
|
return {
|
|
@@ -960,31 +951,46 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
960
951
|
...this.conn.loggingMetadata
|
|
961
952
|
};
|
|
962
953
|
}
|
|
954
|
+
startMissingHeartbeatTimeout() {
|
|
955
|
+
const maxMisses = this.options.heartbeatsUntilDead;
|
|
956
|
+
const missDuration = maxMisses * this.options.heartbeatIntervalMs;
|
|
957
|
+
this.heartbeatMissTimeout = setTimeout(() => {
|
|
958
|
+
this.log?.info(
|
|
959
|
+
`closing connection to ${this.to} due to inactivity (missed ${maxMisses} heartbeats which is ${missDuration}ms)`,
|
|
960
|
+
this.loggingMetadata
|
|
961
|
+
);
|
|
962
|
+
this.telemetry.span.addEvent(
|
|
963
|
+
"closing connection due to missing heartbeat"
|
|
964
|
+
);
|
|
965
|
+
this.conn.close();
|
|
966
|
+
}, missDuration);
|
|
967
|
+
}
|
|
963
968
|
startActiveHeartbeat() {
|
|
964
969
|
this.isActivelyHeartbeating = true;
|
|
970
|
+
this.heartbeatHandle = setInterval(() => {
|
|
971
|
+
this.sendHeartbeat();
|
|
972
|
+
}, this.options.heartbeatIntervalMs);
|
|
965
973
|
}
|
|
966
974
|
sendHeartbeat() {
|
|
967
975
|
this.log?.debug("sending heartbeat", this.loggingMetadata);
|
|
968
|
-
|
|
976
|
+
const heartbeat = {
|
|
969
977
|
streamId: "heartbeat",
|
|
970
978
|
controlFlags: 1 /* AckBit */,
|
|
971
979
|
payload: {
|
|
972
980
|
type: "ACK"
|
|
973
981
|
}
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
closeConnection() {
|
|
977
|
-
this.conn.removeDataListener(this.onMessageData);
|
|
978
|
-
this.conn.removeCloseListener(this.listeners.onConnectionClosed);
|
|
979
|
-
this.conn.removeErrorListener(this.listeners.onConnectionErrored);
|
|
980
|
-
this.conn.close();
|
|
982
|
+
};
|
|
983
|
+
this.send(heartbeat);
|
|
981
984
|
}
|
|
982
985
|
onMessageData = (msg) => {
|
|
983
|
-
const
|
|
984
|
-
if (
|
|
985
|
-
this.listeners.onInvalidMessage(
|
|
986
|
+
const parsedMsgRes = this.codec.fromBuffer(msg);
|
|
987
|
+
if (!parsedMsgRes.ok) {
|
|
988
|
+
this.listeners.onInvalidMessage(
|
|
989
|
+
`could not parse message: ${parsedMsgRes.reason}`
|
|
990
|
+
);
|
|
986
991
|
return;
|
|
987
992
|
}
|
|
993
|
+
const parsedMsg = parsedMsgRes.value;
|
|
988
994
|
if (parsedMsg.seq !== this.ack) {
|
|
989
995
|
if (parsedMsg.seq < this.ack) {
|
|
990
996
|
this.log?.debug(
|
|
@@ -1005,7 +1011,7 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
1005
1011
|
code: import_api3.SpanStatusCode.ERROR,
|
|
1006
1012
|
message: reason
|
|
1007
1013
|
});
|
|
1008
|
-
this.
|
|
1014
|
+
this.conn.close();
|
|
1009
1015
|
}
|
|
1010
1016
|
return;
|
|
1011
1017
|
}
|
|
@@ -1023,9 +1029,7 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
1023
1029
|
transportMessage: parsedMsg
|
|
1024
1030
|
});
|
|
1025
1031
|
if (!this.isActivelyHeartbeating) {
|
|
1026
|
-
|
|
1027
|
-
this.sendHeartbeat();
|
|
1028
|
-
});
|
|
1032
|
+
this.sendHeartbeat();
|
|
1029
1033
|
}
|
|
1030
1034
|
};
|
|
1031
1035
|
_handleStateExit() {
|
|
@@ -1037,6 +1041,10 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
1037
1041
|
clearInterval(this.heartbeatHandle);
|
|
1038
1042
|
this.heartbeatHandle = void 0;
|
|
1039
1043
|
}
|
|
1044
|
+
if (this.heartbeatMissTimeout) {
|
|
1045
|
+
clearTimeout(this.heartbeatMissTimeout);
|
|
1046
|
+
this.heartbeatMissTimeout = void 0;
|
|
1047
|
+
}
|
|
1040
1048
|
}
|
|
1041
1049
|
_handleClose() {
|
|
1042
1050
|
super._handleClose();
|
|
@@ -1068,6 +1076,47 @@ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
|
|
|
1068
1076
|
}
|
|
1069
1077
|
};
|
|
1070
1078
|
|
|
1079
|
+
// codec/adapter.ts
|
|
1080
|
+
var import_value = require("@sinclair/typebox/value");
|
|
1081
|
+
var CodecMessageAdapter = class {
|
|
1082
|
+
constructor(codec) {
|
|
1083
|
+
this.codec = codec;
|
|
1084
|
+
}
|
|
1085
|
+
toBuffer(msg) {
|
|
1086
|
+
try {
|
|
1087
|
+
return {
|
|
1088
|
+
ok: true,
|
|
1089
|
+
value: this.codec.toBuffer(msg)
|
|
1090
|
+
};
|
|
1091
|
+
} catch (e) {
|
|
1092
|
+
return {
|
|
1093
|
+
ok: false,
|
|
1094
|
+
reason: coerceErrorString(e)
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
fromBuffer(buf) {
|
|
1099
|
+
try {
|
|
1100
|
+
const parsedMsg = this.codec.fromBuffer(buf);
|
|
1101
|
+
if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
|
|
1102
|
+
return {
|
|
1103
|
+
ok: false,
|
|
1104
|
+
reason: "transport message schema mismatch"
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
return {
|
|
1108
|
+
ok: true,
|
|
1109
|
+
value: parsedMsg
|
|
1110
|
+
};
|
|
1111
|
+
} catch (e) {
|
|
1112
|
+
return {
|
|
1113
|
+
ok: false,
|
|
1114
|
+
reason: coerceErrorString(e)
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1071
1120
|
// transport/sessionStateMachine/transitions.ts
|
|
1072
1121
|
function inheritSharedSession(session) {
|
|
1073
1122
|
return {
|
|
@@ -1082,7 +1131,8 @@ function inheritSharedSession(session) {
|
|
|
1082
1131
|
options: session.options,
|
|
1083
1132
|
log: session.log,
|
|
1084
1133
|
tracer: session.tracer,
|
|
1085
|
-
protocolVersion: session.protocolVersion
|
|
1134
|
+
protocolVersion: session.protocolVersion,
|
|
1135
|
+
codec: session.codec
|
|
1086
1136
|
};
|
|
1087
1137
|
}
|
|
1088
1138
|
function inheritSharedSessionWithGrace(session) {
|
|
@@ -1111,7 +1161,8 @@ var SessionStateGraph = {
|
|
|
1111
1161
|
options,
|
|
1112
1162
|
protocolVersion,
|
|
1113
1163
|
tracer,
|
|
1114
|
-
log
|
|
1164
|
+
log,
|
|
1165
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1115
1166
|
});
|
|
1116
1167
|
session.log?.info(`session ${session.id} created in NoConnection state`, {
|
|
1117
1168
|
...session.loggingMetadata,
|
|
@@ -1126,7 +1177,8 @@ var SessionStateGraph = {
|
|
|
1126
1177
|
from,
|
|
1127
1178
|
options,
|
|
1128
1179
|
tracer,
|
|
1129
|
-
log
|
|
1180
|
+
log,
|
|
1181
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1130
1182
|
});
|
|
1131
1183
|
session.log?.info(`session created in WaitingForHandshake state`, {
|
|
1132
1184
|
...session.loggingMetadata,
|
|
@@ -1204,6 +1256,7 @@ var SessionStateGraph = {
|
|
|
1204
1256
|
listeners,
|
|
1205
1257
|
...carriedState
|
|
1206
1258
|
});
|
|
1259
|
+
session.startMissingHeartbeatTimeout();
|
|
1207
1260
|
session.log?.info(
|
|
1208
1261
|
`session ${session.id} transition from Handshaking to Connected`,
|
|
1209
1262
|
{
|
|
@@ -1239,7 +1292,8 @@ var SessionStateGraph = {
|
|
|
1239
1292
|
options,
|
|
1240
1293
|
tracer: pendingSession.tracer,
|
|
1241
1294
|
log: pendingSession.log,
|
|
1242
|
-
protocolVersion
|
|
1295
|
+
protocolVersion,
|
|
1296
|
+
codec: new CodecMessageAdapter(options.codec)
|
|
1243
1297
|
}
|
|
1244
1298
|
);
|
|
1245
1299
|
pendingSession._handleStateExit();
|
|
@@ -1249,6 +1303,7 @@ var SessionStateGraph = {
|
|
|
1249
1303
|
listeners,
|
|
1250
1304
|
...carriedState
|
|
1251
1305
|
});
|
|
1306
|
+
session.startMissingHeartbeatTimeout();
|
|
1252
1307
|
conn.telemetry = createConnectionTelemetryInfo(
|
|
1253
1308
|
session.tracer,
|
|
1254
1309
|
conn,
|
|
@@ -1589,12 +1644,16 @@ var Transport = class {
|
|
|
1589
1644
|
);
|
|
1590
1645
|
}
|
|
1591
1646
|
const sameSession = session.id === sessionId;
|
|
1592
|
-
if (!sameSession) {
|
|
1647
|
+
if (!sameSession || session._isConsumed) {
|
|
1593
1648
|
throw new Error(
|
|
1594
1649
|
`session scope for ${sessionId} has ended (transition), can't send`
|
|
1595
1650
|
);
|
|
1596
1651
|
}
|
|
1597
|
-
|
|
1652
|
+
const res = session.send(msg);
|
|
1653
|
+
if (!res.ok) {
|
|
1654
|
+
throw new Error(res.reason);
|
|
1655
|
+
}
|
|
1656
|
+
return res.value;
|
|
1598
1657
|
};
|
|
1599
1658
|
}
|
|
1600
1659
|
};
|
|
@@ -1714,17 +1773,28 @@ var ServerTransport = class extends Transport {
|
|
|
1714
1773
|
message: reason
|
|
1715
1774
|
});
|
|
1716
1775
|
this.log?.warn(reason, metadata);
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
)
|
|
1776
|
+
const responseMsg = handshakeResponseMessage({
|
|
1777
|
+
from: this.clientId,
|
|
1778
|
+
to,
|
|
1779
|
+
status: {
|
|
1780
|
+
ok: false,
|
|
1781
|
+
code,
|
|
1782
|
+
reason
|
|
1783
|
+
}
|
|
1784
|
+
});
|
|
1785
|
+
const res = session.sendHandshake(responseMsg);
|
|
1786
|
+
if (!res.ok) {
|
|
1787
|
+
this.log?.error(`failed to send handshake response: ${res.reason}`, {
|
|
1788
|
+
...session.loggingMetadata,
|
|
1789
|
+
transportMessage: responseMsg
|
|
1790
|
+
});
|
|
1791
|
+
this.protocolError({
|
|
1792
|
+
type: ProtocolError.MessageSendFailure,
|
|
1793
|
+
message: res.reason
|
|
1794
|
+
});
|
|
1795
|
+
this.deletePendingSession(session);
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1728
1798
|
this.protocolError({
|
|
1729
1799
|
type: ProtocolError.HandshakeFailed,
|
|
1730
1800
|
code,
|
|
@@ -1908,7 +1978,20 @@ var ServerTransport = class extends Transport {
|
|
|
1908
1978
|
sessionId
|
|
1909
1979
|
}
|
|
1910
1980
|
});
|
|
1911
|
-
session.sendHandshake(responseMsg);
|
|
1981
|
+
const res = session.sendHandshake(responseMsg);
|
|
1982
|
+
if (!res.ok) {
|
|
1983
|
+
this.log?.error(`failed to send handshake response: ${res.reason}`, {
|
|
1984
|
+
...session.loggingMetadata,
|
|
1985
|
+
transportMessage: responseMsg
|
|
1986
|
+
});
|
|
1987
|
+
this.protocolError({
|
|
1988
|
+
type: ProtocolError.MessageSendFailure,
|
|
1989
|
+
message: res.reason
|
|
1990
|
+
});
|
|
1991
|
+
this.deletePendingSession(session);
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
this.pendingSessions.delete(session);
|
|
1912
1995
|
const connectedSession = ServerSessionStateGraph.transition.WaitingForHandshakeToConnected(
|
|
1913
1996
|
session,
|
|
1914
1997
|
// by this point oldSession is either no connection or we dont have an old session
|
|
@@ -1935,22 +2018,52 @@ var ServerTransport = class extends Transport {
|
|
|
1935
2018
|
this.handleMsg(msg2);
|
|
1936
2019
|
},
|
|
1937
2020
|
onInvalidMessage: (reason) => {
|
|
2021
|
+
this.log?.error(`invalid message: ${reason}`, {
|
|
2022
|
+
...connectedSession.loggingMetadata,
|
|
2023
|
+
transportMessage: msg
|
|
2024
|
+
});
|
|
1938
2025
|
this.protocolError({
|
|
1939
2026
|
type: ProtocolError.InvalidMessage,
|
|
1940
2027
|
message: reason
|
|
1941
2028
|
});
|
|
1942
2029
|
this.deleteSession(connectedSession, { unhealthy: true });
|
|
2030
|
+
},
|
|
2031
|
+
onMessageSendFailure: (msg2, reason) => {
|
|
2032
|
+
this.log?.error(`failed to send message: ${reason}`, {
|
|
2033
|
+
...connectedSession.loggingMetadata,
|
|
2034
|
+
transportMessage: msg2
|
|
2035
|
+
});
|
|
2036
|
+
this.protocolError({
|
|
2037
|
+
type: ProtocolError.MessageSendFailure,
|
|
2038
|
+
message: reason
|
|
2039
|
+
});
|
|
2040
|
+
this.deleteSession(connectedSession, { unhealthy: true });
|
|
1943
2041
|
}
|
|
1944
2042
|
},
|
|
1945
2043
|
gotVersion
|
|
1946
2044
|
);
|
|
2045
|
+
const bufferSendRes = connectedSession.sendBufferedMessages();
|
|
2046
|
+
if (!bufferSendRes.ok) {
|
|
2047
|
+
this.log?.error(
|
|
2048
|
+
`failed to send buffered messages: ${bufferSendRes.reason}`,
|
|
2049
|
+
{
|
|
2050
|
+
...connectedSession.loggingMetadata,
|
|
2051
|
+
transportMessage: msg
|
|
2052
|
+
}
|
|
2053
|
+
);
|
|
2054
|
+
this.protocolError({
|
|
2055
|
+
type: ProtocolError.MessageSendFailure,
|
|
2056
|
+
message: bufferSendRes.reason
|
|
2057
|
+
});
|
|
2058
|
+
this.deleteSession(connectedSession, { unhealthy: true });
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
1947
2061
|
this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);
|
|
1948
2062
|
if (oldSession) {
|
|
1949
2063
|
this.updateSession(connectedSession);
|
|
1950
2064
|
} else {
|
|
1951
2065
|
this.createSession(connectedSession);
|
|
1952
2066
|
}
|
|
1953
|
-
this.pendingSessions.delete(session);
|
|
1954
2067
|
connectedSession.startActiveHeartbeat();
|
|
1955
2068
|
}
|
|
1956
2069
|
};
|