@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.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-FDLAPYCK.js → chunk-DZOATC6M.js} +2 -2
  3. package/dist/{chunk-JMXO5L2X.js → chunk-MJUFKPBT.js} +354 -398
  4. package/dist/chunk-MJUFKPBT.js.map +1 -0
  5. package/dist/{chunk-5WFL722S.js → chunk-PCKHBAVP.js} +94 -3
  6. package/dist/chunk-PCKHBAVP.js.map +1 -0
  7. package/dist/{chunk-NCXUFDVL.js → chunk-VOJVLWVX.js} +360 -516
  8. package/dist/chunk-VOJVLWVX.js.map +1 -0
  9. package/dist/chunk-ZF2UFTNN.js +60 -0
  10. package/dist/chunk-ZF2UFTNN.js.map +1 -0
  11. package/dist/{connection-76c5ed01.d.ts → connection-5685d817.d.ts} +6 -4
  12. package/dist/{connection-975b25c9.d.ts → connection-7582fb92.d.ts} +1 -1
  13. package/dist/{index-dfad460e.d.ts → index-a6fe0edd.d.ts} +55 -59
  14. package/dist/logging/index.d.cts +2 -1
  15. package/dist/logging/index.d.ts +2 -1
  16. package/dist/router/index.cjs +405 -502
  17. package/dist/router/index.cjs.map +1 -1
  18. package/dist/router/index.d.cts +12 -6
  19. package/dist/router/index.d.ts +12 -6
  20. package/dist/router/index.js +4 -3
  21. package/dist/{services-9c496c6e.d.ts → services-be91b485.d.ts} +21 -52
  22. package/dist/{services-7b716dcf.d.ts → services-eb9326a1.d.ts} +21 -52
  23. package/dist/transport/impls/uds/client.cjs +197 -155
  24. package/dist/transport/impls/uds/client.cjs.map +1 -1
  25. package/dist/transport/impls/uds/client.d.cts +3 -2
  26. package/dist/transport/impls/uds/client.d.ts +3 -2
  27. package/dist/transport/impls/uds/client.js +3 -3
  28. package/dist/transport/impls/uds/server.cjs +280 -266
  29. package/dist/transport/impls/uds/server.cjs.map +1 -1
  30. package/dist/transport/impls/uds/server.d.cts +3 -2
  31. package/dist/transport/impls/uds/server.d.ts +3 -2
  32. package/dist/transport/impls/uds/server.js +3 -3
  33. package/dist/transport/impls/ws/client.cjs +251 -214
  34. package/dist/transport/impls/ws/client.cjs.map +1 -1
  35. package/dist/transport/impls/ws/client.d.cts +6 -6
  36. package/dist/transport/impls/ws/client.d.ts +6 -6
  37. package/dist/transport/impls/ws/client.js +33 -48
  38. package/dist/transport/impls/ws/client.js.map +1 -1
  39. package/dist/transport/impls/ws/server.cjs +302 -280
  40. package/dist/transport/impls/ws/server.cjs.map +1 -1
  41. package/dist/transport/impls/ws/server.d.cts +5 -4
  42. package/dist/transport/impls/ws/server.d.ts +5 -4
  43. package/dist/transport/impls/ws/server.js +3 -3
  44. package/dist/transport/impls/ws/server.js.map +1 -1
  45. package/dist/transport/index.cjs +400 -396
  46. package/dist/transport/index.cjs.map +1 -1
  47. package/dist/transport/index.d.cts +25 -14
  48. package/dist/transport/index.d.ts +25 -14
  49. package/dist/transport/index.js +2 -2
  50. package/dist/util/testHelpers.cjs +59 -14
  51. package/dist/util/testHelpers.cjs.map +1 -1
  52. package/dist/util/testHelpers.d.cts +14 -5
  53. package/dist/util/testHelpers.d.ts +14 -5
  54. package/dist/util/testHelpers.js +12 -5
  55. package/dist/util/testHelpers.js.map +1 -1
  56. package/dist/wslike-e0b32dd5.d.ts +40 -0
  57. package/package.json +4 -5
  58. package/dist/chunk-3Y7AB5EB.js +0 -42
  59. package/dist/chunk-3Y7AB5EB.js.map +0 -1
  60. package/dist/chunk-5WFL722S.js.map +0 -1
  61. package/dist/chunk-JMXO5L2X.js.map +0 -1
  62. package/dist/chunk-NCXUFDVL.js.map +0 -1
  63. /package/dist/{chunk-FDLAPYCK.js.map → chunk-DZOATC6M.js.map} +0 -0
@@ -109,18 +109,70 @@ function isAck(controlFlag) {
109
109
  return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
110
110
  }
111
111
 
112
+ // tracing/index.ts
113
+ var import_api = require("@opentelemetry/api");
114
+
115
+ // package.json
116
+ var version = "0.23.0";
117
+
118
+ // tracing/index.ts
119
+ function getPropagationContext(ctx) {
120
+ const tracing = {
121
+ traceparent: "",
122
+ tracestate: ""
123
+ };
124
+ import_api.propagation.inject(ctx, tracing);
125
+ return tracing;
126
+ }
127
+ function createSessionTelemetryInfo(session, propagationCtx) {
128
+ const ctx = propagationCtx ? import_api.propagation.extract(import_api.context.active(), propagationCtx) : import_api.context.active();
129
+ const span = tracer.startSpan(
130
+ `session ${session.id}`,
131
+ {
132
+ attributes: {
133
+ component: "river",
134
+ "river.session.id": session.id,
135
+ "river.session.to": session.to,
136
+ "river.session.from": session.from
137
+ }
138
+ },
139
+ ctx
140
+ );
141
+ return { span, ctx };
142
+ }
143
+ function createConnectionTelemetryInfo(connection, sessionSpan) {
144
+ const ctx = import_api.trace.setSpan(import_api.context.active(), sessionSpan);
145
+ const span = tracer.startSpan(
146
+ `connection ${connection.id}`,
147
+ {
148
+ attributes: {
149
+ component: "river",
150
+ "river.connection.id": connection.id
151
+ },
152
+ links: [{ context: sessionSpan.spanContext() }]
153
+ },
154
+ ctx
155
+ );
156
+ return { span, ctx };
157
+ }
158
+ var tracer = import_api.trace.getTracer("river", version);
159
+ var tracing_default = tracer;
160
+
112
161
  // transport/session.ts
162
+ var import_api2 = require("@opentelemetry/api");
113
163
  var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
114
164
  var unsafeId = () => nanoid2();
115
165
  var Connection = class {
116
- debugId;
166
+ id;
167
+ telemetry;
117
168
  constructor() {
118
- this.debugId = `conn-${unsafeId()}`;
169
+ this.id = `conn-${nanoid2(12)}`;
119
170
  }
120
171
  };
121
172
  var Session = class {
122
173
  codec;
123
174
  options;
175
+ telemetry;
124
176
  /**
125
177
  * The buffer of messages that have been sent but not yet acknowledged.
126
178
  */
@@ -140,12 +192,6 @@ var Session = class {
140
192
  * for this session.
141
193
  */
142
194
  advertisedSessionId;
143
- /**
144
- * The metadata for this session, as parsed from the handshake.
145
- *
146
- * Will only ever be populated on the server side.
147
- */
148
- metadata;
149
195
  /**
150
196
  * Number of messages we've sent along this session (excluding handshake and acks)
151
197
  */
@@ -167,7 +213,7 @@ var Session = class {
167
213
  * The interval for sending heartbeats.
168
214
  */
169
215
  heartbeat;
170
- constructor(conn, from, to, options) {
216
+ constructor(conn, from, to, options, propagationCtx) {
171
217
  this.id = `session-${nanoid2(12)}`;
172
218
  this.options = options;
173
219
  this.from = from;
@@ -179,13 +225,14 @@ var Session = class {
179
225
  () => this.sendHeartbeat(),
180
226
  options.heartbeatIntervalMs
181
227
  );
228
+ this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
182
229
  }
183
230
  get loggingMetadata() {
184
231
  return {
185
232
  clientId: this.from,
186
233
  connectedTo: this.to,
187
234
  sessionId: this.id,
188
- connId: this.connection?.debugId
235
+ connId: this.connection?.id
189
236
  };
190
237
  }
191
238
  /**
@@ -230,6 +277,7 @@ var Session = class {
230
277
  `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
231
278
  this.loggingMetadata
232
279
  );
280
+ this.telemetry.span.addEvent("closing connection due to inactivity");
233
281
  this.closeStaleConnection();
234
282
  }
235
283
  return;
@@ -251,21 +299,25 @@ var Session = class {
251
299
  sendBufferedMessages(conn) {
252
300
  log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
253
301
  ...this.loggingMetadata,
254
- connId: conn.debugId
302
+ connId: conn.id
255
303
  });
256
304
  for (const msg of this.sendBuffer) {
257
305
  log?.debug(`resending msg`, {
258
306
  ...this.loggingMetadata,
259
307
  fullTransportMessage: msg,
260
- connId: conn.debugId
308
+ connId: conn.id
261
309
  });
262
310
  const ok = conn.send(this.codec.toBuffer(msg));
263
311
  if (!ok) {
264
312
  const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
313
+ conn.telemetry?.span.setStatus({
314
+ code: import_api2.SpanStatusCode.ERROR,
315
+ message: errMsg
316
+ });
265
317
  log?.error(errMsg, {
266
318
  ...this.loggingMetadata,
267
319
  fullTransportMessage: msg,
268
- connId: conn.debugId,
320
+ connId: conn.id,
269
321
  tags: ["invariant-violation"]
270
322
  });
271
323
  conn.close();
@@ -448,7 +500,6 @@ var UdsConnection = class extends Connection {
448
500
 
449
501
  // transport/transport.ts
450
502
  var import_value = require("@sinclair/typebox/value");
451
- var import_api2 = require("@opentelemetry/api");
452
503
 
453
504
  // transport/events.ts
454
505
  var ProtocolError = {
@@ -484,11 +535,6 @@ var EventDispatcher = class {
484
535
  }
485
536
  };
486
537
 
487
- // tracing/index.ts
488
- var import_api = require("@opentelemetry/api");
489
- var tracer = import_api.trace.getTracer("river");
490
- var tracing_default = tracer;
491
-
492
538
  // util/stringify.ts
493
539
  function coerceErrorString(err) {
494
540
  if (err instanceof Error) {
@@ -621,6 +667,7 @@ var NaiveJsonCodec = {
621
667
  };
622
668
 
623
669
  // transport/transport.ts
670
+ var import_api3 = require("@opentelemetry/api");
624
671
  var defaultTransportOptions = {
625
672
  heartbeatIntervalMs: 1e3,
626
673
  heartbeatsUntilDead: 2,
@@ -699,17 +746,22 @@ var Transport = class {
699
746
  status: "connect",
700
747
  conn
701
748
  });
749
+ conn.telemetry = createConnectionTelemetryInfo(
750
+ conn,
751
+ session.telemetry.span
752
+ );
702
753
  if (isReconnect) {
703
754
  session.replaceWithNewConnection(conn);
704
755
  log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
705
756
  }
706
757
  }
707
- createSession(to, conn) {
758
+ createSession(to, conn, propagationCtx) {
708
759
  const session = new Session(
709
760
  conn,
710
761
  this.clientId,
711
762
  to,
712
- this.options
763
+ this.options,
764
+ propagationCtx
713
765
  );
714
766
  this.sessions.set(session.to, session);
715
767
  this.eventDispatcher.dispatchEvent("sessionStatus", {
@@ -718,11 +770,11 @@ var Transport = class {
718
770
  });
719
771
  return session;
720
772
  }
721
- getOrCreateSession(to, conn, sessionId) {
773
+ getOrCreateSession(to, conn, sessionId, propagationCtx) {
722
774
  let session = this.sessions.get(to);
723
775
  let isReconnect = session !== void 0;
724
776
  if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
725
- log?.warn(
777
+ log?.info(
726
778
  `session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
727
779
  session.loggingMetadata
728
780
  );
@@ -731,7 +783,7 @@ var Transport = class {
731
783
  session = void 0;
732
784
  }
733
785
  if (!session) {
734
- session = this.createSession(to, conn);
786
+ session = this.createSession(to, conn, propagationCtx);
735
787
  log?.info(
736
788
  `no session for ${to}, created a new one`,
737
789
  session.loggingMetadata
@@ -744,6 +796,7 @@ var Transport = class {
744
796
  }
745
797
  deleteSession(session) {
746
798
  session.close();
799
+ session.telemetry.span.end();
747
800
  this.sessions.delete(session.to);
748
801
  log?.info(
749
802
  `session ${session.id} disconnect from ${session.to}`,
@@ -760,12 +813,16 @@ var Transport = class {
760
813
  * @param connectedTo The peer we are connected to.
761
814
  */
762
815
  onDisconnect(conn, session) {
816
+ conn.telemetry?.span.end();
763
817
  this.eventDispatcher.dispatchEvent("connectionStatus", {
764
818
  status: "disconnect",
765
819
  conn
766
820
  });
767
821
  session.connection = void 0;
768
- session.beginGrace(() => this.deleteSession(session));
822
+ session.beginGrace(() => {
823
+ session.telemetry.span.addEvent("session grace period expired");
824
+ this.deleteSession(session);
825
+ });
769
826
  }
770
827
  /**
771
828
  * Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
@@ -825,6 +882,10 @@ var Transport = class {
825
882
  tags: ["invariant-violation"]
826
883
  });
827
884
  this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
885
+ session.telemetry.span.setStatus({
886
+ code: import_api3.SpanStatusCode.ERROR,
887
+ message: "message order violated"
888
+ });
828
889
  session.close();
829
890
  }
830
891
  return;
@@ -935,6 +996,10 @@ var ClientTransport = class extends Transport {
935
996
  * tests or a special case where you don't want to reconnect.
936
997
  */
937
998
  reconnectOnConnectionDrop = true;
999
+ /**
1000
+ * Optional handshake options for this client.
1001
+ */
1002
+ handshakeExtensions;
938
1003
  constructor(clientId, providedOptions) {
939
1004
  super(clientId, providedOptions);
940
1005
  this.options = {
@@ -944,6 +1009,9 @@ var ClientTransport = class extends Transport {
944
1009
  this.inflightConnectionPromises = /* @__PURE__ */ new Map();
945
1010
  this.retryBudget = new LeakyBucketRateLimit(this.options);
946
1011
  }
1012
+ extendHandshake(options) {
1013
+ this.handshakeExtensions = options;
1014
+ }
947
1015
  handleConnection(conn, to) {
948
1016
  if (this.state !== "open")
949
1017
  return;
@@ -952,7 +1020,7 @@ var ClientTransport = class extends Transport {
952
1020
  if (!session) {
953
1021
  log?.warn(
954
1022
  `connection to ${to} timed out waiting for handshake, closing`,
955
- { clientId: this.clientId, connectedTo: to, connId: conn.debugId }
1023
+ { clientId: this.clientId, connectedTo: to, connId: conn.id }
956
1024
  );
957
1025
  conn.close();
958
1026
  }
@@ -970,6 +1038,10 @@ var ClientTransport = class extends Transport {
970
1038
  conn.addDataListener((data2) => {
971
1039
  const parsed = this.parseMsg(data2);
972
1040
  if (!parsed) {
1041
+ conn.telemetry?.span.setStatus({
1042
+ code: import_api3.SpanStatusCode.ERROR,
1043
+ message: "message parse failure"
1044
+ });
973
1045
  conn.close();
974
1046
  return;
975
1047
  }
@@ -992,6 +1064,10 @@ var ClientTransport = class extends Transport {
992
1064
  }
993
1065
  });
994
1066
  conn.addErrorListener((err) => {
1067
+ conn.telemetry?.span.setStatus({
1068
+ code: import_api3.SpanStatusCode.ERROR,
1069
+ message: "connection error"
1070
+ });
995
1071
  log?.warn(`error in connection to ${to}: ${coerceErrorString(err)}`, {
996
1072
  ...session?.loggingMetadata,
997
1073
  clientId: this.clientId,
@@ -1002,6 +1078,10 @@ var ClientTransport = class extends Transport {
1002
1078
  receiveHandshakeResponseMessage(data, conn) {
1003
1079
  const parsed = this.parseMsg(data);
1004
1080
  if (!parsed) {
1081
+ conn.telemetry?.span.setStatus({
1082
+ code: import_api3.SpanStatusCode.ERROR,
1083
+ message: "non-transport message"
1084
+ });
1005
1085
  this.protocolError(
1006
1086
  ProtocolError.HandshakeFailed,
1007
1087
  "received non-transport message"
@@ -1009,6 +1089,10 @@ var ClientTransport = class extends Transport {
1009
1089
  return false;
1010
1090
  }
1011
1091
  if (!import_value.Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
1092
+ conn.telemetry?.span.setStatus({
1093
+ code: import_api3.SpanStatusCode.ERROR,
1094
+ message: "invalid handshake response"
1095
+ });
1012
1096
  log?.warn(`received invalid handshake resp`, {
1013
1097
  clientId: this.clientId,
1014
1098
  connectedTo: parsed.from,
@@ -1021,7 +1105,11 @@ var ClientTransport = class extends Transport {
1021
1105
  return false;
1022
1106
  }
1023
1107
  if (!parsed.payload.status.ok) {
1024
- log?.warn(`received invalid handshake resp`, {
1108
+ conn.telemetry?.span.setStatus({
1109
+ code: import_api3.SpanStatusCode.ERROR,
1110
+ message: "handshake rejected"
1111
+ });
1112
+ log?.warn(`received handshake rejection`, {
1025
1113
  clientId: this.clientId,
1026
1114
  connectedTo: parsed.from,
1027
1115
  fullTransportMessage: parsed
@@ -1051,142 +1139,94 @@ var ClientTransport = class extends Transport {
1051
1139
  * @param to The client ID of the node to connect to.
1052
1140
  */
1053
1141
  async connect(to) {
1054
- return tracing_default.startActiveSpan(
1055
- "connect",
1056
- {
1057
- attributes: {
1058
- component: "river",
1059
- "span.kind": "client"
1060
- },
1061
- kind: import_api2.SpanKind.CLIENT
1062
- },
1063
- async (span) => {
1064
- try {
1065
- await this.connectAttempt(to);
1066
- } catch (e) {
1067
- if (e instanceof Error) {
1068
- span.recordException(e);
1069
- } else {
1070
- span.recordException(coerceErrorString(e));
1071
- }
1072
- span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
1073
- } finally {
1074
- span.end();
1075
- }
1142
+ const canProceedWithConnection = () => this.state === "open";
1143
+ if (!canProceedWithConnection()) {
1144
+ log?.info(
1145
+ `transport state is no longer open, cancelling attempt to connect to ${to}`,
1146
+ { clientId: this.clientId, connectedTo: to }
1147
+ );
1148
+ return;
1149
+ }
1150
+ let reconnectPromise = this.inflightConnectionPromises.get(to);
1151
+ if (!reconnectPromise) {
1152
+ const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
1153
+ if (!this.retryBudget.hasBudget(to)) {
1154
+ const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
1155
+ log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
1156
+ this.protocolError(ProtocolError.RetriesExceeded, errMsg);
1157
+ return;
1076
1158
  }
1077
- );
1078
- }
1079
- async connectAttempt(to, attempt = 0) {
1080
- const retry = await tracing_default.startActiveSpan(
1081
- "connect",
1082
- {
1083
- attributes: {
1084
- component: "river",
1085
- "river.attempt": attempt,
1086
- "span.kind": "client"
1087
- },
1088
- kind: import_api2.SpanKind.CLIENT
1089
- },
1090
- async (span) => {
1159
+ let sleep = Promise.resolve();
1160
+ const backoffMs = this.retryBudget.getBackoffMs(to);
1161
+ if (backoffMs > 0) {
1162
+ sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
1163
+ }
1164
+ log?.info(`attempting connection to ${to} (${backoffMs}ms backoff)`, {
1165
+ clientId: this.clientId,
1166
+ connectedTo: to
1167
+ });
1168
+ this.retryBudget.consumeBudget(to);
1169
+ reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
1091
1170
  try {
1092
- const canProceedWithConnection = () => this.state === "open";
1171
+ span.addEvent("backoff", { backoffMs });
1172
+ await sleep;
1093
1173
  if (!canProceedWithConnection()) {
1094
- log?.info(
1095
- `transport state is no longer open, cancelling attempt to connect to ${to}`,
1096
- { clientId: this.clientId, connectedTo: to }
1097
- );
1098
- return false;
1174
+ throw new Error("transport state is no longer open");
1099
1175
  }
1100
- let reconnectPromise = this.inflightConnectionPromises.get(to);
1101
- if (!reconnectPromise) {
1102
- const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
1103
- if (!this.retryBudget.hasBudget(to)) {
1104
- const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
1105
- log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
1106
- this.protocolError(ProtocolError.RetriesExceeded, errMsg);
1107
- return false;
1108
- }
1109
- let sleep = Promise.resolve();
1110
- const backoffMs = this.retryBudget.getBackoffMs(to);
1111
- if (backoffMs > 0) {
1112
- sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
1113
- }
1114
- log?.info(
1115
- `attempting connection to ${to} (${backoffMs}ms backoff)`,
1116
- {
1117
- clientId: this.clientId,
1118
- connectedTo: to
1119
- }
1120
- );
1121
- this.retryBudget.consumeBudget(to);
1122
- reconnectPromise = sleep.then(() => {
1123
- if (!canProceedWithConnection()) {
1124
- throw new Error("transport state is no longer open");
1125
- }
1126
- }).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
1127
- if (!canProceedWithConnection()) {
1128
- log?.info(
1129
- `transport state is no longer open, closing pre-handshake connection to ${to}`,
1130
- {
1131
- clientId: this.clientId,
1132
- connectedTo: to,
1133
- connId: conn.debugId
1134
- }
1135
- );
1136
- conn.close();
1137
- throw new Error("transport state is no longer open");
1138
- }
1139
- return this.sendHandshake(to, conn).then((ok) => {
1140
- if (!ok) {
1141
- conn.close();
1142
- throw new Error("failed to send handshake");
1143
- }
1144
- return conn;
1145
- });
1146
- });
1147
- this.inflightConnectionPromises.set(to, reconnectPromise);
1148
- } else {
1176
+ span.addEvent("connecting");
1177
+ const conn = await this.createNewOutgoingConnection(to);
1178
+ if (!canProceedWithConnection()) {
1149
1179
  log?.info(
1150
- `attempting connection to ${to} (reusing previous attempt)`,
1180
+ `transport state is no longer open, closing pre-handshake connection to ${to}`,
1151
1181
  {
1152
1182
  clientId: this.clientId,
1153
- connectedTo: to
1183
+ connectedTo: to,
1184
+ connId: conn.id
1154
1185
  }
1155
1186
  );
1187
+ conn.close();
1188
+ throw new Error("transport state is no longer open");
1156
1189
  }
1157
- try {
1158
- await reconnectPromise;
1159
- } catch (error) {
1160
- this.inflightConnectionPromises.delete(to);
1161
- const errStr = coerceErrorString(error);
1162
- if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
1163
- log?.warn(`connection to ${to} failed (${errStr})`, {
1164
- clientId: this.clientId,
1165
- connectedTo: to
1166
- });
1167
- } else {
1168
- log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
1169
- clientId: this.clientId,
1170
- connectedTo: to
1171
- });
1172
- return true;
1173
- }
1174
- }
1175
- } catch (e) {
1176
- if (e instanceof Error) {
1177
- span.recordException(e);
1178
- } else {
1179
- span.recordException(coerceErrorString(e));
1190
+ span.addEvent("sending handshake");
1191
+ const ok = await this.sendHandshake(to, conn);
1192
+ if (!ok) {
1193
+ conn.close();
1194
+ throw new Error("failed to send handshake");
1180
1195
  }
1181
- span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
1196
+ return conn;
1197
+ } catch (err) {
1198
+ const errStr = coerceErrorString(err);
1199
+ span.recordException(errStr);
1200
+ span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
1201
+ throw err;
1182
1202
  } finally {
1183
1203
  span.end();
1184
1204
  }
1185
- return false;
1205
+ });
1206
+ this.inflightConnectionPromises.set(to, reconnectPromise);
1207
+ } else {
1208
+ log?.info(`attempting connection to ${to} (reusing previous attempt)`, {
1209
+ clientId: this.clientId,
1210
+ connectedTo: to
1211
+ });
1212
+ }
1213
+ try {
1214
+ await reconnectPromise;
1215
+ } catch (error) {
1216
+ this.inflightConnectionPromises.delete(to);
1217
+ const errStr = coerceErrorString(error);
1218
+ if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
1219
+ log?.warn(`connection to ${to} failed (${errStr})`, {
1220
+ clientId: this.clientId,
1221
+ connectedTo: to
1222
+ });
1223
+ } else {
1224
+ log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
1225
+ clientId: this.clientId,
1226
+ connectedTo: to
1227
+ });
1228
+ return this.connect(to);
1186
1229
  }
1187
- );
1188
- if (retry) {
1189
- return this.connectAttempt(to, attempt + 1);
1190
1230
  }
1191
1231
  }
1192
1232
  deleteSession(session) {
@@ -1194,13 +1234,11 @@ var ClientTransport = class extends Transport {
1194
1234
  super.deleteSession(session);
1195
1235
  }
1196
1236
  async sendHandshake(to, conn) {
1197
- const tracing = { traceparent: "", tracestate: "" };
1198
- import_api2.propagation.inject(import_api2.context.active(), tracing);
1199
1237
  let metadata;
1200
- if (this.options.handshake) {
1201
- metadata = await this.options.handshake.get();
1202
- if (!import_value.Value.Check(this.options.handshake.schema, metadata)) {
1203
- log?.error(`handshake metadata did not match schema`, {
1238
+ if (this.handshakeExtensions) {
1239
+ metadata = await this.handshakeExtensions.construct();
1240
+ if (!import_value.Value.Check(this.handshakeExtensions.schema, metadata)) {
1241
+ log?.error(`constructed handshake metadata did not match schema`, {
1204
1242
  clientId: this.clientId,
1205
1243
  connectedTo: to,
1206
1244
  tags: ["invariant-violation"]
@@ -1209,6 +1247,10 @@ var ClientTransport = class extends Transport {
1209
1247
  ProtocolError.HandshakeFailed,
1210
1248
  "handshake metadata did not match schema"
1211
1249
  );
1250
+ conn.telemetry?.span.setStatus({
1251
+ code: import_api3.SpanStatusCode.ERROR,
1252
+ message: "handshake meta mismatch"
1253
+ });
1212
1254
  return false;
1213
1255
  }
1214
1256
  }
@@ -1218,7 +1260,7 @@ var ClientTransport = class extends Transport {
1218
1260
  to,
1219
1261
  session.id,
1220
1262
  metadata,
1221
- tracing
1263
+ getPropagationContext(session.telemetry.ctx)
1222
1264
  );
1223
1265
  log?.debug(`sending handshake request to ${to}`, {
1224
1266
  clientId: this.clientId,