@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.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-5WFL722S.js → chunk-3MFX6NXA.js} +94 -3
  3. package/dist/chunk-3MFX6NXA.js.map +1 -0
  4. package/dist/{chunk-NCXUFDVL.js → chunk-GCLEWC26.js} +328 -500
  5. package/dist/chunk-GCLEWC26.js.map +1 -0
  6. package/dist/chunk-HUBFYN37.js +60 -0
  7. package/dist/chunk-HUBFYN37.js.map +1 -0
  8. package/dist/{chunk-FDLAPYCK.js → chunk-S3YKQT4J.js} +2 -2
  9. package/dist/{chunk-JMXO5L2X.js → chunk-ZPBWKBM5.js} +344 -384
  10. package/dist/chunk-ZPBWKBM5.js.map +1 -0
  11. package/dist/{connection-76c5ed01.d.ts → connection-8b059ac4.d.ts} +6 -4
  12. package/dist/{connection-975b25c9.d.ts → connection-bbfe1147.d.ts} +1 -1
  13. package/dist/{index-dfad460e.d.ts → index-2ece5234.d.ts} +16 -7
  14. package/dist/logging/index.d.cts +2 -1
  15. package/dist/logging/index.d.ts +2 -1
  16. package/dist/router/index.cjs +373 -486
  17. package/dist/router/index.cjs.map +1 -1
  18. package/dist/router/index.d.cts +5 -4
  19. package/dist/router/index.d.ts +5 -4
  20. package/dist/router/index.js +4 -3
  21. package/dist/{services-7b716dcf.d.ts → services-acbcc441.d.ts} +1 -1
  22. package/dist/{services-9c496c6e.d.ts → services-cb01a7a8.d.ts} +1 -1
  23. package/dist/transport/impls/uds/client.cjs +186 -145
  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 +281 -256
  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 +240 -204
  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 +303 -270
  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 +390 -382
  46. package/dist/transport/index.cjs.map +1 -1
  47. package/dist/transport/index.d.cts +5 -5
  48. package/dist/transport/index.d.ts +5 -5
  49. package/dist/transport/index.js +2 -2
  50. package/dist/util/testHelpers.cjs +57 -7
  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 +10 -4
  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-S3YKQT4J.js.map} +0 -0
@@ -4,11 +4,14 @@ import {
4
4
  OpaqueTransportMessageSchema,
5
5
  PROTOCOL_VERSION,
6
6
  coerceErrorString,
7
+ createConnectionTelemetryInfo,
8
+ createSessionTelemetryInfo,
9
+ getPropagationContext,
7
10
  handshakeRequestMessage,
8
11
  handshakeResponseMessage,
9
12
  isAck,
10
13
  tracing_default
11
- } from "./chunk-5WFL722S.js";
14
+ } from "./chunk-3MFX6NXA.js";
12
15
  import {
13
16
  log
14
17
  } from "./chunk-OTQNCLFH.js";
@@ -18,17 +21,20 @@ import {
18
21
 
19
22
  // transport/session.ts
20
23
  import { customAlphabet } from "nanoid";
24
+ import { SpanStatusCode } from "@opentelemetry/api";
21
25
  var nanoid = customAlphabet("1234567890abcdefghijklmnopqrstuvxyz", 6);
22
26
  var unsafeId = () => nanoid();
23
27
  var Connection = class {
24
- debugId;
28
+ id;
29
+ telemetry;
25
30
  constructor() {
26
- this.debugId = `conn-${unsafeId()}`;
31
+ this.id = `conn-${nanoid(12)}`;
27
32
  }
28
33
  };
29
34
  var Session = class {
30
35
  codec;
31
36
  options;
37
+ telemetry;
32
38
  /**
33
39
  * The buffer of messages that have been sent but not yet acknowledged.
34
40
  */
@@ -75,7 +81,7 @@ var Session = class {
75
81
  * The interval for sending heartbeats.
76
82
  */
77
83
  heartbeat;
78
- constructor(conn, from, to, options) {
84
+ constructor(conn, from, to, options, propagationCtx) {
79
85
  this.id = `session-${nanoid(12)}`;
80
86
  this.options = options;
81
87
  this.from = from;
@@ -87,13 +93,14 @@ var Session = class {
87
93
  () => this.sendHeartbeat(),
88
94
  options.heartbeatIntervalMs
89
95
  );
96
+ this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
90
97
  }
91
98
  get loggingMetadata() {
92
99
  return {
93
100
  clientId: this.from,
94
101
  connectedTo: this.to,
95
102
  sessionId: this.id,
96
- connId: this.connection?.debugId
103
+ connId: this.connection?.id
97
104
  };
98
105
  }
99
106
  /**
@@ -138,6 +145,7 @@ var Session = class {
138
145
  `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
139
146
  this.loggingMetadata
140
147
  );
148
+ this.telemetry.span.addEvent("closing connection due to inactivity");
141
149
  this.closeStaleConnection();
142
150
  }
143
151
  return;
@@ -159,21 +167,25 @@ var Session = class {
159
167
  sendBufferedMessages(conn) {
160
168
  log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
161
169
  ...this.loggingMetadata,
162
- connId: conn.debugId
170
+ connId: conn.id
163
171
  });
164
172
  for (const msg of this.sendBuffer) {
165
173
  log?.debug(`resending msg`, {
166
174
  ...this.loggingMetadata,
167
175
  fullTransportMessage: msg,
168
- connId: conn.debugId
176
+ connId: conn.id
169
177
  });
170
178
  const ok = conn.send(this.codec.toBuffer(msg));
171
179
  if (!ok) {
172
180
  const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
181
+ conn.telemetry?.span.setStatus({
182
+ code: SpanStatusCode.ERROR,
183
+ message: errMsg
184
+ });
173
185
  log?.error(errMsg, {
174
186
  ...this.loggingMetadata,
175
187
  fullTransportMessage: msg,
176
- connId: conn.debugId,
188
+ connId: conn.id,
177
189
  tags: ["invariant-violation"]
178
190
  });
179
191
  conn.close();
@@ -292,12 +304,6 @@ var EventDispatcher = class {
292
304
 
293
305
  // transport/transport.ts
294
306
  import { Value } from "@sinclair/typebox/value";
295
- import {
296
- context,
297
- propagation,
298
- SpanKind,
299
- SpanStatusCode
300
- } from "@opentelemetry/api";
301
307
 
302
308
  // transport/rateLimit.ts
303
309
  var LeakyBucketRateLimit = class {
@@ -371,6 +377,7 @@ var LeakyBucketRateLimit = class {
371
377
  };
372
378
 
373
379
  // transport/transport.ts
380
+ import { SpanStatusCode as SpanStatusCode2 } from "@opentelemetry/api";
374
381
  var defaultTransportOptions = {
375
382
  heartbeatIntervalMs: 1e3,
376
383
  heartbeatsUntilDead: 2,
@@ -449,17 +456,22 @@ var Transport = class {
449
456
  status: "connect",
450
457
  conn
451
458
  });
459
+ conn.telemetry = createConnectionTelemetryInfo(
460
+ conn,
461
+ session.telemetry.span
462
+ );
452
463
  if (isReconnect) {
453
464
  session.replaceWithNewConnection(conn);
454
465
  log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
455
466
  }
456
467
  }
457
- createSession(to, conn) {
468
+ createSession(to, conn, propagationCtx) {
458
469
  const session = new Session(
459
470
  conn,
460
471
  this.clientId,
461
472
  to,
462
- this.options
473
+ this.options,
474
+ propagationCtx
463
475
  );
464
476
  this.sessions.set(session.to, session);
465
477
  this.eventDispatcher.dispatchEvent("sessionStatus", {
@@ -468,11 +480,11 @@ var Transport = class {
468
480
  });
469
481
  return session;
470
482
  }
471
- getOrCreateSession(to, conn, sessionId) {
483
+ getOrCreateSession(to, conn, sessionId, propagationCtx) {
472
484
  let session = this.sessions.get(to);
473
485
  let isReconnect = session !== void 0;
474
486
  if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
475
- log?.warn(
487
+ log?.info(
476
488
  `session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
477
489
  session.loggingMetadata
478
490
  );
@@ -481,7 +493,7 @@ var Transport = class {
481
493
  session = void 0;
482
494
  }
483
495
  if (!session) {
484
- session = this.createSession(to, conn);
496
+ session = this.createSession(to, conn, propagationCtx);
485
497
  log?.info(
486
498
  `no session for ${to}, created a new one`,
487
499
  session.loggingMetadata
@@ -494,6 +506,7 @@ var Transport = class {
494
506
  }
495
507
  deleteSession(session) {
496
508
  session.close();
509
+ session.telemetry.span.end();
497
510
  this.sessions.delete(session.to);
498
511
  log?.info(
499
512
  `session ${session.id} disconnect from ${session.to}`,
@@ -510,12 +523,16 @@ var Transport = class {
510
523
  * @param connectedTo The peer we are connected to.
511
524
  */
512
525
  onDisconnect(conn, session) {
526
+ conn.telemetry?.span.end();
513
527
  this.eventDispatcher.dispatchEvent("connectionStatus", {
514
528
  status: "disconnect",
515
529
  conn
516
530
  });
517
531
  session.connection = void 0;
518
- session.beginGrace(() => this.deleteSession(session));
532
+ session.beginGrace(() => {
533
+ session.telemetry.span.addEvent("session grace period expired");
534
+ this.deleteSession(session);
535
+ });
519
536
  }
520
537
  /**
521
538
  * Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
@@ -575,6 +592,10 @@ var Transport = class {
575
592
  tags: ["invariant-violation"]
576
593
  });
577
594
  this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
595
+ session.telemetry.span.setStatus({
596
+ code: SpanStatusCode2.ERROR,
597
+ message: "message order violated"
598
+ });
578
599
  session.close();
579
600
  }
580
601
  return;
@@ -702,7 +723,7 @@ var ClientTransport = class extends Transport {
702
723
  if (!session) {
703
724
  log?.warn(
704
725
  `connection to ${to} timed out waiting for handshake, closing`,
705
- { clientId: this.clientId, connectedTo: to, connId: conn.debugId }
726
+ { clientId: this.clientId, connectedTo: to, connId: conn.id }
706
727
  );
707
728
  conn.close();
708
729
  }
@@ -720,6 +741,10 @@ var ClientTransport = class extends Transport {
720
741
  conn.addDataListener((data2) => {
721
742
  const parsed = this.parseMsg(data2);
722
743
  if (!parsed) {
744
+ conn.telemetry?.span.setStatus({
745
+ code: SpanStatusCode2.ERROR,
746
+ message: "message parse failure"
747
+ });
723
748
  conn.close();
724
749
  return;
725
750
  }
@@ -742,6 +767,10 @@ var ClientTransport = class extends Transport {
742
767
  }
743
768
  });
744
769
  conn.addErrorListener((err) => {
770
+ conn.telemetry?.span.setStatus({
771
+ code: SpanStatusCode2.ERROR,
772
+ message: "connection error"
773
+ });
745
774
  log?.warn(`error in connection to ${to}: ${coerceErrorString(err)}`, {
746
775
  ...session?.loggingMetadata,
747
776
  clientId: this.clientId,
@@ -752,6 +781,10 @@ var ClientTransport = class extends Transport {
752
781
  receiveHandshakeResponseMessage(data, conn) {
753
782
  const parsed = this.parseMsg(data);
754
783
  if (!parsed) {
784
+ conn.telemetry?.span.setStatus({
785
+ code: SpanStatusCode2.ERROR,
786
+ message: "non-transport message"
787
+ });
755
788
  this.protocolError(
756
789
  ProtocolError.HandshakeFailed,
757
790
  "received non-transport message"
@@ -759,6 +792,10 @@ var ClientTransport = class extends Transport {
759
792
  return false;
760
793
  }
761
794
  if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
795
+ conn.telemetry?.span.setStatus({
796
+ code: SpanStatusCode2.ERROR,
797
+ message: "invalid handshake response"
798
+ });
762
799
  log?.warn(`received invalid handshake resp`, {
763
800
  clientId: this.clientId,
764
801
  connectedTo: parsed.from,
@@ -771,7 +808,11 @@ var ClientTransport = class extends Transport {
771
808
  return false;
772
809
  }
773
810
  if (!parsed.payload.status.ok) {
774
- log?.warn(`received invalid handshake resp`, {
811
+ conn.telemetry?.span.setStatus({
812
+ code: SpanStatusCode2.ERROR,
813
+ message: "handshake rejected"
814
+ });
815
+ log?.warn(`received handshake rejection`, {
775
816
  clientId: this.clientId,
776
817
  connectedTo: parsed.from,
777
818
  fullTransportMessage: parsed
@@ -801,142 +842,94 @@ var ClientTransport = class extends Transport {
801
842
  * @param to The client ID of the node to connect to.
802
843
  */
803
844
  async connect(to) {
804
- return tracing_default.startActiveSpan(
805
- "connect",
806
- {
807
- attributes: {
808
- component: "river",
809
- "span.kind": "client"
810
- },
811
- kind: SpanKind.CLIENT
812
- },
813
- async (span) => {
814
- try {
815
- await this.connectAttempt(to);
816
- } catch (e) {
817
- if (e instanceof Error) {
818
- span.recordException(e);
819
- } else {
820
- span.recordException(coerceErrorString(e));
821
- }
822
- span.setStatus({ code: SpanStatusCode.ERROR });
823
- } finally {
824
- span.end();
825
- }
845
+ const canProceedWithConnection = () => this.state === "open";
846
+ if (!canProceedWithConnection()) {
847
+ log?.info(
848
+ `transport state is no longer open, cancelling attempt to connect to ${to}`,
849
+ { clientId: this.clientId, connectedTo: to }
850
+ );
851
+ return;
852
+ }
853
+ let reconnectPromise = this.inflightConnectionPromises.get(to);
854
+ if (!reconnectPromise) {
855
+ const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
856
+ if (!this.retryBudget.hasBudget(to)) {
857
+ const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
858
+ log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
859
+ this.protocolError(ProtocolError.RetriesExceeded, errMsg);
860
+ return;
826
861
  }
827
- );
828
- }
829
- async connectAttempt(to, attempt = 0) {
830
- const retry = await tracing_default.startActiveSpan(
831
- "connect",
832
- {
833
- attributes: {
834
- component: "river",
835
- "river.attempt": attempt,
836
- "span.kind": "client"
837
- },
838
- kind: SpanKind.CLIENT
839
- },
840
- async (span) => {
862
+ let sleep = Promise.resolve();
863
+ const backoffMs = this.retryBudget.getBackoffMs(to);
864
+ if (backoffMs > 0) {
865
+ sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
866
+ }
867
+ log?.info(`attempting connection to ${to} (${backoffMs}ms backoff)`, {
868
+ clientId: this.clientId,
869
+ connectedTo: to
870
+ });
871
+ this.retryBudget.consumeBudget(to);
872
+ reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
841
873
  try {
842
- const canProceedWithConnection = () => this.state === "open";
874
+ span.addEvent("backoff", { backoffMs });
875
+ await sleep;
843
876
  if (!canProceedWithConnection()) {
844
- log?.info(
845
- `transport state is no longer open, cancelling attempt to connect to ${to}`,
846
- { clientId: this.clientId, connectedTo: to }
847
- );
848
- return false;
877
+ throw new Error("transport state is no longer open");
849
878
  }
850
- let reconnectPromise = this.inflightConnectionPromises.get(to);
851
- if (!reconnectPromise) {
852
- const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
853
- if (!this.retryBudget.hasBudget(to)) {
854
- const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
855
- log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
856
- this.protocolError(ProtocolError.RetriesExceeded, errMsg);
857
- return false;
858
- }
859
- let sleep = Promise.resolve();
860
- const backoffMs = this.retryBudget.getBackoffMs(to);
861
- if (backoffMs > 0) {
862
- sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
863
- }
864
- log?.info(
865
- `attempting connection to ${to} (${backoffMs}ms backoff)`,
866
- {
867
- clientId: this.clientId,
868
- connectedTo: to
869
- }
870
- );
871
- this.retryBudget.consumeBudget(to);
872
- reconnectPromise = sleep.then(() => {
873
- if (!canProceedWithConnection()) {
874
- throw new Error("transport state is no longer open");
875
- }
876
- }).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
877
- if (!canProceedWithConnection()) {
878
- log?.info(
879
- `transport state is no longer open, closing pre-handshake connection to ${to}`,
880
- {
881
- clientId: this.clientId,
882
- connectedTo: to,
883
- connId: conn.debugId
884
- }
885
- );
886
- conn.close();
887
- throw new Error("transport state is no longer open");
888
- }
889
- return this.sendHandshake(to, conn).then((ok) => {
890
- if (!ok) {
891
- conn.close();
892
- throw new Error("failed to send handshake");
893
- }
894
- return conn;
895
- });
896
- });
897
- this.inflightConnectionPromises.set(to, reconnectPromise);
898
- } else {
879
+ span.addEvent("connecting");
880
+ const conn = await this.createNewOutgoingConnection(to);
881
+ if (!canProceedWithConnection()) {
899
882
  log?.info(
900
- `attempting connection to ${to} (reusing previous attempt)`,
883
+ `transport state is no longer open, closing pre-handshake connection to ${to}`,
901
884
  {
902
885
  clientId: this.clientId,
903
- connectedTo: to
886
+ connectedTo: to,
887
+ connId: conn.id
904
888
  }
905
889
  );
890
+ conn.close();
891
+ throw new Error("transport state is no longer open");
906
892
  }
907
- try {
908
- await reconnectPromise;
909
- } catch (error) {
910
- this.inflightConnectionPromises.delete(to);
911
- const errStr = coerceErrorString(error);
912
- if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
913
- log?.warn(`connection to ${to} failed (${errStr})`, {
914
- clientId: this.clientId,
915
- connectedTo: to
916
- });
917
- } else {
918
- log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
919
- clientId: this.clientId,
920
- connectedTo: to
921
- });
922
- return true;
923
- }
924
- }
925
- } catch (e) {
926
- if (e instanceof Error) {
927
- span.recordException(e);
928
- } else {
929
- span.recordException(coerceErrorString(e));
893
+ span.addEvent("sending handshake");
894
+ const ok = await this.sendHandshake(to, conn);
895
+ if (!ok) {
896
+ conn.close();
897
+ throw new Error("failed to send handshake");
930
898
  }
931
- span.setStatus({ code: SpanStatusCode.ERROR });
899
+ return conn;
900
+ } catch (err) {
901
+ const errStr = coerceErrorString(err);
902
+ span.recordException(errStr);
903
+ span.setStatus({ code: SpanStatusCode2.ERROR });
904
+ throw err;
932
905
  } finally {
933
906
  span.end();
934
907
  }
935
- return false;
908
+ });
909
+ this.inflightConnectionPromises.set(to, reconnectPromise);
910
+ } else {
911
+ log?.info(`attempting connection to ${to} (reusing previous attempt)`, {
912
+ clientId: this.clientId,
913
+ connectedTo: to
914
+ });
915
+ }
916
+ try {
917
+ await reconnectPromise;
918
+ } catch (error) {
919
+ this.inflightConnectionPromises.delete(to);
920
+ const errStr = coerceErrorString(error);
921
+ if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
922
+ log?.warn(`connection to ${to} failed (${errStr})`, {
923
+ clientId: this.clientId,
924
+ connectedTo: to
925
+ });
926
+ } else {
927
+ log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
928
+ clientId: this.clientId,
929
+ connectedTo: to
930
+ });
931
+ return this.connect(to);
936
932
  }
937
- );
938
- if (retry) {
939
- return this.connectAttempt(to, attempt + 1);
940
933
  }
941
934
  }
942
935
  deleteSession(session) {
@@ -944,8 +937,6 @@ var ClientTransport = class extends Transport {
944
937
  super.deleteSession(session);
945
938
  }
946
939
  async sendHandshake(to, conn) {
947
- const tracing = { traceparent: "", tracestate: "" };
948
- propagation.inject(context.active(), tracing);
949
940
  let metadata;
950
941
  if (this.options.handshake) {
951
942
  metadata = await this.options.handshake.get();
@@ -959,6 +950,10 @@ var ClientTransport = class extends Transport {
959
950
  ProtocolError.HandshakeFailed,
960
951
  "handshake metadata did not match schema"
961
952
  );
953
+ conn.telemetry?.span.setStatus({
954
+ code: SpanStatusCode2.ERROR,
955
+ message: "handshake meta mismatch"
956
+ });
962
957
  return false;
963
958
  }
964
959
  }
@@ -968,7 +963,7 @@ var ClientTransport = class extends Transport {
968
963
  to,
969
964
  session.id,
970
965
  metadata,
971
- tracing
966
+ getPropagationContext(session.telemetry.ctx)
972
967
  );
973
968
  log?.debug(`sending handshake request to ${to}`, {
974
969
  clientId: this.clientId,
@@ -999,268 +994,233 @@ var ServerTransport = class extends Transport {
999
994
  });
1000
995
  }
1001
996
  handleConnection(conn) {
1002
- tracing_default.startActiveSpan(
1003
- "handleConnection",
1004
- {
1005
- attributes: {
1006
- component: "river",
1007
- "span.kind": "server"
1008
- },
1009
- kind: SpanKind.SERVER
1010
- },
1011
- (span) => {
1012
- if (this.state !== "open")
1013
- return;
1014
- log?.info(`new incoming connection`, {
1015
- clientId: this.clientId,
1016
- connId: conn.debugId
997
+ if (this.state !== "open")
998
+ return;
999
+ log?.info(`new incoming connection`, {
1000
+ clientId: this.clientId,
1001
+ connId: conn.id
1002
+ });
1003
+ let session = void 0;
1004
+ const client = () => session?.to ?? "unknown";
1005
+ const handshakeTimeout = setTimeout(() => {
1006
+ if (!session) {
1007
+ log?.warn(
1008
+ `connection to ${client()} timed out waiting for handshake, closing`,
1009
+ {
1010
+ clientId: this.clientId,
1011
+ connectedTo: client(),
1012
+ connId: conn.id
1013
+ }
1014
+ );
1015
+ conn.telemetry?.span.setStatus({
1016
+ code: SpanStatusCode2.ERROR,
1017
+ message: "handshake timeout"
1017
1018
  });
1018
- let session = void 0;
1019
- const client = () => session?.to ?? "unknown";
1020
- const handshakeTimeout = setTimeout(() => {
1021
- if (!session) {
1022
- log?.warn(
1023
- `connection to ${client()} timed out waiting for handshake, closing`,
1024
- {
1025
- clientId: this.clientId,
1026
- connectedTo: client(),
1027
- connId: conn.debugId
1028
- }
1029
- );
1030
- span.setStatus({ code: SpanStatusCode.ERROR });
1031
- span.end();
1019
+ conn.close();
1020
+ }
1021
+ }, this.options.sessionDisconnectGraceMs);
1022
+ const buffer = [];
1023
+ let receivedHandshakeMessage = false;
1024
+ const handshakeHandler = (data) => {
1025
+ if (receivedHandshakeMessage) {
1026
+ buffer.push(data);
1027
+ return;
1028
+ }
1029
+ receivedHandshakeMessage = true;
1030
+ clearTimeout(handshakeTimeout);
1031
+ void this.receiveHandshakeRequestMessage(data, conn).then(
1032
+ (maybeSession) => {
1033
+ if (!maybeSession) {
1032
1034
  conn.close();
1033
- }
1034
- }, this.options.sessionDisconnectGraceMs);
1035
- const buffer = [];
1036
- let receivedHandshakeMessage = false;
1037
- const handshakeHandler = (data) => {
1038
- if (receivedHandshakeMessage) {
1039
- buffer.push(data);
1040
1035
  return;
1041
1036
  }
1042
- receivedHandshakeMessage = true;
1043
- clearTimeout(handshakeTimeout);
1044
- void this.receiveHandshakeRequestMessage(data, conn).then(
1045
- (maybeSession) => {
1046
- if (!maybeSession) {
1047
- span.setStatus({ code: SpanStatusCode.ERROR });
1048
- span.end();
1049
- conn.close();
1050
- return;
1051
- }
1052
- session = maybeSession;
1053
- const dataHandler = (data2) => {
1054
- const parsed = this.parseMsg(data2);
1055
- if (!parsed) {
1056
- conn.close();
1057
- return;
1058
- }
1059
- this.handleMsg(parsed);
1060
- };
1061
- conn.removeDataListener(handshakeHandler);
1062
- conn.addDataListener(dataHandler);
1063
- for (const data2 of buffer) {
1064
- dataHandler(data2);
1065
- }
1066
- buffer.length = 0;
1037
+ session = maybeSession;
1038
+ const dataHandler = (data2) => {
1039
+ const parsed = this.parseMsg(data2);
1040
+ if (!parsed) {
1041
+ conn.close();
1042
+ return;
1067
1043
  }
1068
- );
1069
- };
1070
- conn.addDataListener(handshakeHandler);
1071
- conn.addCloseListener(() => {
1072
- if (session) {
1073
- log?.info(`connection to ${client()} disconnected`, {
1074
- clientId: this.clientId,
1075
- connId: conn.debugId
1076
- });
1077
- this.onDisconnect(conn, session);
1078
- }
1079
- span.setStatus({ code: SpanStatusCode.OK });
1080
- span.end();
1081
- });
1082
- conn.addErrorListener((err) => {
1083
- if (session) {
1084
- log?.warn(
1085
- `connection to ${client()} got an error: ${coerceErrorString(
1086
- err
1087
- )}`,
1088
- { clientId: this.clientId, connId: conn.debugId }
1089
- );
1044
+ this.handleMsg(parsed);
1045
+ };
1046
+ for (const data2 of buffer) {
1047
+ dataHandler(data2);
1090
1048
  }
1091
- span.setStatus({ code: SpanStatusCode.ERROR });
1092
- span.end();
1093
- });
1094
- }
1095
- );
1049
+ conn.removeDataListener(handshakeHandler);
1050
+ conn.addDataListener(dataHandler);
1051
+ buffer.length = 0;
1052
+ }
1053
+ );
1054
+ };
1055
+ conn.addDataListener(handshakeHandler);
1056
+ conn.addCloseListener(() => {
1057
+ if (!session)
1058
+ return;
1059
+ log?.info(`connection to ${client()} disconnected`, {
1060
+ clientId: this.clientId,
1061
+ connId: conn.id
1062
+ });
1063
+ this.onDisconnect(conn, session);
1064
+ });
1065
+ conn.addErrorListener((err) => {
1066
+ conn.telemetry?.span.setStatus({
1067
+ code: SpanStatusCode2.ERROR,
1068
+ message: "connection error"
1069
+ });
1070
+ if (!session)
1071
+ return;
1072
+ log?.warn(
1073
+ `connection to ${client()} got an error: ${coerceErrorString(err)}`,
1074
+ { clientId: this.clientId, connId: conn.id }
1075
+ );
1076
+ });
1096
1077
  }
1097
1078
  async receiveHandshakeRequestMessage(data, conn) {
1098
1079
  const parsed = this.parseMsg(data);
1099
1080
  if (!parsed) {
1081
+ conn.telemetry?.span.setStatus({
1082
+ code: SpanStatusCode2.ERROR,
1083
+ message: "non-transport message"
1084
+ });
1100
1085
  this.protocolError(
1101
1086
  ProtocolError.HandshakeFailed,
1102
1087
  "received non-transport message"
1103
1088
  );
1104
1089
  return false;
1105
1090
  }
1106
- let activeContext = context.active();
1107
- if (parsed.tracing) {
1108
- activeContext = propagation.extract(activeContext, parsed.tracing);
1091
+ if (!Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1092
+ conn.telemetry?.span.setStatus({
1093
+ code: SpanStatusCode2.ERROR,
1094
+ message: "invalid handshake request"
1095
+ });
1096
+ const reason = "received invalid handshake msg";
1097
+ const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1098
+ ok: false,
1099
+ reason
1100
+ });
1101
+ conn.send(this.codec.toBuffer(responseMsg2));
1102
+ const logData = { ...parsed.payload ?? {}, metadata: "redacted" };
1103
+ log?.warn(reason, {
1104
+ clientId: this.clientId,
1105
+ connId: conn.id,
1106
+ partialTransportMessage: { ...parsed, payload: logData }
1107
+ });
1108
+ this.protocolError(
1109
+ ProtocolError.HandshakeFailed,
1110
+ "invalid handshake request"
1111
+ );
1112
+ return false;
1109
1113
  }
1110
- return tracing_default.startActiveSpan(
1111
- "receiveHandshakeRequestMessage",
1112
- {
1113
- attributes: {
1114
- component: "river",
1115
- "span.kind": "server"
1116
- },
1117
- kind: SpanKind.SERVER
1118
- },
1119
- activeContext,
1120
- async (span) => {
1121
- if (!Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1122
- const reason = "received invalid handshake msg";
1123
- const responseMsg2 = handshakeResponseMessage(
1124
- this.clientId,
1125
- parsed.from,
1126
- {
1127
- ok: false,
1128
- reason
1129
- }
1130
- );
1131
- conn.send(this.codec.toBuffer(responseMsg2));
1132
- const logData = typeof parsed.payload === "object" ? {
1133
- ...parsed,
1134
- payload: { ...parsed.payload, metadata: "redacted" }
1135
- } : { ...parsed };
1136
- log?.warn(`${reason}: ${JSON.stringify(logData)}`, {
1137
- clientId: this.clientId,
1138
- connId: conn.debugId
1139
- });
1140
- this.protocolError(
1141
- ProtocolError.HandshakeFailed,
1142
- "invalid handshake request"
1143
- );
1144
- span.setStatus({ code: SpanStatusCode.ERROR });
1145
- span.end();
1146
- return false;
1147
- }
1148
- const gotVersion = parsed.payload.protocolVersion;
1149
- if (gotVersion !== PROTOCOL_VERSION) {
1150
- const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1151
- const responseMsg2 = handshakeResponseMessage(
1152
- this.clientId,
1153
- parsed.from,
1154
- {
1155
- ok: false,
1156
- reason
1157
- }
1158
- );
1159
- conn.send(this.codec.toBuffer(responseMsg2));
1160
- log?.warn(
1161
- `received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
1162
- { clientId: this.clientId, connId: conn.debugId }
1163
- );
1164
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1165
- span.setStatus({ code: SpanStatusCode.ERROR });
1166
- span.end();
1167
- return false;
1168
- }
1169
- const { session, isReconnect } = this.getOrCreateSession(
1114
+ const gotVersion = parsed.payload.protocolVersion;
1115
+ if (gotVersion !== PROTOCOL_VERSION) {
1116
+ conn.telemetry?.span.setStatus({
1117
+ code: SpanStatusCode2.ERROR,
1118
+ message: "incorrect protocol version"
1119
+ });
1120
+ const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1121
+ const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1122
+ ok: false,
1123
+ reason
1124
+ });
1125
+ conn.send(this.codec.toBuffer(responseMsg2));
1126
+ log?.warn(
1127
+ `received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
1128
+ { clientId: this.clientId, connId: conn.id }
1129
+ );
1130
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1131
+ return false;
1132
+ }
1133
+ const { session, isReconnect } = this.getOrCreateSession(
1134
+ parsed.from,
1135
+ conn,
1136
+ parsed.payload.sessionId,
1137
+ parsed.tracing
1138
+ );
1139
+ let handshakeMetadata;
1140
+ if (this.options.handshake) {
1141
+ if (!Value.Check(
1142
+ this.options.handshake.requestSchema,
1143
+ parsed.payload.metadata
1144
+ )) {
1145
+ conn.telemetry?.span.setStatus({
1146
+ code: SpanStatusCode2.ERROR,
1147
+ message: "malformed handshake meta"
1148
+ });
1149
+ const reason = "received malformed handshake metadata";
1150
+ const responseMsg2 = handshakeResponseMessage(
1151
+ this.clientId,
1170
1152
  parsed.from,
1171
- conn,
1172
- parsed.payload.sessionId
1153
+ { ok: false, reason }
1173
1154
  );
1174
- let handshakeMetadata;
1175
- if (this.options.handshake) {
1176
- if (!Value.Check(
1177
- this.options.handshake.requestSchema,
1178
- parsed.payload.metadata
1179
- )) {
1180
- const reason = "received malformed handshake metadata";
1181
- const responseMsg2 = handshakeResponseMessage(
1182
- this.clientId,
1183
- parsed.from,
1184
- { ok: false, reason }
1185
- );
1186
- conn.send(this.codec.toBuffer(responseMsg2));
1187
- log?.warn(
1188
- `received malformed handshake metadata from ${parsed.from}`,
1189
- {
1190
- clientId: this.clientId,
1191
- connId: conn.debugId
1192
- }
1193
- );
1194
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1195
- this.deleteSession(session);
1196
- span.setStatus({ code: SpanStatusCode.ERROR });
1197
- span.end();
1198
- return false;
1199
- }
1200
- const parsedMetadata = await this.options.handshake.parse(
1201
- parsed.payload.metadata,
1202
- session,
1203
- isReconnect
1204
- );
1205
- if (parsedMetadata === false) {
1206
- const reason = "rejected by server";
1207
- const responseMsg2 = handshakeResponseMessage(
1208
- this.clientId,
1209
- parsed.from,
1210
- { ok: false, reason }
1211
- );
1212
- conn.send(this.codec.toBuffer(responseMsg2));
1213
- log?.warn(`rejected handshake from ${parsed.from}`, {
1214
- clientId: this.clientId,
1215
- connId: conn.debugId
1216
- });
1217
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1218
- this.deleteSession(session);
1219
- span.setStatus({ code: SpanStatusCode.ERROR });
1220
- span.end();
1221
- return false;
1222
- }
1223
- if (!Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
1224
- const reason = "failed to parse handshake metadata";
1225
- const responseMsg2 = handshakeResponseMessage(
1226
- this.clientId,
1227
- parsed.from,
1228
- { ok: false, reason }
1229
- );
1230
- conn.send(this.codec.toBuffer(responseMsg2));
1231
- log?.error(`failed to parse handshake metadata`, {
1232
- clientId: this.clientId,
1233
- connId: conn.debugId,
1234
- tags: ["invariant-violation"]
1235
- });
1236
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1237
- this.deleteSession(session);
1238
- span.setStatus({ code: SpanStatusCode.ERROR });
1239
- span.end();
1240
- return false;
1241
- }
1242
- handshakeMetadata = parsedMetadata;
1243
- }
1244
- handshakeMetadata ??= {};
1245
- session.metadata = handshakeMetadata;
1246
- log?.debug(
1247
- `handshake from ${parsed.from} ok, responding with handshake success`,
1248
- { clientId: this.clientId, connId: conn.debugId }
1155
+ conn.send(this.codec.toBuffer(responseMsg2));
1156
+ log?.warn(`received malformed handshake metadata from ${parsed.from}`, {
1157
+ clientId: this.clientId,
1158
+ connId: conn.id
1159
+ });
1160
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1161
+ this.deleteSession(session);
1162
+ return false;
1163
+ }
1164
+ const parsedMetadata = await this.options.handshake.parse(
1165
+ parsed.payload.metadata,
1166
+ session,
1167
+ isReconnect
1168
+ );
1169
+ if (parsedMetadata === false) {
1170
+ conn.telemetry?.span.setStatus({
1171
+ code: SpanStatusCode2.ERROR,
1172
+ message: "rejected by handshake handler"
1173
+ });
1174
+ const reason = "rejected by handshake handler";
1175
+ const responseMsg2 = handshakeResponseMessage(
1176
+ this.clientId,
1177
+ parsed.from,
1178
+ { ok: false, reason }
1249
1179
  );
1250
- const responseMsg = handshakeResponseMessage(
1180
+ conn.send(this.codec.toBuffer(responseMsg2));
1181
+ log?.warn(`rejected handshake from ${parsed.from}`, {
1182
+ clientId: this.clientId,
1183
+ connId: conn.id
1184
+ });
1185
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1186
+ this.deleteSession(session);
1187
+ return false;
1188
+ }
1189
+ if (!Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
1190
+ conn.telemetry?.span.setStatus({
1191
+ code: SpanStatusCode2.ERROR,
1192
+ message: "malformed handshake meta"
1193
+ });
1194
+ const reason = "failed to parse handshake metadata";
1195
+ const responseMsg2 = handshakeResponseMessage(
1251
1196
  this.clientId,
1252
1197
  parsed.from,
1253
- {
1254
- ok: true,
1255
- sessionId: session.id
1256
- }
1198
+ { ok: false, reason }
1257
1199
  );
1258
- conn.send(this.codec.toBuffer(responseMsg));
1259
- this.onConnect(conn, parsed.from, session, isReconnect);
1260
- span.end();
1261
- return session;
1200
+ conn.send(this.codec.toBuffer(responseMsg2));
1201
+ log?.error(`failed to parse handshake metadata`, {
1202
+ clientId: this.clientId,
1203
+ connId: conn.id
1204
+ });
1205
+ this.protocolError(ProtocolError.HandshakeFailed, reason);
1206
+ this.deleteSession(session);
1207
+ return false;
1262
1208
  }
1209
+ handshakeMetadata = parsedMetadata;
1210
+ }
1211
+ handshakeMetadata ??= {};
1212
+ session.metadata = handshakeMetadata;
1213
+ log?.debug(
1214
+ `handshake from ${parsed.from} ok, responding with handshake success`,
1215
+ { clientId: this.clientId, connId: conn.id }
1263
1216
  );
1217
+ const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
1218
+ ok: true,
1219
+ sessionId: session.id
1220
+ });
1221
+ conn.send(this.codec.toBuffer(responseMsg));
1222
+ this.onConnect(conn, parsed.from, session, isReconnect);
1223
+ return session;
1264
1224
  }
1265
1225
  };
1266
1226
 
@@ -1273,4 +1233,4 @@ export {
1273
1233
  ClientTransport,
1274
1234
  ServerTransport
1275
1235
  };
1276
- //# sourceMappingURL=chunk-JMXO5L2X.js.map
1236
+ //# sourceMappingURL=chunk-ZPBWKBM5.js.map