@replit/river 0.21.1 → 0.22.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/README.md +1 -1
- package/dist/{chunk-5WFL722S.js → chunk-3MFX6NXA.js} +94 -3
- package/dist/chunk-3MFX6NXA.js.map +1 -0
- package/dist/{chunk-NCXUFDVL.js → chunk-GCLEWC26.js} +328 -500
- package/dist/chunk-GCLEWC26.js.map +1 -0
- package/dist/chunk-HUBFYN37.js +60 -0
- package/dist/chunk-HUBFYN37.js.map +1 -0
- package/dist/{chunk-FDLAPYCK.js → chunk-S3YKQT4J.js} +2 -2
- package/dist/{chunk-JMXO5L2X.js → chunk-ZPBWKBM5.js} +344 -384
- package/dist/chunk-ZPBWKBM5.js.map +1 -0
- package/dist/{connection-76c5ed01.d.ts → connection-8b059ac4.d.ts} +6 -4
- package/dist/{connection-975b25c9.d.ts → connection-bbfe1147.d.ts} +1 -1
- package/dist/{index-dfad460e.d.ts → index-2ece5234.d.ts} +16 -7
- package/dist/logging/index.d.cts +2 -1
- package/dist/logging/index.d.ts +2 -1
- package/dist/router/index.cjs +373 -486
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +5 -4
- package/dist/router/index.d.ts +5 -4
- package/dist/router/index.js +4 -3
- package/dist/{services-7b716dcf.d.ts → services-acbcc441.d.ts} +1 -1
- package/dist/{services-9c496c6e.d.ts → services-cb01a7a8.d.ts} +1 -1
- package/dist/transport/impls/uds/client.cjs +186 -145
- package/dist/transport/impls/uds/client.cjs.map +1 -1
- package/dist/transport/impls/uds/client.d.cts +3 -2
- package/dist/transport/impls/uds/client.d.ts +3 -2
- package/dist/transport/impls/uds/client.js +3 -3
- package/dist/transport/impls/uds/server.cjs +281 -256
- package/dist/transport/impls/uds/server.cjs.map +1 -1
- package/dist/transport/impls/uds/server.d.cts +3 -2
- package/dist/transport/impls/uds/server.d.ts +3 -2
- package/dist/transport/impls/uds/server.js +3 -3
- package/dist/transport/impls/ws/client.cjs +240 -204
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +6 -6
- package/dist/transport/impls/ws/client.d.ts +6 -6
- package/dist/transport/impls/ws/client.js +33 -48
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +303 -270
- 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 +3 -3
- package/dist/transport/impls/ws/server.js.map +1 -1
- package/dist/transport/index.cjs +390 -382
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +5 -5
- package/dist/transport/index.d.ts +5 -5
- package/dist/transport/index.js +2 -2
- package/dist/util/testHelpers.cjs +57 -7
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +14 -5
- package/dist/util/testHelpers.d.ts +14 -5
- package/dist/util/testHelpers.js +10 -4
- package/dist/util/testHelpers.js.map +1 -1
- package/dist/wslike-e0b32dd5.d.ts +40 -0
- package/package.json +4 -5
- package/dist/chunk-3Y7AB5EB.js +0 -42
- package/dist/chunk-3Y7AB5EB.js.map +0 -1
- package/dist/chunk-5WFL722S.js.map +0 -1
- package/dist/chunk-JMXO5L2X.js.map +0 -1
- package/dist/chunk-NCXUFDVL.js.map +0 -1
- /package/dist/{chunk-FDLAPYCK.js.map → chunk-S3YKQT4J.js.map} +0 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// transport/impls/ws/client.ts
|
|
@@ -33,11 +23,9 @@ __export(client_exports, {
|
|
|
33
23
|
WebSocketClientTransport: () => WebSocketClientTransport
|
|
34
24
|
});
|
|
35
25
|
module.exports = __toCommonJS(client_exports);
|
|
36
|
-
var import_agnostic_ws2 = __toESM(require("agnostic-ws"), 1);
|
|
37
26
|
|
|
38
27
|
// transport/transport.ts
|
|
39
28
|
var import_value = require("@sinclair/typebox/value");
|
|
40
|
-
var import_api2 = require("@opentelemetry/api");
|
|
41
29
|
|
|
42
30
|
// transport/message.ts
|
|
43
31
|
var import_typebox = require("@sinclair/typebox");
|
|
@@ -156,17 +144,71 @@ var EventDispatcher = class {
|
|
|
156
144
|
|
|
157
145
|
// transport/session.ts
|
|
158
146
|
var import_nanoid2 = require("nanoid");
|
|
147
|
+
|
|
148
|
+
// tracing/index.ts
|
|
149
|
+
var import_api = require("@opentelemetry/api");
|
|
150
|
+
|
|
151
|
+
// package.json
|
|
152
|
+
var version = "0.22.0";
|
|
153
|
+
|
|
154
|
+
// tracing/index.ts
|
|
155
|
+
function getPropagationContext(ctx) {
|
|
156
|
+
const tracing = {
|
|
157
|
+
traceparent: "",
|
|
158
|
+
tracestate: ""
|
|
159
|
+
};
|
|
160
|
+
import_api.propagation.inject(ctx, tracing);
|
|
161
|
+
return tracing;
|
|
162
|
+
}
|
|
163
|
+
function createSessionTelemetryInfo(session, propagationCtx) {
|
|
164
|
+
const ctx = propagationCtx ? import_api.propagation.extract(import_api.context.active(), propagationCtx) : import_api.context.active();
|
|
165
|
+
const span = tracer.startSpan(
|
|
166
|
+
`session ${session.id}`,
|
|
167
|
+
{
|
|
168
|
+
attributes: {
|
|
169
|
+
component: "river",
|
|
170
|
+
"river.session.id": session.id,
|
|
171
|
+
"river.session.to": session.to,
|
|
172
|
+
"river.session.from": session.from
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
ctx
|
|
176
|
+
);
|
|
177
|
+
return { span, ctx };
|
|
178
|
+
}
|
|
179
|
+
function createConnectionTelemetryInfo(connection, sessionSpan) {
|
|
180
|
+
const ctx = import_api.trace.setSpan(import_api.context.active(), sessionSpan);
|
|
181
|
+
const span = tracer.startSpan(
|
|
182
|
+
`connection ${connection.id}`,
|
|
183
|
+
{
|
|
184
|
+
attributes: {
|
|
185
|
+
component: "river",
|
|
186
|
+
"river.connection.id": connection.id
|
|
187
|
+
},
|
|
188
|
+
links: [{ context: sessionSpan.spanContext() }]
|
|
189
|
+
},
|
|
190
|
+
ctx
|
|
191
|
+
);
|
|
192
|
+
return { span, ctx };
|
|
193
|
+
}
|
|
194
|
+
var tracer = import_api.trace.getTracer("river", version);
|
|
195
|
+
var tracing_default = tracer;
|
|
196
|
+
|
|
197
|
+
// transport/session.ts
|
|
198
|
+
var import_api2 = require("@opentelemetry/api");
|
|
159
199
|
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
160
200
|
var unsafeId = () => nanoid2();
|
|
161
201
|
var Connection = class {
|
|
162
|
-
|
|
202
|
+
id;
|
|
203
|
+
telemetry;
|
|
163
204
|
constructor() {
|
|
164
|
-
this.
|
|
205
|
+
this.id = `conn-${nanoid2(12)}`;
|
|
165
206
|
}
|
|
166
207
|
};
|
|
167
208
|
var Session = class {
|
|
168
209
|
codec;
|
|
169
210
|
options;
|
|
211
|
+
telemetry;
|
|
170
212
|
/**
|
|
171
213
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
172
214
|
*/
|
|
@@ -213,7 +255,7 @@ var Session = class {
|
|
|
213
255
|
* The interval for sending heartbeats.
|
|
214
256
|
*/
|
|
215
257
|
heartbeat;
|
|
216
|
-
constructor(conn, from, to, options) {
|
|
258
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
217
259
|
this.id = `session-${nanoid2(12)}`;
|
|
218
260
|
this.options = options;
|
|
219
261
|
this.from = from;
|
|
@@ -225,13 +267,14 @@ var Session = class {
|
|
|
225
267
|
() => this.sendHeartbeat(),
|
|
226
268
|
options.heartbeatIntervalMs
|
|
227
269
|
);
|
|
270
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
228
271
|
}
|
|
229
272
|
get loggingMetadata() {
|
|
230
273
|
return {
|
|
231
274
|
clientId: this.from,
|
|
232
275
|
connectedTo: this.to,
|
|
233
276
|
sessionId: this.id,
|
|
234
|
-
connId: this.connection?.
|
|
277
|
+
connId: this.connection?.id
|
|
235
278
|
};
|
|
236
279
|
}
|
|
237
280
|
/**
|
|
@@ -276,6 +319,7 @@ var Session = class {
|
|
|
276
319
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
277
320
|
this.loggingMetadata
|
|
278
321
|
);
|
|
322
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
279
323
|
this.closeStaleConnection();
|
|
280
324
|
}
|
|
281
325
|
return;
|
|
@@ -297,21 +341,25 @@ var Session = class {
|
|
|
297
341
|
sendBufferedMessages(conn) {
|
|
298
342
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
299
343
|
...this.loggingMetadata,
|
|
300
|
-
connId: conn.
|
|
344
|
+
connId: conn.id
|
|
301
345
|
});
|
|
302
346
|
for (const msg of this.sendBuffer) {
|
|
303
347
|
log?.debug(`resending msg`, {
|
|
304
348
|
...this.loggingMetadata,
|
|
305
349
|
fullTransportMessage: msg,
|
|
306
|
-
connId: conn.
|
|
350
|
+
connId: conn.id
|
|
307
351
|
});
|
|
308
352
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
309
353
|
if (!ok) {
|
|
310
354
|
const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
|
|
355
|
+
conn.telemetry?.span.setStatus({
|
|
356
|
+
code: import_api2.SpanStatusCode.ERROR,
|
|
357
|
+
message: errMsg
|
|
358
|
+
});
|
|
311
359
|
log?.error(errMsg, {
|
|
312
360
|
...this.loggingMetadata,
|
|
313
361
|
fullTransportMessage: msg,
|
|
314
|
-
connId: conn.
|
|
362
|
+
connId: conn.id,
|
|
315
363
|
tags: ["invariant-violation"]
|
|
316
364
|
});
|
|
317
365
|
conn.close();
|
|
@@ -394,11 +442,6 @@ var Session = class {
|
|
|
394
442
|
}
|
|
395
443
|
};
|
|
396
444
|
|
|
397
|
-
// tracing/index.ts
|
|
398
|
-
var import_api = require("@opentelemetry/api");
|
|
399
|
-
var tracer = import_api.trace.getTracer("river");
|
|
400
|
-
var tracing_default = tracer;
|
|
401
|
-
|
|
402
445
|
// util/stringify.ts
|
|
403
446
|
function coerceErrorString(err) {
|
|
404
447
|
if (err instanceof Error) {
|
|
@@ -531,6 +574,7 @@ var NaiveJsonCodec = {
|
|
|
531
574
|
};
|
|
532
575
|
|
|
533
576
|
// transport/transport.ts
|
|
577
|
+
var import_api3 = require("@opentelemetry/api");
|
|
534
578
|
var defaultTransportOptions = {
|
|
535
579
|
heartbeatIntervalMs: 1e3,
|
|
536
580
|
heartbeatsUntilDead: 2,
|
|
@@ -609,17 +653,22 @@ var Transport = class {
|
|
|
609
653
|
status: "connect",
|
|
610
654
|
conn
|
|
611
655
|
});
|
|
656
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
657
|
+
conn,
|
|
658
|
+
session.telemetry.span
|
|
659
|
+
);
|
|
612
660
|
if (isReconnect) {
|
|
613
661
|
session.replaceWithNewConnection(conn);
|
|
614
662
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
615
663
|
}
|
|
616
664
|
}
|
|
617
|
-
createSession(to, conn) {
|
|
665
|
+
createSession(to, conn, propagationCtx) {
|
|
618
666
|
const session = new Session(
|
|
619
667
|
conn,
|
|
620
668
|
this.clientId,
|
|
621
669
|
to,
|
|
622
|
-
this.options
|
|
670
|
+
this.options,
|
|
671
|
+
propagationCtx
|
|
623
672
|
);
|
|
624
673
|
this.sessions.set(session.to, session);
|
|
625
674
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -628,11 +677,11 @@ var Transport = class {
|
|
|
628
677
|
});
|
|
629
678
|
return session;
|
|
630
679
|
}
|
|
631
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
680
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
632
681
|
let session = this.sessions.get(to);
|
|
633
682
|
let isReconnect = session !== void 0;
|
|
634
683
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
635
|
-
log?.
|
|
684
|
+
log?.info(
|
|
636
685
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
637
686
|
session.loggingMetadata
|
|
638
687
|
);
|
|
@@ -641,7 +690,7 @@ var Transport = class {
|
|
|
641
690
|
session = void 0;
|
|
642
691
|
}
|
|
643
692
|
if (!session) {
|
|
644
|
-
session = this.createSession(to, conn);
|
|
693
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
645
694
|
log?.info(
|
|
646
695
|
`no session for ${to}, created a new one`,
|
|
647
696
|
session.loggingMetadata
|
|
@@ -654,6 +703,7 @@ var Transport = class {
|
|
|
654
703
|
}
|
|
655
704
|
deleteSession(session) {
|
|
656
705
|
session.close();
|
|
706
|
+
session.telemetry.span.end();
|
|
657
707
|
this.sessions.delete(session.to);
|
|
658
708
|
log?.info(
|
|
659
709
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -670,12 +720,16 @@ var Transport = class {
|
|
|
670
720
|
* @param connectedTo The peer we are connected to.
|
|
671
721
|
*/
|
|
672
722
|
onDisconnect(conn, session) {
|
|
723
|
+
conn.telemetry?.span.end();
|
|
673
724
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
674
725
|
status: "disconnect",
|
|
675
726
|
conn
|
|
676
727
|
});
|
|
677
728
|
session.connection = void 0;
|
|
678
|
-
session.beginGrace(() =>
|
|
729
|
+
session.beginGrace(() => {
|
|
730
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
731
|
+
this.deleteSession(session);
|
|
732
|
+
});
|
|
679
733
|
}
|
|
680
734
|
/**
|
|
681
735
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -735,6 +789,10 @@ var Transport = class {
|
|
|
735
789
|
tags: ["invariant-violation"]
|
|
736
790
|
});
|
|
737
791
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
792
|
+
session.telemetry.span.setStatus({
|
|
793
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
794
|
+
message: "message order violated"
|
|
795
|
+
});
|
|
738
796
|
session.close();
|
|
739
797
|
}
|
|
740
798
|
return;
|
|
@@ -862,7 +920,7 @@ var ClientTransport = class extends Transport {
|
|
|
862
920
|
if (!session) {
|
|
863
921
|
log?.warn(
|
|
864
922
|
`connection to ${to} timed out waiting for handshake, closing`,
|
|
865
|
-
{ clientId: this.clientId, connectedTo: to, connId: conn.
|
|
923
|
+
{ clientId: this.clientId, connectedTo: to, connId: conn.id }
|
|
866
924
|
);
|
|
867
925
|
conn.close();
|
|
868
926
|
}
|
|
@@ -880,6 +938,10 @@ var ClientTransport = class extends Transport {
|
|
|
880
938
|
conn.addDataListener((data2) => {
|
|
881
939
|
const parsed = this.parseMsg(data2);
|
|
882
940
|
if (!parsed) {
|
|
941
|
+
conn.telemetry?.span.setStatus({
|
|
942
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
943
|
+
message: "message parse failure"
|
|
944
|
+
});
|
|
883
945
|
conn.close();
|
|
884
946
|
return;
|
|
885
947
|
}
|
|
@@ -902,6 +964,10 @@ var ClientTransport = class extends Transport {
|
|
|
902
964
|
}
|
|
903
965
|
});
|
|
904
966
|
conn.addErrorListener((err) => {
|
|
967
|
+
conn.telemetry?.span.setStatus({
|
|
968
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
969
|
+
message: "connection error"
|
|
970
|
+
});
|
|
905
971
|
log?.warn(`error in connection to ${to}: ${coerceErrorString(err)}`, {
|
|
906
972
|
...session?.loggingMetadata,
|
|
907
973
|
clientId: this.clientId,
|
|
@@ -912,6 +978,10 @@ var ClientTransport = class extends Transport {
|
|
|
912
978
|
receiveHandshakeResponseMessage(data, conn) {
|
|
913
979
|
const parsed = this.parseMsg(data);
|
|
914
980
|
if (!parsed) {
|
|
981
|
+
conn.telemetry?.span.setStatus({
|
|
982
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
983
|
+
message: "non-transport message"
|
|
984
|
+
});
|
|
915
985
|
this.protocolError(
|
|
916
986
|
ProtocolError.HandshakeFailed,
|
|
917
987
|
"received non-transport message"
|
|
@@ -919,6 +989,10 @@ var ClientTransport = class extends Transport {
|
|
|
919
989
|
return false;
|
|
920
990
|
}
|
|
921
991
|
if (!import_value.Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
|
|
992
|
+
conn.telemetry?.span.setStatus({
|
|
993
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
994
|
+
message: "invalid handshake response"
|
|
995
|
+
});
|
|
922
996
|
log?.warn(`received invalid handshake resp`, {
|
|
923
997
|
clientId: this.clientId,
|
|
924
998
|
connectedTo: parsed.from,
|
|
@@ -931,7 +1005,11 @@ var ClientTransport = class extends Transport {
|
|
|
931
1005
|
return false;
|
|
932
1006
|
}
|
|
933
1007
|
if (!parsed.payload.status.ok) {
|
|
934
|
-
|
|
1008
|
+
conn.telemetry?.span.setStatus({
|
|
1009
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1010
|
+
message: "handshake rejected"
|
|
1011
|
+
});
|
|
1012
|
+
log?.warn(`received handshake rejection`, {
|
|
935
1013
|
clientId: this.clientId,
|
|
936
1014
|
connectedTo: parsed.from,
|
|
937
1015
|
fullTransportMessage: parsed
|
|
@@ -961,142 +1039,94 @@ var ClientTransport = class extends Transport {
|
|
|
961
1039
|
* @param to The client ID of the node to connect to.
|
|
962
1040
|
*/
|
|
963
1041
|
async connect(to) {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
span.recordException(coerceErrorString(e));
|
|
981
|
-
}
|
|
982
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
983
|
-
} finally {
|
|
984
|
-
span.end();
|
|
985
|
-
}
|
|
1042
|
+
const canProceedWithConnection = () => this.state === "open";
|
|
1043
|
+
if (!canProceedWithConnection()) {
|
|
1044
|
+
log?.info(
|
|
1045
|
+
`transport state is no longer open, cancelling attempt to connect to ${to}`,
|
|
1046
|
+
{ clientId: this.clientId, connectedTo: to }
|
|
1047
|
+
);
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
let reconnectPromise = this.inflightConnectionPromises.get(to);
|
|
1051
|
+
if (!reconnectPromise) {
|
|
1052
|
+
const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
|
|
1053
|
+
if (!this.retryBudget.hasBudget(to)) {
|
|
1054
|
+
const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
1055
|
+
log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
|
|
1056
|
+
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
1057
|
+
return;
|
|
986
1058
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
{
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
kind: import_api2.SpanKind.CLIENT
|
|
999
|
-
},
|
|
1000
|
-
async (span) => {
|
|
1059
|
+
let sleep = Promise.resolve();
|
|
1060
|
+
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
1061
|
+
if (backoffMs > 0) {
|
|
1062
|
+
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
1063
|
+
}
|
|
1064
|
+
log?.info(`attempting connection to ${to} (${backoffMs}ms backoff)`, {
|
|
1065
|
+
clientId: this.clientId,
|
|
1066
|
+
connectedTo: to
|
|
1067
|
+
});
|
|
1068
|
+
this.retryBudget.consumeBudget(to);
|
|
1069
|
+
reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
|
|
1001
1070
|
try {
|
|
1002
|
-
|
|
1071
|
+
span.addEvent("backoff", { backoffMs });
|
|
1072
|
+
await sleep;
|
|
1003
1073
|
if (!canProceedWithConnection()) {
|
|
1004
|
-
|
|
1005
|
-
`transport state is no longer open, cancelling attempt to connect to ${to}`,
|
|
1006
|
-
{ clientId: this.clientId, connectedTo: to }
|
|
1007
|
-
);
|
|
1008
|
-
return false;
|
|
1074
|
+
throw new Error("transport state is no longer open");
|
|
1009
1075
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
if (!this.retryBudget.hasBudget(to)) {
|
|
1014
|
-
const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
1015
|
-
log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
|
|
1016
|
-
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
1017
|
-
return false;
|
|
1018
|
-
}
|
|
1019
|
-
let sleep = Promise.resolve();
|
|
1020
|
-
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
1021
|
-
if (backoffMs > 0) {
|
|
1022
|
-
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
1023
|
-
}
|
|
1024
|
-
log?.info(
|
|
1025
|
-
`attempting connection to ${to} (${backoffMs}ms backoff)`,
|
|
1026
|
-
{
|
|
1027
|
-
clientId: this.clientId,
|
|
1028
|
-
connectedTo: to
|
|
1029
|
-
}
|
|
1030
|
-
);
|
|
1031
|
-
this.retryBudget.consumeBudget(to);
|
|
1032
|
-
reconnectPromise = sleep.then(() => {
|
|
1033
|
-
if (!canProceedWithConnection()) {
|
|
1034
|
-
throw new Error("transport state is no longer open");
|
|
1035
|
-
}
|
|
1036
|
-
}).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
|
|
1037
|
-
if (!canProceedWithConnection()) {
|
|
1038
|
-
log?.info(
|
|
1039
|
-
`transport state is no longer open, closing pre-handshake connection to ${to}`,
|
|
1040
|
-
{
|
|
1041
|
-
clientId: this.clientId,
|
|
1042
|
-
connectedTo: to,
|
|
1043
|
-
connId: conn.debugId
|
|
1044
|
-
}
|
|
1045
|
-
);
|
|
1046
|
-
conn.close();
|
|
1047
|
-
throw new Error("transport state is no longer open");
|
|
1048
|
-
}
|
|
1049
|
-
return this.sendHandshake(to, conn).then((ok) => {
|
|
1050
|
-
if (!ok) {
|
|
1051
|
-
conn.close();
|
|
1052
|
-
throw new Error("failed to send handshake");
|
|
1053
|
-
}
|
|
1054
|
-
return conn;
|
|
1055
|
-
});
|
|
1056
|
-
});
|
|
1057
|
-
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
1058
|
-
} else {
|
|
1076
|
+
span.addEvent("connecting");
|
|
1077
|
+
const conn = await this.createNewOutgoingConnection(to);
|
|
1078
|
+
if (!canProceedWithConnection()) {
|
|
1059
1079
|
log?.info(
|
|
1060
|
-
`
|
|
1080
|
+
`transport state is no longer open, closing pre-handshake connection to ${to}`,
|
|
1061
1081
|
{
|
|
1062
1082
|
clientId: this.clientId,
|
|
1063
|
-
connectedTo: to
|
|
1083
|
+
connectedTo: to,
|
|
1084
|
+
connId: conn.id
|
|
1064
1085
|
}
|
|
1065
1086
|
);
|
|
1087
|
+
conn.close();
|
|
1088
|
+
throw new Error("transport state is no longer open");
|
|
1066
1089
|
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
1073
|
-
log?.warn(`connection to ${to} failed (${errStr})`, {
|
|
1074
|
-
clientId: this.clientId,
|
|
1075
|
-
connectedTo: to
|
|
1076
|
-
});
|
|
1077
|
-
} else {
|
|
1078
|
-
log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
|
|
1079
|
-
clientId: this.clientId,
|
|
1080
|
-
connectedTo: to
|
|
1081
|
-
});
|
|
1082
|
-
return true;
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
} catch (e) {
|
|
1086
|
-
if (e instanceof Error) {
|
|
1087
|
-
span.recordException(e);
|
|
1088
|
-
} else {
|
|
1089
|
-
span.recordException(coerceErrorString(e));
|
|
1090
|
+
span.addEvent("sending handshake");
|
|
1091
|
+
const ok = await this.sendHandshake(to, conn);
|
|
1092
|
+
if (!ok) {
|
|
1093
|
+
conn.close();
|
|
1094
|
+
throw new Error("failed to send handshake");
|
|
1090
1095
|
}
|
|
1091
|
-
|
|
1096
|
+
return conn;
|
|
1097
|
+
} catch (err) {
|
|
1098
|
+
const errStr = coerceErrorString(err);
|
|
1099
|
+
span.recordException(errStr);
|
|
1100
|
+
span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
|
|
1101
|
+
throw err;
|
|
1092
1102
|
} finally {
|
|
1093
1103
|
span.end();
|
|
1094
1104
|
}
|
|
1095
|
-
|
|
1105
|
+
});
|
|
1106
|
+
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
1107
|
+
} else {
|
|
1108
|
+
log?.info(`attempting connection to ${to} (reusing previous attempt)`, {
|
|
1109
|
+
clientId: this.clientId,
|
|
1110
|
+
connectedTo: to
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
try {
|
|
1114
|
+
await reconnectPromise;
|
|
1115
|
+
} catch (error) {
|
|
1116
|
+
this.inflightConnectionPromises.delete(to);
|
|
1117
|
+
const errStr = coerceErrorString(error);
|
|
1118
|
+
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
1119
|
+
log?.warn(`connection to ${to} failed (${errStr})`, {
|
|
1120
|
+
clientId: this.clientId,
|
|
1121
|
+
connectedTo: to
|
|
1122
|
+
});
|
|
1123
|
+
} else {
|
|
1124
|
+
log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
|
|
1125
|
+
clientId: this.clientId,
|
|
1126
|
+
connectedTo: to
|
|
1127
|
+
});
|
|
1128
|
+
return this.connect(to);
|
|
1096
1129
|
}
|
|
1097
|
-
);
|
|
1098
|
-
if (retry) {
|
|
1099
|
-
return this.connectAttempt(to, attempt + 1);
|
|
1100
1130
|
}
|
|
1101
1131
|
}
|
|
1102
1132
|
deleteSession(session) {
|
|
@@ -1104,8 +1134,6 @@ var ClientTransport = class extends Transport {
|
|
|
1104
1134
|
super.deleteSession(session);
|
|
1105
1135
|
}
|
|
1106
1136
|
async sendHandshake(to, conn) {
|
|
1107
|
-
const tracing = { traceparent: "", tracestate: "" };
|
|
1108
|
-
import_api2.propagation.inject(import_api2.context.active(), tracing);
|
|
1109
1137
|
let metadata;
|
|
1110
1138
|
if (this.options.handshake) {
|
|
1111
1139
|
metadata = await this.options.handshake.get();
|
|
@@ -1119,6 +1147,10 @@ var ClientTransport = class extends Transport {
|
|
|
1119
1147
|
ProtocolError.HandshakeFailed,
|
|
1120
1148
|
"handshake metadata did not match schema"
|
|
1121
1149
|
);
|
|
1150
|
+
conn.telemetry?.span.setStatus({
|
|
1151
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1152
|
+
message: "handshake meta mismatch"
|
|
1153
|
+
});
|
|
1122
1154
|
return false;
|
|
1123
1155
|
}
|
|
1124
1156
|
}
|
|
@@ -1128,7 +1160,7 @@ var ClientTransport = class extends Transport {
|
|
|
1128
1160
|
to,
|
|
1129
1161
|
session.id,
|
|
1130
1162
|
metadata,
|
|
1131
|
-
|
|
1163
|
+
getPropagationContext(session.telemetry.ctx)
|
|
1132
1164
|
);
|
|
1133
1165
|
log?.debug(`sending handshake request to ${to}`, {
|
|
1134
1166
|
clientId: this.clientId,
|
|
@@ -1144,13 +1176,31 @@ var ClientTransport = class extends Transport {
|
|
|
1144
1176
|
};
|
|
1145
1177
|
|
|
1146
1178
|
// transport/impls/ws/connection.ts
|
|
1147
|
-
var import_agnostic_ws = __toESM(require("agnostic-ws"), 1);
|
|
1148
1179
|
var WebSocketConnection = class extends Connection {
|
|
1180
|
+
errorCb = null;
|
|
1181
|
+
closeCb = null;
|
|
1149
1182
|
ws;
|
|
1150
1183
|
constructor(ws) {
|
|
1151
1184
|
super();
|
|
1152
1185
|
this.ws = ws;
|
|
1153
1186
|
this.ws.binaryType = "arraybuffer";
|
|
1187
|
+
let didError = false;
|
|
1188
|
+
this.ws.onerror = () => {
|
|
1189
|
+
didError = true;
|
|
1190
|
+
};
|
|
1191
|
+
this.ws.onclose = ({ code, reason }) => {
|
|
1192
|
+
if (didError && this.errorCb) {
|
|
1193
|
+
this.errorCb(
|
|
1194
|
+
new Error(
|
|
1195
|
+
`websocket closed with code and reason: ${code} - ${reason}`
|
|
1196
|
+
)
|
|
1197
|
+
);
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
if (this.closeCb) {
|
|
1201
|
+
this.closeCb();
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1154
1204
|
}
|
|
1155
1205
|
addDataListener(cb) {
|
|
1156
1206
|
this.ws.onmessage = (msg) => cb(msg.data);
|
|
@@ -1159,13 +1209,13 @@ var WebSocketConnection = class extends Connection {
|
|
|
1159
1209
|
this.ws.onmessage = null;
|
|
1160
1210
|
}
|
|
1161
1211
|
addCloseListener(cb) {
|
|
1162
|
-
this.
|
|
1212
|
+
this.closeCb = cb;
|
|
1163
1213
|
}
|
|
1164
1214
|
addErrorListener(cb) {
|
|
1165
|
-
this.
|
|
1215
|
+
this.errorCb = cb;
|
|
1166
1216
|
}
|
|
1167
1217
|
send(payload) {
|
|
1168
|
-
if (this.ws.readyState ===
|
|
1218
|
+
if (this.ws.readyState === this.ws.OPEN) {
|
|
1169
1219
|
this.ws.send(payload);
|
|
1170
1220
|
return true;
|
|
1171
1221
|
} else {
|
|
@@ -1182,7 +1232,7 @@ var WebSocketClientTransport = class extends ClientTransport {
|
|
|
1182
1232
|
/**
|
|
1183
1233
|
* A function that returns a Promise that resolves to a websocket URL.
|
|
1184
1234
|
*/
|
|
1185
|
-
|
|
1235
|
+
wsGetter;
|
|
1186
1236
|
/**
|
|
1187
1237
|
* Creates a new WebSocketClientTransport instance.
|
|
1188
1238
|
* @param wsGetter A function that returns a Promise that resolves to a WebSocket instance.
|
|
@@ -1190,53 +1240,39 @@ var WebSocketClientTransport = class extends ClientTransport {
|
|
|
1190
1240
|
* @param serverId The ID of the server this transport is connecting to.
|
|
1191
1241
|
* @param providedOptions An optional object containing configuration options for the transport.
|
|
1192
1242
|
*/
|
|
1193
|
-
constructor(
|
|
1243
|
+
constructor(wsGetter, clientId, providedOptions) {
|
|
1194
1244
|
super(clientId, providedOptions);
|
|
1195
|
-
this.
|
|
1245
|
+
this.wsGetter = wsGetter;
|
|
1196
1246
|
}
|
|
1197
1247
|
async createNewOutgoingConnection(to) {
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
connectedTo: to
|
|
1202
|
-
});
|
|
1203
|
-
Promise.resolve(this.urlGetter(to)).then((url) => new import_agnostic_ws2.default(url)).then((ws) => {
|
|
1204
|
-
if (ws.readyState === import_agnostic_ws2.default.OPEN) {
|
|
1205
|
-
resolve({ ws });
|
|
1206
|
-
return;
|
|
1207
|
-
}
|
|
1208
|
-
if (ws.readyState === import_agnostic_ws2.default.CLOSING || ws.readyState === import_agnostic_ws2.default.CLOSED) {
|
|
1209
|
-
resolve({ err: "ws is closing or closed" });
|
|
1210
|
-
return;
|
|
1211
|
-
}
|
|
1212
|
-
ws.onopen = () => {
|
|
1213
|
-
resolve({ ws });
|
|
1214
|
-
};
|
|
1215
|
-
ws.onclose = (evt) => {
|
|
1216
|
-
resolve({ err: evt.reason });
|
|
1217
|
-
};
|
|
1218
|
-
ws.onerror = (evt) => {
|
|
1219
|
-
const err = evt.error;
|
|
1220
|
-
resolve({
|
|
1221
|
-
err: `${err.name}: ${err.message}`
|
|
1222
|
-
});
|
|
1223
|
-
};
|
|
1224
|
-
}).catch((e) => {
|
|
1225
|
-
const reason = e instanceof Error ? e.message : "unknown reason";
|
|
1226
|
-
resolve({ err: `couldn't get a new websocket: ${reason}` });
|
|
1227
|
-
});
|
|
1248
|
+
log?.info(`establishing a new websocket to ${to}`, {
|
|
1249
|
+
clientId: this.clientId,
|
|
1250
|
+
connectedTo: to
|
|
1228
1251
|
});
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1252
|
+
const ws = await this.wsGetter(to);
|
|
1253
|
+
await new Promise((resolve, reject) => {
|
|
1254
|
+
if (ws.readyState === ws.OPEN) {
|
|
1255
|
+
resolve();
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
if (ws.readyState === ws.CLOSING || ws.readyState === ws.CLOSED) {
|
|
1259
|
+
reject(new Error("ws is closing or closed"));
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
ws.onopen = () => {
|
|
1263
|
+
resolve();
|
|
1264
|
+
};
|
|
1265
|
+
ws.onclose = (evt) => {
|
|
1266
|
+
reject(new Error(evt.reason));
|
|
1267
|
+
};
|
|
1268
|
+
});
|
|
1269
|
+
const conn = new WebSocketConnection(ws);
|
|
1270
|
+
log?.info(`raw websocket to ${to} ok, starting handshake`, {
|
|
1271
|
+
clientId: this.clientId,
|
|
1272
|
+
connectedTo: to
|
|
1273
|
+
});
|
|
1274
|
+
this.handleConnection(conn, to);
|
|
1275
|
+
return conn;
|
|
1240
1276
|
}
|
|
1241
1277
|
};
|
|
1242
1278
|
// Annotate the CommonJS export names for ESM import in node:
|