@replit/river 0.21.1 → 0.23.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-FDLAPYCK.js → chunk-DZOATC6M.js} +2 -2
- package/dist/{chunk-JMXO5L2X.js → chunk-MJUFKPBT.js} +354 -398
- package/dist/chunk-MJUFKPBT.js.map +1 -0
- package/dist/{chunk-5WFL722S.js → chunk-PCKHBAVP.js} +94 -3
- package/dist/chunk-PCKHBAVP.js.map +1 -0
- package/dist/{chunk-NCXUFDVL.js → chunk-VOJVLWVX.js} +360 -516
- package/dist/chunk-VOJVLWVX.js.map +1 -0
- package/dist/chunk-ZF2UFTNN.js +60 -0
- package/dist/chunk-ZF2UFTNN.js.map +1 -0
- package/dist/{connection-76c5ed01.d.ts → connection-5685d817.d.ts} +6 -4
- package/dist/{connection-975b25c9.d.ts → connection-7582fb92.d.ts} +1 -1
- package/dist/{index-dfad460e.d.ts → index-a6fe0edd.d.ts} +55 -59
- package/dist/logging/index.d.cts +2 -1
- package/dist/logging/index.d.ts +2 -1
- package/dist/router/index.cjs +405 -502
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +12 -6
- package/dist/router/index.d.ts +12 -6
- package/dist/router/index.js +4 -3
- package/dist/{services-9c496c6e.d.ts → services-be91b485.d.ts} +21 -52
- package/dist/{services-7b716dcf.d.ts → services-eb9326a1.d.ts} +21 -52
- package/dist/transport/impls/uds/client.cjs +197 -155
- 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 +280 -266
- 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 +251 -214
- 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 +302 -280
- 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 +400 -396
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +25 -14
- package/dist/transport/index.d.ts +25 -14
- package/dist/transport/index.js +2 -2
- package/dist/util/testHelpers.cjs +59 -14
- 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 +12 -5
- 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-DZOATC6M.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.23.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
|
*/
|
|
@@ -186,12 +228,6 @@ var Session = class {
|
|
|
186
228
|
* for this session.
|
|
187
229
|
*/
|
|
188
230
|
advertisedSessionId;
|
|
189
|
-
/**
|
|
190
|
-
* The metadata for this session, as parsed from the handshake.
|
|
191
|
-
*
|
|
192
|
-
* Will only ever be populated on the server side.
|
|
193
|
-
*/
|
|
194
|
-
metadata;
|
|
195
231
|
/**
|
|
196
232
|
* Number of messages we've sent along this session (excluding handshake and acks)
|
|
197
233
|
*/
|
|
@@ -213,7 +249,7 @@ var Session = class {
|
|
|
213
249
|
* The interval for sending heartbeats.
|
|
214
250
|
*/
|
|
215
251
|
heartbeat;
|
|
216
|
-
constructor(conn, from, to, options) {
|
|
252
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
217
253
|
this.id = `session-${nanoid2(12)}`;
|
|
218
254
|
this.options = options;
|
|
219
255
|
this.from = from;
|
|
@@ -225,13 +261,14 @@ var Session = class {
|
|
|
225
261
|
() => this.sendHeartbeat(),
|
|
226
262
|
options.heartbeatIntervalMs
|
|
227
263
|
);
|
|
264
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
228
265
|
}
|
|
229
266
|
get loggingMetadata() {
|
|
230
267
|
return {
|
|
231
268
|
clientId: this.from,
|
|
232
269
|
connectedTo: this.to,
|
|
233
270
|
sessionId: this.id,
|
|
234
|
-
connId: this.connection?.
|
|
271
|
+
connId: this.connection?.id
|
|
235
272
|
};
|
|
236
273
|
}
|
|
237
274
|
/**
|
|
@@ -276,6 +313,7 @@ var Session = class {
|
|
|
276
313
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
277
314
|
this.loggingMetadata
|
|
278
315
|
);
|
|
316
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
279
317
|
this.closeStaleConnection();
|
|
280
318
|
}
|
|
281
319
|
return;
|
|
@@ -297,21 +335,25 @@ var Session = class {
|
|
|
297
335
|
sendBufferedMessages(conn) {
|
|
298
336
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
299
337
|
...this.loggingMetadata,
|
|
300
|
-
connId: conn.
|
|
338
|
+
connId: conn.id
|
|
301
339
|
});
|
|
302
340
|
for (const msg of this.sendBuffer) {
|
|
303
341
|
log?.debug(`resending msg`, {
|
|
304
342
|
...this.loggingMetadata,
|
|
305
343
|
fullTransportMessage: msg,
|
|
306
|
-
connId: conn.
|
|
344
|
+
connId: conn.id
|
|
307
345
|
});
|
|
308
346
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
309
347
|
if (!ok) {
|
|
310
348
|
const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
|
|
349
|
+
conn.telemetry?.span.setStatus({
|
|
350
|
+
code: import_api2.SpanStatusCode.ERROR,
|
|
351
|
+
message: errMsg
|
|
352
|
+
});
|
|
311
353
|
log?.error(errMsg, {
|
|
312
354
|
...this.loggingMetadata,
|
|
313
355
|
fullTransportMessage: msg,
|
|
314
|
-
connId: conn.
|
|
356
|
+
connId: conn.id,
|
|
315
357
|
tags: ["invariant-violation"]
|
|
316
358
|
});
|
|
317
359
|
conn.close();
|
|
@@ -394,11 +436,6 @@ var Session = class {
|
|
|
394
436
|
}
|
|
395
437
|
};
|
|
396
438
|
|
|
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
439
|
// util/stringify.ts
|
|
403
440
|
function coerceErrorString(err) {
|
|
404
441
|
if (err instanceof Error) {
|
|
@@ -531,6 +568,7 @@ var NaiveJsonCodec = {
|
|
|
531
568
|
};
|
|
532
569
|
|
|
533
570
|
// transport/transport.ts
|
|
571
|
+
var import_api3 = require("@opentelemetry/api");
|
|
534
572
|
var defaultTransportOptions = {
|
|
535
573
|
heartbeatIntervalMs: 1e3,
|
|
536
574
|
heartbeatsUntilDead: 2,
|
|
@@ -609,17 +647,22 @@ var Transport = class {
|
|
|
609
647
|
status: "connect",
|
|
610
648
|
conn
|
|
611
649
|
});
|
|
650
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
651
|
+
conn,
|
|
652
|
+
session.telemetry.span
|
|
653
|
+
);
|
|
612
654
|
if (isReconnect) {
|
|
613
655
|
session.replaceWithNewConnection(conn);
|
|
614
656
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
615
657
|
}
|
|
616
658
|
}
|
|
617
|
-
createSession(to, conn) {
|
|
659
|
+
createSession(to, conn, propagationCtx) {
|
|
618
660
|
const session = new Session(
|
|
619
661
|
conn,
|
|
620
662
|
this.clientId,
|
|
621
663
|
to,
|
|
622
|
-
this.options
|
|
664
|
+
this.options,
|
|
665
|
+
propagationCtx
|
|
623
666
|
);
|
|
624
667
|
this.sessions.set(session.to, session);
|
|
625
668
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -628,11 +671,11 @@ var Transport = class {
|
|
|
628
671
|
});
|
|
629
672
|
return session;
|
|
630
673
|
}
|
|
631
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
674
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
632
675
|
let session = this.sessions.get(to);
|
|
633
676
|
let isReconnect = session !== void 0;
|
|
634
677
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
635
|
-
log?.
|
|
678
|
+
log?.info(
|
|
636
679
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
637
680
|
session.loggingMetadata
|
|
638
681
|
);
|
|
@@ -641,7 +684,7 @@ var Transport = class {
|
|
|
641
684
|
session = void 0;
|
|
642
685
|
}
|
|
643
686
|
if (!session) {
|
|
644
|
-
session = this.createSession(to, conn);
|
|
687
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
645
688
|
log?.info(
|
|
646
689
|
`no session for ${to}, created a new one`,
|
|
647
690
|
session.loggingMetadata
|
|
@@ -654,6 +697,7 @@ var Transport = class {
|
|
|
654
697
|
}
|
|
655
698
|
deleteSession(session) {
|
|
656
699
|
session.close();
|
|
700
|
+
session.telemetry.span.end();
|
|
657
701
|
this.sessions.delete(session.to);
|
|
658
702
|
log?.info(
|
|
659
703
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -670,12 +714,16 @@ var Transport = class {
|
|
|
670
714
|
* @param connectedTo The peer we are connected to.
|
|
671
715
|
*/
|
|
672
716
|
onDisconnect(conn, session) {
|
|
717
|
+
conn.telemetry?.span.end();
|
|
673
718
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
674
719
|
status: "disconnect",
|
|
675
720
|
conn
|
|
676
721
|
});
|
|
677
722
|
session.connection = void 0;
|
|
678
|
-
session.beginGrace(() =>
|
|
723
|
+
session.beginGrace(() => {
|
|
724
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
725
|
+
this.deleteSession(session);
|
|
726
|
+
});
|
|
679
727
|
}
|
|
680
728
|
/**
|
|
681
729
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -735,6 +783,10 @@ var Transport = class {
|
|
|
735
783
|
tags: ["invariant-violation"]
|
|
736
784
|
});
|
|
737
785
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
786
|
+
session.telemetry.span.setStatus({
|
|
787
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
788
|
+
message: "message order violated"
|
|
789
|
+
});
|
|
738
790
|
session.close();
|
|
739
791
|
}
|
|
740
792
|
return;
|
|
@@ -845,6 +897,10 @@ var ClientTransport = class extends Transport {
|
|
|
845
897
|
* tests or a special case where you don't want to reconnect.
|
|
846
898
|
*/
|
|
847
899
|
reconnectOnConnectionDrop = true;
|
|
900
|
+
/**
|
|
901
|
+
* Optional handshake options for this client.
|
|
902
|
+
*/
|
|
903
|
+
handshakeExtensions;
|
|
848
904
|
constructor(clientId, providedOptions) {
|
|
849
905
|
super(clientId, providedOptions);
|
|
850
906
|
this.options = {
|
|
@@ -854,6 +910,9 @@ var ClientTransport = class extends Transport {
|
|
|
854
910
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
855
911
|
this.retryBudget = new LeakyBucketRateLimit(this.options);
|
|
856
912
|
}
|
|
913
|
+
extendHandshake(options) {
|
|
914
|
+
this.handshakeExtensions = options;
|
|
915
|
+
}
|
|
857
916
|
handleConnection(conn, to) {
|
|
858
917
|
if (this.state !== "open")
|
|
859
918
|
return;
|
|
@@ -862,7 +921,7 @@ var ClientTransport = class extends Transport {
|
|
|
862
921
|
if (!session) {
|
|
863
922
|
log?.warn(
|
|
864
923
|
`connection to ${to} timed out waiting for handshake, closing`,
|
|
865
|
-
{ clientId: this.clientId, connectedTo: to, connId: conn.
|
|
924
|
+
{ clientId: this.clientId, connectedTo: to, connId: conn.id }
|
|
866
925
|
);
|
|
867
926
|
conn.close();
|
|
868
927
|
}
|
|
@@ -880,6 +939,10 @@ var ClientTransport = class extends Transport {
|
|
|
880
939
|
conn.addDataListener((data2) => {
|
|
881
940
|
const parsed = this.parseMsg(data2);
|
|
882
941
|
if (!parsed) {
|
|
942
|
+
conn.telemetry?.span.setStatus({
|
|
943
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
944
|
+
message: "message parse failure"
|
|
945
|
+
});
|
|
883
946
|
conn.close();
|
|
884
947
|
return;
|
|
885
948
|
}
|
|
@@ -902,6 +965,10 @@ var ClientTransport = class extends Transport {
|
|
|
902
965
|
}
|
|
903
966
|
});
|
|
904
967
|
conn.addErrorListener((err) => {
|
|
968
|
+
conn.telemetry?.span.setStatus({
|
|
969
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
970
|
+
message: "connection error"
|
|
971
|
+
});
|
|
905
972
|
log?.warn(`error in connection to ${to}: ${coerceErrorString(err)}`, {
|
|
906
973
|
...session?.loggingMetadata,
|
|
907
974
|
clientId: this.clientId,
|
|
@@ -912,6 +979,10 @@ var ClientTransport = class extends Transport {
|
|
|
912
979
|
receiveHandshakeResponseMessage(data, conn) {
|
|
913
980
|
const parsed = this.parseMsg(data);
|
|
914
981
|
if (!parsed) {
|
|
982
|
+
conn.telemetry?.span.setStatus({
|
|
983
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
984
|
+
message: "non-transport message"
|
|
985
|
+
});
|
|
915
986
|
this.protocolError(
|
|
916
987
|
ProtocolError.HandshakeFailed,
|
|
917
988
|
"received non-transport message"
|
|
@@ -919,6 +990,10 @@ var ClientTransport = class extends Transport {
|
|
|
919
990
|
return false;
|
|
920
991
|
}
|
|
921
992
|
if (!import_value.Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
|
|
993
|
+
conn.telemetry?.span.setStatus({
|
|
994
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
995
|
+
message: "invalid handshake response"
|
|
996
|
+
});
|
|
922
997
|
log?.warn(`received invalid handshake resp`, {
|
|
923
998
|
clientId: this.clientId,
|
|
924
999
|
connectedTo: parsed.from,
|
|
@@ -931,7 +1006,11 @@ var ClientTransport = class extends Transport {
|
|
|
931
1006
|
return false;
|
|
932
1007
|
}
|
|
933
1008
|
if (!parsed.payload.status.ok) {
|
|
934
|
-
|
|
1009
|
+
conn.telemetry?.span.setStatus({
|
|
1010
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1011
|
+
message: "handshake rejected"
|
|
1012
|
+
});
|
|
1013
|
+
log?.warn(`received handshake rejection`, {
|
|
935
1014
|
clientId: this.clientId,
|
|
936
1015
|
connectedTo: parsed.from,
|
|
937
1016
|
fullTransportMessage: parsed
|
|
@@ -961,142 +1040,94 @@ var ClientTransport = class extends Transport {
|
|
|
961
1040
|
* @param to The client ID of the node to connect to.
|
|
962
1041
|
*/
|
|
963
1042
|
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
|
-
}
|
|
1043
|
+
const canProceedWithConnection = () => this.state === "open";
|
|
1044
|
+
if (!canProceedWithConnection()) {
|
|
1045
|
+
log?.info(
|
|
1046
|
+
`transport state is no longer open, cancelling attempt to connect to ${to}`,
|
|
1047
|
+
{ clientId: this.clientId, connectedTo: to }
|
|
1048
|
+
);
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
let reconnectPromise = this.inflightConnectionPromises.get(to);
|
|
1052
|
+
if (!reconnectPromise) {
|
|
1053
|
+
const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
|
|
1054
|
+
if (!this.retryBudget.hasBudget(to)) {
|
|
1055
|
+
const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
1056
|
+
log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
|
|
1057
|
+
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
1058
|
+
return;
|
|
986
1059
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
{
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
kind: import_api2.SpanKind.CLIENT
|
|
999
|
-
},
|
|
1000
|
-
async (span) => {
|
|
1060
|
+
let sleep = Promise.resolve();
|
|
1061
|
+
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
1062
|
+
if (backoffMs > 0) {
|
|
1063
|
+
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
1064
|
+
}
|
|
1065
|
+
log?.info(`attempting connection to ${to} (${backoffMs}ms backoff)`, {
|
|
1066
|
+
clientId: this.clientId,
|
|
1067
|
+
connectedTo: to
|
|
1068
|
+
});
|
|
1069
|
+
this.retryBudget.consumeBudget(to);
|
|
1070
|
+
reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
|
|
1001
1071
|
try {
|
|
1002
|
-
|
|
1072
|
+
span.addEvent("backoff", { backoffMs });
|
|
1073
|
+
await sleep;
|
|
1003
1074
|
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;
|
|
1075
|
+
throw new Error("transport state is no longer open");
|
|
1009
1076
|
}
|
|
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 {
|
|
1077
|
+
span.addEvent("connecting");
|
|
1078
|
+
const conn = await this.createNewOutgoingConnection(to);
|
|
1079
|
+
if (!canProceedWithConnection()) {
|
|
1059
1080
|
log?.info(
|
|
1060
|
-
`
|
|
1081
|
+
`transport state is no longer open, closing pre-handshake connection to ${to}`,
|
|
1061
1082
|
{
|
|
1062
1083
|
clientId: this.clientId,
|
|
1063
|
-
connectedTo: to
|
|
1084
|
+
connectedTo: to,
|
|
1085
|
+
connId: conn.id
|
|
1064
1086
|
}
|
|
1065
1087
|
);
|
|
1088
|
+
conn.close();
|
|
1089
|
+
throw new Error("transport state is no longer open");
|
|
1066
1090
|
}
|
|
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
|
-
}
|
|
1091
|
+
span.addEvent("sending handshake");
|
|
1092
|
+
const ok = await this.sendHandshake(to, conn);
|
|
1093
|
+
if (!ok) {
|
|
1094
|
+
conn.close();
|
|
1095
|
+
throw new Error("failed to send handshake");
|
|
1084
1096
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
1097
|
+
return conn;
|
|
1098
|
+
} catch (err) {
|
|
1099
|
+
const errStr = coerceErrorString(err);
|
|
1100
|
+
span.recordException(errStr);
|
|
1101
|
+
span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
|
|
1102
|
+
throw err;
|
|
1092
1103
|
} finally {
|
|
1093
1104
|
span.end();
|
|
1094
1105
|
}
|
|
1095
|
-
|
|
1106
|
+
});
|
|
1107
|
+
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
1108
|
+
} else {
|
|
1109
|
+
log?.info(`attempting connection to ${to} (reusing previous attempt)`, {
|
|
1110
|
+
clientId: this.clientId,
|
|
1111
|
+
connectedTo: to
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
try {
|
|
1115
|
+
await reconnectPromise;
|
|
1116
|
+
} catch (error) {
|
|
1117
|
+
this.inflightConnectionPromises.delete(to);
|
|
1118
|
+
const errStr = coerceErrorString(error);
|
|
1119
|
+
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
1120
|
+
log?.warn(`connection to ${to} failed (${errStr})`, {
|
|
1121
|
+
clientId: this.clientId,
|
|
1122
|
+
connectedTo: to
|
|
1123
|
+
});
|
|
1124
|
+
} else {
|
|
1125
|
+
log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
|
|
1126
|
+
clientId: this.clientId,
|
|
1127
|
+
connectedTo: to
|
|
1128
|
+
});
|
|
1129
|
+
return this.connect(to);
|
|
1096
1130
|
}
|
|
1097
|
-
);
|
|
1098
|
-
if (retry) {
|
|
1099
|
-
return this.connectAttempt(to, attempt + 1);
|
|
1100
1131
|
}
|
|
1101
1132
|
}
|
|
1102
1133
|
deleteSession(session) {
|
|
@@ -1104,13 +1135,11 @@ var ClientTransport = class extends Transport {
|
|
|
1104
1135
|
super.deleteSession(session);
|
|
1105
1136
|
}
|
|
1106
1137
|
async sendHandshake(to, conn) {
|
|
1107
|
-
const tracing = { traceparent: "", tracestate: "" };
|
|
1108
|
-
import_api2.propagation.inject(import_api2.context.active(), tracing);
|
|
1109
1138
|
let metadata;
|
|
1110
|
-
if (this.
|
|
1111
|
-
metadata = await this.
|
|
1112
|
-
if (!import_value.Value.Check(this.
|
|
1113
|
-
log?.error(`handshake metadata did not match schema`, {
|
|
1139
|
+
if (this.handshakeExtensions) {
|
|
1140
|
+
metadata = await this.handshakeExtensions.construct();
|
|
1141
|
+
if (!import_value.Value.Check(this.handshakeExtensions.schema, metadata)) {
|
|
1142
|
+
log?.error(`constructed handshake metadata did not match schema`, {
|
|
1114
1143
|
clientId: this.clientId,
|
|
1115
1144
|
connectedTo: to,
|
|
1116
1145
|
tags: ["invariant-violation"]
|
|
@@ -1119,6 +1148,10 @@ var ClientTransport = class extends Transport {
|
|
|
1119
1148
|
ProtocolError.HandshakeFailed,
|
|
1120
1149
|
"handshake metadata did not match schema"
|
|
1121
1150
|
);
|
|
1151
|
+
conn.telemetry?.span.setStatus({
|
|
1152
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1153
|
+
message: "handshake meta mismatch"
|
|
1154
|
+
});
|
|
1122
1155
|
return false;
|
|
1123
1156
|
}
|
|
1124
1157
|
}
|
|
@@ -1128,7 +1161,7 @@ var ClientTransport = class extends Transport {
|
|
|
1128
1161
|
to,
|
|
1129
1162
|
session.id,
|
|
1130
1163
|
metadata,
|
|
1131
|
-
|
|
1164
|
+
getPropagationContext(session.telemetry.ctx)
|
|
1132
1165
|
);
|
|
1133
1166
|
log?.debug(`sending handshake request to ${to}`, {
|
|
1134
1167
|
clientId: this.clientId,
|
|
@@ -1144,13 +1177,31 @@ var ClientTransport = class extends Transport {
|
|
|
1144
1177
|
};
|
|
1145
1178
|
|
|
1146
1179
|
// transport/impls/ws/connection.ts
|
|
1147
|
-
var import_agnostic_ws = __toESM(require("agnostic-ws"), 1);
|
|
1148
1180
|
var WebSocketConnection = class extends Connection {
|
|
1181
|
+
errorCb = null;
|
|
1182
|
+
closeCb = null;
|
|
1149
1183
|
ws;
|
|
1150
1184
|
constructor(ws) {
|
|
1151
1185
|
super();
|
|
1152
1186
|
this.ws = ws;
|
|
1153
1187
|
this.ws.binaryType = "arraybuffer";
|
|
1188
|
+
let didError = false;
|
|
1189
|
+
this.ws.onerror = () => {
|
|
1190
|
+
didError = true;
|
|
1191
|
+
};
|
|
1192
|
+
this.ws.onclose = ({ code, reason }) => {
|
|
1193
|
+
if (didError && this.errorCb) {
|
|
1194
|
+
this.errorCb(
|
|
1195
|
+
new Error(
|
|
1196
|
+
`websocket closed with code and reason: ${code} - ${reason}`
|
|
1197
|
+
)
|
|
1198
|
+
);
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (this.closeCb) {
|
|
1202
|
+
this.closeCb();
|
|
1203
|
+
}
|
|
1204
|
+
};
|
|
1154
1205
|
}
|
|
1155
1206
|
addDataListener(cb) {
|
|
1156
1207
|
this.ws.onmessage = (msg) => cb(msg.data);
|
|
@@ -1159,13 +1210,13 @@ var WebSocketConnection = class extends Connection {
|
|
|
1159
1210
|
this.ws.onmessage = null;
|
|
1160
1211
|
}
|
|
1161
1212
|
addCloseListener(cb) {
|
|
1162
|
-
this.
|
|
1213
|
+
this.closeCb = cb;
|
|
1163
1214
|
}
|
|
1164
1215
|
addErrorListener(cb) {
|
|
1165
|
-
this.
|
|
1216
|
+
this.errorCb = cb;
|
|
1166
1217
|
}
|
|
1167
1218
|
send(payload) {
|
|
1168
|
-
if (this.ws.readyState ===
|
|
1219
|
+
if (this.ws.readyState === this.ws.OPEN) {
|
|
1169
1220
|
this.ws.send(payload);
|
|
1170
1221
|
return true;
|
|
1171
1222
|
} else {
|
|
@@ -1182,7 +1233,7 @@ var WebSocketClientTransport = class extends ClientTransport {
|
|
|
1182
1233
|
/**
|
|
1183
1234
|
* A function that returns a Promise that resolves to a websocket URL.
|
|
1184
1235
|
*/
|
|
1185
|
-
|
|
1236
|
+
wsGetter;
|
|
1186
1237
|
/**
|
|
1187
1238
|
* Creates a new WebSocketClientTransport instance.
|
|
1188
1239
|
* @param wsGetter A function that returns a Promise that resolves to a WebSocket instance.
|
|
@@ -1190,53 +1241,39 @@ var WebSocketClientTransport = class extends ClientTransport {
|
|
|
1190
1241
|
* @param serverId The ID of the server this transport is connecting to.
|
|
1191
1242
|
* @param providedOptions An optional object containing configuration options for the transport.
|
|
1192
1243
|
*/
|
|
1193
|
-
constructor(
|
|
1244
|
+
constructor(wsGetter, clientId, providedOptions) {
|
|
1194
1245
|
super(clientId, providedOptions);
|
|
1195
|
-
this.
|
|
1246
|
+
this.wsGetter = wsGetter;
|
|
1196
1247
|
}
|
|
1197
1248
|
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
|
-
});
|
|
1249
|
+
log?.info(`establishing a new websocket to ${to}`, {
|
|
1250
|
+
clientId: this.clientId,
|
|
1251
|
+
connectedTo: to
|
|
1228
1252
|
});
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1253
|
+
const ws = await this.wsGetter(to);
|
|
1254
|
+
await new Promise((resolve, reject) => {
|
|
1255
|
+
if (ws.readyState === ws.OPEN) {
|
|
1256
|
+
resolve();
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
if (ws.readyState === ws.CLOSING || ws.readyState === ws.CLOSED) {
|
|
1260
|
+
reject(new Error("ws is closing or closed"));
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
1263
|
+
ws.onopen = () => {
|
|
1264
|
+
resolve();
|
|
1265
|
+
};
|
|
1266
|
+
ws.onclose = (evt) => {
|
|
1267
|
+
reject(new Error(evt.reason));
|
|
1268
|
+
};
|
|
1269
|
+
});
|
|
1270
|
+
const conn = new WebSocketConnection(ws);
|
|
1271
|
+
log?.info(`raw websocket to ${to} ok, starting handshake`, {
|
|
1272
|
+
clientId: this.clientId,
|
|
1273
|
+
connectedTo: to
|
|
1274
|
+
});
|
|
1275
|
+
this.handleConnection(conn, to);
|
|
1276
|
+
return conn;
|
|
1240
1277
|
}
|
|
1241
1278
|
};
|
|
1242
1279
|
// Annotate the CommonJS export names for ESM import in node:
|