@replit/river 0.23.12 → 0.23.13

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 (74) hide show
  1. package/dist/chunk-2FNLANTJ.js +327 -0
  2. package/dist/chunk-2FNLANTJ.js.map +1 -0
  3. package/dist/{chunk-3AW3IXVD.js → chunk-4PVU7J25.js} +1 -21
  4. package/dist/chunk-4PVU7J25.js.map +1 -0
  5. package/dist/{chunk-H6KTH6W6.js → chunk-4QZOW4DH.js} +2 -2
  6. package/dist/{chunk-7RUKEUKE.js → chunk-ES4XO2XD.js} +2 -2
  7. package/dist/{chunk-7RUKEUKE.js.map → chunk-ES4XO2XD.js.map} +1 -1
  8. package/dist/{chunk-XZ6IOBM5.js → chunk-KFTGQ3QC.js} +2 -2
  9. package/dist/chunk-KFTGQ3QC.js.map +1 -0
  10. package/dist/chunk-S4DUN7KK.js +455 -0
  11. package/dist/chunk-S4DUN7KK.js.map +1 -0
  12. package/dist/{chunk-HDBVL7EF.js → chunk-SX6HI63Q.js} +2 -2
  13. package/dist/chunk-XM656KMN.js +408 -0
  14. package/dist/chunk-XM656KMN.js.map +1 -0
  15. package/dist/chunk-ZUKDZY54.js +271 -0
  16. package/dist/chunk-ZUKDZY54.js.map +1 -0
  17. package/dist/client-dd5c9dd0.d.ts +52 -0
  18. package/dist/codec/index.js +20 -2
  19. package/dist/codec/index.js.map +1 -1
  20. package/dist/{connection-8debd45f.d.ts → connection-39816c00.d.ts} +1 -1
  21. package/dist/{connection-581558f8.d.ts → connection-40318f22.d.ts} +1 -1
  22. package/dist/{transport-47af1c81.d.ts → handshake-e428d1c8.d.ts} +88 -153
  23. package/dist/{index-60f03cb7.d.ts → index-ea74cdbb.d.ts} +1 -1
  24. package/dist/logging/index.d.cts +1 -1
  25. package/dist/logging/index.d.ts +1 -1
  26. package/dist/router/index.cjs +1 -1
  27. package/dist/router/index.cjs.map +1 -1
  28. package/dist/router/index.d.cts +8 -6
  29. package/dist/router/index.d.ts +8 -6
  30. package/dist/router/index.js +2 -2
  31. package/dist/server-ebf80863.d.ts +24 -0
  32. package/dist/{services-ca72c9f8.d.ts → services-f406b3aa.d.ts} +3 -2
  33. package/dist/transport/impls/uds/client.cjs +192 -164
  34. package/dist/transport/impls/uds/client.cjs.map +1 -1
  35. package/dist/transport/impls/uds/client.d.cts +6 -5
  36. package/dist/transport/impls/uds/client.d.ts +6 -5
  37. package/dist/transport/impls/uds/client.js +6 -4
  38. package/dist/transport/impls/uds/client.js.map +1 -1
  39. package/dist/transport/impls/uds/server.cjs +240 -212
  40. package/dist/transport/impls/uds/server.cjs.map +1 -1
  41. package/dist/transport/impls/uds/server.d.cts +6 -5
  42. package/dist/transport/impls/uds/server.d.ts +6 -5
  43. package/dist/transport/impls/uds/server.js +8 -6
  44. package/dist/transport/impls/uds/server.js.map +1 -1
  45. package/dist/transport/impls/ws/client.cjs +194 -166
  46. package/dist/transport/impls/ws/client.cjs.map +1 -1
  47. package/dist/transport/impls/ws/client.d.cts +6 -5
  48. package/dist/transport/impls/ws/client.d.ts +6 -5
  49. package/dist/transport/impls/ws/client.js +6 -4
  50. package/dist/transport/impls/ws/client.js.map +1 -1
  51. package/dist/transport/impls/ws/server.cjs +194 -166
  52. package/dist/transport/impls/ws/server.cjs.map +1 -1
  53. package/dist/transport/impls/ws/server.d.cts +4 -3
  54. package/dist/transport/impls/ws/server.d.ts +4 -3
  55. package/dist/transport/impls/ws/server.js +8 -6
  56. package/dist/transport/impls/ws/server.js.map +1 -1
  57. package/dist/transport/index.cjs +138 -104
  58. package/dist/transport/index.cjs.map +1 -1
  59. package/dist/transport/index.d.cts +4 -2
  60. package/dist/transport/index.d.ts +4 -2
  61. package/dist/transport/index.js +14 -8
  62. package/dist/util/testHelpers.cjs +2 -6
  63. package/dist/util/testHelpers.cjs.map +1 -1
  64. package/dist/util/testHelpers.d.cts +5 -4
  65. package/dist/util/testHelpers.d.ts +5 -4
  66. package/dist/util/testHelpers.js +4 -5
  67. package/dist/util/testHelpers.js.map +1 -1
  68. package/package.json +1 -1
  69. package/dist/chunk-3AW3IXVD.js.map +0 -1
  70. package/dist/chunk-VRU4IKRT.js +0 -1392
  71. package/dist/chunk-VRU4IKRT.js.map +0 -1
  72. package/dist/chunk-XZ6IOBM5.js.map +0 -1
  73. /package/dist/{chunk-H6KTH6W6.js.map → chunk-4QZOW4DH.js.map} +0 -0
  74. /package/dist/{chunk-HDBVL7EF.js.map → chunk-SX6HI63Q.js.map} +0 -0
@@ -0,0 +1,455 @@
1
+ import {
2
+ ProtocolError,
3
+ Transport
4
+ } from "./chunk-XM656KMN.js";
5
+ import {
6
+ defaultClientTransportOptions
7
+ } from "./chunk-2FNLANTJ.js";
8
+ import {
9
+ ControlMessageHandshakeResponseSchema,
10
+ coerceErrorString,
11
+ getPropagationContext,
12
+ handshakeRequestMessage,
13
+ tracing_default
14
+ } from "./chunk-ES4XO2XD.js";
15
+
16
+ // transport/client.ts
17
+ import { SpanStatusCode } from "@opentelemetry/api";
18
+
19
+ // transport/rateLimit.ts
20
+ var LeakyBucketRateLimit = class {
21
+ budgetConsumed;
22
+ intervalHandles;
23
+ options;
24
+ constructor(options) {
25
+ this.options = options;
26
+ this.budgetConsumed = /* @__PURE__ */ new Map();
27
+ this.intervalHandles = /* @__PURE__ */ new Map();
28
+ }
29
+ getBackoffMs(user) {
30
+ if (!this.budgetConsumed.has(user))
31
+ return 0;
32
+ const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
33
+ const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
34
+ const backoffMs = Math.min(
35
+ this.options.baseIntervalMs * 2 ** exponent,
36
+ this.options.maxBackoffMs
37
+ );
38
+ return backoffMs + jitter;
39
+ }
40
+ get totalBudgetRestoreTime() {
41
+ return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
42
+ }
43
+ consumeBudget(user) {
44
+ this.stopLeak(user);
45
+ this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
46
+ }
47
+ getBudgetConsumed(user) {
48
+ return this.budgetConsumed.get(user) ?? 0;
49
+ }
50
+ hasBudget(user) {
51
+ return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
52
+ }
53
+ startRestoringBudget(user) {
54
+ if (this.intervalHandles.has(user)) {
55
+ return;
56
+ }
57
+ const restoreBudgetForUser = () => {
58
+ const currentBudget = this.budgetConsumed.get(user);
59
+ if (!currentBudget) {
60
+ this.stopLeak(user);
61
+ return;
62
+ }
63
+ const newBudget = currentBudget - 1;
64
+ if (newBudget === 0) {
65
+ this.budgetConsumed.delete(user);
66
+ return;
67
+ }
68
+ this.budgetConsumed.set(user, newBudget);
69
+ };
70
+ const intervalHandle = setInterval(
71
+ restoreBudgetForUser,
72
+ this.options.budgetRestoreIntervalMs
73
+ );
74
+ this.intervalHandles.set(user, intervalHandle);
75
+ }
76
+ stopLeak(user) {
77
+ if (!this.intervalHandles.has(user)) {
78
+ return;
79
+ }
80
+ clearInterval(this.intervalHandles.get(user));
81
+ this.intervalHandles.delete(user);
82
+ }
83
+ close() {
84
+ for (const user of this.intervalHandles.keys()) {
85
+ this.stopLeak(user);
86
+ }
87
+ }
88
+ };
89
+
90
+ // transport/client.ts
91
+ import { Value } from "@sinclair/typebox/value";
92
+ var ClientTransport = class extends Transport {
93
+ /**
94
+ * The options for this transport.
95
+ */
96
+ options;
97
+ /**
98
+ * The map of reconnect promises for each client ID.
99
+ */
100
+ inflightConnectionPromises;
101
+ retryBudget;
102
+ /**
103
+ * A flag indicating whether the transport should automatically reconnect
104
+ * when a connection is dropped.
105
+ * Realistically, this should always be true for clients unless you are writing
106
+ * tests or a special case where you don't want to reconnect.
107
+ */
108
+ reconnectOnConnectionDrop = true;
109
+ /**
110
+ * Optional handshake options for this client.
111
+ */
112
+ handshakeExtensions;
113
+ constructor(clientId, providedOptions) {
114
+ super(clientId, providedOptions);
115
+ this.options = {
116
+ ...defaultClientTransportOptions,
117
+ ...providedOptions
118
+ };
119
+ this.inflightConnectionPromises = /* @__PURE__ */ new Map();
120
+ this.retryBudget = new LeakyBucketRateLimit(this.options);
121
+ }
122
+ extendHandshake(options) {
123
+ this.handshakeExtensions = options;
124
+ }
125
+ handleConnection(conn, to) {
126
+ if (this.getStatus() !== "open")
127
+ return;
128
+ let session = void 0;
129
+ const handshakeTimeout = setTimeout(() => {
130
+ if (session)
131
+ return;
132
+ this.log?.warn(
133
+ `connection to ${to} timed out waiting for handshake, closing`,
134
+ { ...conn.loggingMetadata, clientId: this.clientId, connectedTo: to }
135
+ );
136
+ conn.close();
137
+ }, this.options.sessionDisconnectGraceMs);
138
+ const handshakeHandler = (data) => {
139
+ const maybeSession = this.receiveHandshakeResponseMessage(data, conn);
140
+ clearTimeout(handshakeTimeout);
141
+ if (!maybeSession) {
142
+ conn.close();
143
+ return;
144
+ } else {
145
+ session = maybeSession;
146
+ }
147
+ conn.removeDataListener(handshakeHandler);
148
+ conn.addDataListener((data2) => {
149
+ const parsed = this.parseMsg(data2, conn);
150
+ if (!parsed) {
151
+ conn.telemetry?.span.setStatus({
152
+ code: SpanStatusCode.ERROR,
153
+ message: "message parse failure"
154
+ });
155
+ conn.close();
156
+ return;
157
+ }
158
+ this.handleMsg(parsed, conn);
159
+ });
160
+ };
161
+ conn.addDataListener(handshakeHandler);
162
+ conn.addCloseListener(() => {
163
+ if (session) {
164
+ this.onDisconnect(conn, session);
165
+ }
166
+ const willReconnect = this.reconnectOnConnectionDrop && this.getStatus() === "open";
167
+ this.log?.info(
168
+ `connection to ${to} disconnected` + (willReconnect ? ", reconnecting" : ""),
169
+ {
170
+ ...conn.loggingMetadata,
171
+ ...session?.loggingMetadata,
172
+ clientId: this.clientId,
173
+ connectedTo: to
174
+ }
175
+ );
176
+ this.inflightConnectionPromises.delete(to);
177
+ if (this.reconnectOnConnectionDrop) {
178
+ void this.connect(to);
179
+ }
180
+ });
181
+ conn.addErrorListener((err) => {
182
+ conn.telemetry?.span.setStatus({
183
+ code: SpanStatusCode.ERROR,
184
+ message: "connection error"
185
+ });
186
+ this.log?.warn(
187
+ `error in connection to ${to}: ${coerceErrorString(err)}`,
188
+ {
189
+ ...conn.loggingMetadata,
190
+ ...session?.loggingMetadata,
191
+ clientId: this.clientId,
192
+ connectedTo: to
193
+ }
194
+ );
195
+ });
196
+ }
197
+ receiveHandshakeResponseMessage(data, conn) {
198
+ const parsed = this.parseMsg(data, conn);
199
+ if (!parsed) {
200
+ conn.telemetry?.span.setStatus({
201
+ code: SpanStatusCode.ERROR,
202
+ message: "non-transport message"
203
+ });
204
+ this.protocolError(
205
+ ProtocolError.HandshakeFailed,
206
+ "received non-transport message"
207
+ );
208
+ return false;
209
+ }
210
+ if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
211
+ conn.telemetry?.span.setStatus({
212
+ code: SpanStatusCode.ERROR,
213
+ message: "invalid handshake response"
214
+ });
215
+ this.log?.warn(`received invalid handshake resp`, {
216
+ ...conn.loggingMetadata,
217
+ clientId: this.clientId,
218
+ connectedTo: parsed.from,
219
+ transportMessage: parsed,
220
+ validationErrors: [
221
+ ...Value.Errors(
222
+ ControlMessageHandshakeResponseSchema,
223
+ parsed.payload
224
+ )
225
+ ]
226
+ });
227
+ this.protocolError(
228
+ ProtocolError.HandshakeFailed,
229
+ "invalid handshake resp"
230
+ );
231
+ return false;
232
+ }
233
+ if (!parsed.payload.status.ok) {
234
+ conn.telemetry?.span.setStatus({
235
+ code: SpanStatusCode.ERROR,
236
+ message: "handshake rejected"
237
+ });
238
+ this.log?.warn(`received handshake rejection`, {
239
+ ...conn.loggingMetadata,
240
+ clientId: this.clientId,
241
+ connectedTo: parsed.from,
242
+ transportMessage: parsed
243
+ });
244
+ this.protocolError(
245
+ ProtocolError.HandshakeFailed,
246
+ parsed.payload.status.reason
247
+ );
248
+ return false;
249
+ }
250
+ const previousSession = this.sessions.get(parsed.from);
251
+ if (previousSession?.advertisedSessionId && previousSession.advertisedSessionId !== parsed.payload.status.sessionId) {
252
+ this.deleteSession({
253
+ session: previousSession,
254
+ closeHandshakingConnection: true
255
+ });
256
+ conn.telemetry?.span.setStatus({
257
+ code: SpanStatusCode.ERROR,
258
+ message: "session id mismatch"
259
+ });
260
+ this.log?.warn(`handshake from ${parsed.from} session id mismatch`, {
261
+ ...conn.loggingMetadata,
262
+ clientId: this.clientId,
263
+ connectedTo: parsed.from,
264
+ transportMessage: parsed
265
+ });
266
+ this.protocolError(ProtocolError.HandshakeFailed, "session id mismatch");
267
+ return false;
268
+ }
269
+ this.log?.debug(`handshake from ${parsed.from} ok`, {
270
+ ...conn.loggingMetadata,
271
+ clientId: this.clientId,
272
+ connectedTo: parsed.from,
273
+ transportMessage: parsed
274
+ });
275
+ const { session, isTransparentReconnect } = this.getOrCreateSession({
276
+ to: parsed.from,
277
+ conn,
278
+ sessionId: parsed.payload.status.sessionId
279
+ });
280
+ this.onConnect(conn, session, isTransparentReconnect);
281
+ this.retryBudget.startRestoringBudget(session.to);
282
+ return session;
283
+ }
284
+ /**
285
+ * Manually attempts to connect to a client.
286
+ * @param to The client ID of the node to connect to.
287
+ */
288
+ async connect(to) {
289
+ if (this.connections.has(to)) {
290
+ this.log?.info(`already connected to ${to}, skipping connect attempt`, {
291
+ clientId: this.clientId,
292
+ connectedTo: to
293
+ });
294
+ return;
295
+ }
296
+ const canProceedWithConnection = () => this.getStatus() === "open";
297
+ if (!canProceedWithConnection()) {
298
+ this.log?.info(
299
+ `transport state is no longer open, cancelling attempt to connect to ${to}`,
300
+ { clientId: this.clientId, connectedTo: to }
301
+ );
302
+ return;
303
+ }
304
+ let reconnectPromise = this.inflightConnectionPromises.get(to);
305
+ if (!reconnectPromise) {
306
+ if (!this.retryBudget.hasBudget(to)) {
307
+ const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
308
+ const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
309
+ this.log?.error(errMsg, { clientId: this.clientId, connectedTo: to });
310
+ this.protocolError(ProtocolError.RetriesExceeded, errMsg);
311
+ return;
312
+ }
313
+ let sleep = Promise.resolve();
314
+ const backoffMs = this.retryBudget.getBackoffMs(to);
315
+ if (backoffMs > 0) {
316
+ sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
317
+ }
318
+ this.log?.info(
319
+ `attempting connection to ${to} (${backoffMs}ms backoff)`,
320
+ {
321
+ clientId: this.clientId,
322
+ connectedTo: to
323
+ }
324
+ );
325
+ this.retryBudget.consumeBudget(to);
326
+ reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
327
+ try {
328
+ span.addEvent("backoff", { backoffMs });
329
+ await sleep;
330
+ if (!canProceedWithConnection()) {
331
+ throw new Error("transport state is no longer open");
332
+ }
333
+ span.addEvent("connecting");
334
+ const conn = await this.createNewOutgoingConnection(to);
335
+ if (!canProceedWithConnection()) {
336
+ this.log?.info(
337
+ `transport state is no longer open, closing pre-handshake connection to ${to}`,
338
+ {
339
+ ...conn.loggingMetadata,
340
+ clientId: this.clientId,
341
+ connectedTo: to
342
+ }
343
+ );
344
+ conn.close();
345
+ throw new Error("transport state is no longer open");
346
+ }
347
+ span.addEvent("sending handshake");
348
+ const ok = await this.sendHandshake(to, conn);
349
+ if (!ok) {
350
+ conn.close();
351
+ throw new Error("failed to send handshake");
352
+ }
353
+ return conn;
354
+ } catch (err) {
355
+ const errStr = coerceErrorString(err);
356
+ span.recordException(errStr);
357
+ span.setStatus({ code: SpanStatusCode.ERROR });
358
+ throw err;
359
+ } finally {
360
+ span.end();
361
+ }
362
+ });
363
+ this.inflightConnectionPromises.set(to, reconnectPromise);
364
+ } else {
365
+ this.log?.info(
366
+ `attempting connection to ${to} (reusing previous attempt)`,
367
+ {
368
+ clientId: this.clientId,
369
+ connectedTo: to
370
+ }
371
+ );
372
+ }
373
+ try {
374
+ await reconnectPromise;
375
+ } catch (error) {
376
+ this.inflightConnectionPromises.delete(to);
377
+ const errStr = coerceErrorString(error);
378
+ if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
379
+ this.log?.warn(`connection to ${to} failed (${errStr})`, {
380
+ clientId: this.clientId,
381
+ connectedTo: to
382
+ });
383
+ } else {
384
+ this.log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
385
+ clientId: this.clientId,
386
+ connectedTo: to
387
+ });
388
+ await this.connect(to);
389
+ }
390
+ }
391
+ }
392
+ deleteSession({
393
+ session,
394
+ closeHandshakingConnection,
395
+ handshakingConn
396
+ }) {
397
+ this.inflightConnectionPromises.delete(session.to);
398
+ super.deleteSession({
399
+ session,
400
+ closeHandshakingConnection,
401
+ handshakingConn
402
+ });
403
+ }
404
+ async sendHandshake(to, conn) {
405
+ let metadata = void 0;
406
+ if (this.handshakeExtensions) {
407
+ metadata = await this.handshakeExtensions.construct();
408
+ if (!Value.Check(this.handshakeExtensions.schema, metadata)) {
409
+ this.log?.error(`constructed handshake metadata did not match schema`, {
410
+ ...conn.loggingMetadata,
411
+ clientId: this.clientId,
412
+ connectedTo: to,
413
+ validationErrors: [
414
+ ...Value.Errors(this.handshakeExtensions.schema, metadata)
415
+ ],
416
+ tags: ["invariant-violation"]
417
+ });
418
+ this.protocolError(
419
+ ProtocolError.HandshakeFailed,
420
+ "handshake metadata did not match schema"
421
+ );
422
+ conn.telemetry?.span.setStatus({
423
+ code: SpanStatusCode.ERROR,
424
+ message: "handshake meta mismatch"
425
+ });
426
+ return false;
427
+ }
428
+ }
429
+ const { session } = this.getOrCreateSession({ to, handshakingConn: conn });
430
+ const requestMsg = handshakeRequestMessage(
431
+ this.clientId,
432
+ to,
433
+ session.id,
434
+ metadata,
435
+ getPropagationContext(session.telemetry.ctx)
436
+ );
437
+ this.log?.debug(`sending handshake request to ${to}`, {
438
+ ...conn.loggingMetadata,
439
+ clientId: this.clientId,
440
+ connectedTo: to,
441
+ transportMessage: requestMsg
442
+ });
443
+ conn.send(this.codec.toBuffer(requestMsg));
444
+ return true;
445
+ }
446
+ close() {
447
+ this.retryBudget.close();
448
+ super.close();
449
+ }
450
+ };
451
+
452
+ export {
453
+ ClientTransport
454
+ };
455
+ //# sourceMappingURL=chunk-S4DUN7KK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../transport/client.ts","../transport/rateLimit.ts"],"sourcesContent":["import { SpanStatusCode } from '@opentelemetry/api';\nimport { ClientHandshakeOptions } from '../router/handshake';\nimport {\n ControlMessageHandshakeResponseSchema,\n TransportClientId,\n handshakeRequestMessage,\n} from './message';\nimport {\n ClientTransportOptions,\n ProvidedClientTransportOptions,\n defaultClientTransportOptions,\n} from './options';\nimport { LeakyBucketRateLimit } from './rateLimit';\nimport { Connection, Session } from './session';\nimport { Transport } from './transport';\nimport { coerceErrorString } from '../util/stringify';\nimport { ProtocolError } from './events';\nimport { Value } from '@sinclair/typebox/value';\nimport tracer, { getPropagationContext } from '../tracing';\n\nexport abstract class ClientTransport<\n ConnType extends Connection,\n> extends Transport<ConnType> {\n /**\n * The options for this transport.\n */\n protected options: ClientTransportOptions;\n\n /**\n * The map of reconnect promises for each client ID.\n */\n inflightConnectionPromises: Map<TransportClientId, Promise<ConnType>>;\n retryBudget: LeakyBucketRateLimit;\n\n /**\n * A flag indicating whether the transport should automatically reconnect\n * when a connection is dropped.\n * Realistically, this should always be true for clients unless you are writing\n * tests or a special case where you don't want to reconnect.\n */\n reconnectOnConnectionDrop = true;\n\n /**\n * Optional handshake options for this client.\n */\n handshakeExtensions?: ClientHandshakeOptions;\n\n constructor(\n clientId: TransportClientId,\n providedOptions?: ProvidedClientTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.options = {\n ...defaultClientTransportOptions,\n ...providedOptions,\n };\n this.inflightConnectionPromises = new Map();\n this.retryBudget = new LeakyBucketRateLimit(this.options);\n }\n\n extendHandshake(options: ClientHandshakeOptions) {\n this.handshakeExtensions = options;\n }\n\n protected handleConnection(conn: ConnType, to: TransportClientId): void {\n if (this.getStatus() !== 'open') return;\n let session: Session<ConnType> | undefined = undefined;\n\n // kill the conn after the grace period if we haven't received a handshake\n const handshakeTimeout = setTimeout(() => {\n if (session) return;\n this.log?.warn(\n `connection to ${to} timed out waiting for handshake, closing`,\n { ...conn.loggingMetadata, clientId: this.clientId, connectedTo: to },\n );\n conn.close();\n }, this.options.sessionDisconnectGraceMs);\n\n const handshakeHandler = (data: Uint8Array) => {\n const maybeSession = this.receiveHandshakeResponseMessage(data, conn);\n clearTimeout(handshakeTimeout);\n if (!maybeSession) {\n conn.close();\n return;\n } else {\n session = maybeSession;\n }\n\n // when we are done handshake sequence,\n // remove handshake listener and use the normal message listener\n conn.removeDataListener(handshakeHandler);\n conn.addDataListener((data) => {\n const parsed = this.parseMsg(data, conn);\n if (!parsed) {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'message parse failure',\n });\n conn.close();\n return;\n }\n\n this.handleMsg(parsed, conn);\n });\n };\n\n conn.addDataListener(handshakeHandler);\n conn.addCloseListener(() => {\n if (session) {\n this.onDisconnect(conn, session);\n }\n\n const willReconnect =\n this.reconnectOnConnectionDrop && this.getStatus() === 'open';\n\n this.log?.info(\n `connection to ${to} disconnected` +\n (willReconnect ? ', reconnecting' : ''),\n {\n ...conn.loggingMetadata,\n ...session?.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n\n this.inflightConnectionPromises.delete(to);\n if (this.reconnectOnConnectionDrop) {\n void this.connect(to);\n }\n });\n conn.addErrorListener((err) => {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'connection error',\n });\n this.log?.warn(\n `error in connection to ${to}: ${coerceErrorString(err)}`,\n {\n ...conn.loggingMetadata,\n ...session?.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n });\n }\n\n receiveHandshakeResponseMessage(\n data: Uint8Array,\n conn: ConnType,\n ): Session<ConnType> | false {\n const parsed = this.parseMsg(data, conn);\n if (!parsed) {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'non-transport message',\n });\n this.protocolError(\n ProtocolError.HandshakeFailed,\n 'received non-transport message',\n );\n return false;\n }\n\n if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'invalid handshake response',\n });\n this.log?.warn(`received invalid handshake resp`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n validationErrors: [\n ...Value.Errors(\n ControlMessageHandshakeResponseSchema,\n parsed.payload,\n ),\n ],\n });\n this.protocolError(\n ProtocolError.HandshakeFailed,\n 'invalid handshake resp',\n );\n return false;\n }\n\n if (!parsed.payload.status.ok) {\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'handshake rejected',\n });\n this.log?.warn(`received handshake rejection`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n });\n this.protocolError(\n ProtocolError.HandshakeFailed,\n parsed.payload.status.reason,\n );\n return false;\n }\n\n // before we claim victory and we deem that the handshake is fully established, check that our\n // session matches the remote's. if they do not match, proactively close the connection.\n // otherwise we will end up breaking a lot of invariants.\n //\n // note that there may be a way to convey the expectation of the client that this is a\n // transparent reconnect to the server so that the server can do the same in a single roundtrip,\n // but that requires a bit more surgery to the handshake.\n const previousSession = this.sessions.get(parsed.from);\n if (\n previousSession?.advertisedSessionId &&\n previousSession.advertisedSessionId !== parsed.payload.status.sessionId\n ) {\n this.deleteSession({\n session: previousSession,\n closeHandshakingConnection: true,\n });\n\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'session id mismatch',\n });\n this.log?.warn(`handshake from ${parsed.from} session id mismatch`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n });\n this.protocolError(ProtocolError.HandshakeFailed, 'session id mismatch');\n return false;\n }\n\n this.log?.debug(`handshake from ${parsed.from} ok`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: parsed.from,\n transportMessage: parsed,\n });\n\n const { session, isTransparentReconnect } = this.getOrCreateSession({\n to: parsed.from,\n conn,\n sessionId: parsed.payload.status.sessionId,\n });\n\n this.onConnect(conn, session, isTransparentReconnect);\n\n // After a successful connection, we start restoring the budget\n // so that the next time we try to connect, we don't hit the client\n // with backoff forever.\n this.retryBudget.startRestoringBudget(session.to);\n return session;\n }\n\n /**\n * Abstract method that creates a new {@link Connection} object.\n * This should call {@link handleConnection} when the connection is created.\n * The downstream client implementation needs to implement this.\n *\n * @param to The client ID of the node to connect to.\n * @returns The new connection object.\n */\n protected abstract createNewOutgoingConnection(\n to: TransportClientId,\n ): Promise<ConnType>;\n\n /**\n * Manually attempts to connect to a client.\n * @param to The client ID of the node to connect to.\n */\n async connect(to: TransportClientId): Promise<void> {\n if (this.connections.has(to)) {\n this.log?.info(`already connected to ${to}, skipping connect attempt`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n return;\n }\n\n const canProceedWithConnection = () => this.getStatus() === 'open';\n if (!canProceedWithConnection()) {\n this.log?.info(\n `transport state is no longer open, cancelling attempt to connect to ${to}`,\n { clientId: this.clientId, connectedTo: to },\n );\n return;\n }\n\n let reconnectPromise = this.inflightConnectionPromises.get(to);\n if (!reconnectPromise) {\n // check budget\n if (!this.retryBudget.hasBudget(to)) {\n const budgetConsumed = this.retryBudget.getBudgetConsumed(to);\n const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;\n this.log?.error(errMsg, { clientId: this.clientId, connectedTo: to });\n this.protocolError(ProtocolError.RetriesExceeded, errMsg);\n return;\n }\n\n let sleep = Promise.resolve();\n const backoffMs = this.retryBudget.getBackoffMs(to);\n if (backoffMs > 0) {\n sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));\n }\n\n this.log?.info(\n `attempting connection to ${to} (${backoffMs}ms backoff)`,\n {\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n this.retryBudget.consumeBudget(to);\n reconnectPromise = tracer.startActiveSpan('connect', async (span) => {\n try {\n span.addEvent('backoff', { backoffMs });\n await sleep;\n if (!canProceedWithConnection()) {\n throw new Error('transport state is no longer open');\n }\n\n span.addEvent('connecting');\n const conn = await this.createNewOutgoingConnection(to);\n if (!canProceedWithConnection()) {\n this.log?.info(\n `transport state is no longer open, closing pre-handshake connection to ${to}`,\n {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n conn.close();\n throw new Error('transport state is no longer open');\n }\n\n span.addEvent('sending handshake');\n const ok = await this.sendHandshake(to, conn);\n if (!ok) {\n conn.close();\n throw new Error('failed to send handshake');\n }\n\n return conn;\n } catch (err) {\n // rethrow the error so that the promise is rejected\n // as it was before we wrapped it in a span\n const errStr = coerceErrorString(err);\n span.recordException(errStr);\n span.setStatus({ code: SpanStatusCode.ERROR });\n throw err;\n } finally {\n span.end();\n }\n });\n\n this.inflightConnectionPromises.set(to, reconnectPromise);\n } else {\n this.log?.info(\n `attempting connection to ${to} (reusing previous attempt)`,\n {\n clientId: this.clientId,\n connectedTo: to,\n },\n );\n }\n\n try {\n await reconnectPromise;\n } catch (error: unknown) {\n this.inflightConnectionPromises.delete(to);\n const errStr = coerceErrorString(error);\n\n if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {\n this.log?.warn(`connection to ${to} failed (${errStr})`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n } else {\n this.log?.warn(`connection to ${to} failed (${errStr}), retrying`, {\n clientId: this.clientId,\n connectedTo: to,\n });\n await this.connect(to);\n }\n }\n }\n\n protected deleteSession({\n session,\n closeHandshakingConnection,\n handshakingConn,\n }: {\n session: Session<ConnType>;\n closeHandshakingConnection: boolean;\n handshakingConn?: ConnType;\n }) {\n this.inflightConnectionPromises.delete(session.to);\n super.deleteSession({\n session,\n closeHandshakingConnection,\n handshakingConn,\n });\n }\n\n protected async sendHandshake(to: TransportClientId, conn: ConnType) {\n let metadata: unknown = undefined;\n\n if (this.handshakeExtensions) {\n metadata = await this.handshakeExtensions.construct();\n if (!Value.Check(this.handshakeExtensions.schema, metadata)) {\n this.log?.error(`constructed handshake metadata did not match schema`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n validationErrors: [\n ...Value.Errors(this.handshakeExtensions.schema, metadata),\n ],\n tags: ['invariant-violation'],\n });\n this.protocolError(\n ProtocolError.HandshakeFailed,\n 'handshake metadata did not match schema',\n );\n conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: 'handshake meta mismatch',\n });\n return false;\n }\n }\n\n // dont pass conn here as we dont want the session to start using the conn\n // until we have finished the handshake. Still, let the session know that\n // it is semi-associated with the conn, and it can close it if .close() is called.\n const { session } = this.getOrCreateSession({ to, handshakingConn: conn });\n const requestMsg = handshakeRequestMessage(\n this.clientId,\n to,\n session.id,\n metadata,\n getPropagationContext(session.telemetry.ctx),\n );\n this.log?.debug(`sending handshake request to ${to}`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n connectedTo: to,\n transportMessage: requestMsg,\n });\n conn.send(this.codec.toBuffer(requestMsg));\n return true;\n }\n\n close() {\n this.retryBudget.close();\n super.close();\n }\n}\n","import { TransportClientId } from './message';\n\n/**\n * Options to control the backoff and retry behavior of the client transport's connection behaviour.\n *\n * River implements exponential backoff with jitter to prevent flooding the server\n * when there's an issue with connection establishment.\n *\n * The backoff is calculated via the following:\n * backOff = min(jitter + {@link baseIntervalMs} * 2 ^ budget_consumed, {@link maxBackoffMs})\n *\n * We use a leaky bucket rate limit with a budget of {@link attemptBudgetCapacity} reconnection attempts.\n * Budget only starts to restore after a successful handshake at a rate of one budget per {@link budgetRestoreIntervalMs}.\n */\nexport interface ConnectionRetryOptions {\n /**\n * The base interval to wait before retrying a connection.\n */\n baseIntervalMs: number;\n\n /**\n * The maximum random jitter to add to the total backoff time.\n */\n maxJitterMs: number;\n\n /**\n * The maximum amount of time to wait before retrying a connection.\n * This does not include the jitter.\n */\n maxBackoffMs: number;\n\n /**\n * The max number of times to attempt a connection before a successful handshake.\n * This persists across connections but starts restoring budget after a successful handshake.\n * The restoration interval depends on {@link budgetRestoreIntervalMs}\n */\n attemptBudgetCapacity: number;\n\n /**\n * After a successful connection attempt, how long to wait before we restore a single budget.\n */\n budgetRestoreIntervalMs: number;\n}\n\nexport class LeakyBucketRateLimit {\n private budgetConsumed: Map<TransportClientId, number>;\n private intervalHandles: Map<\n TransportClientId,\n ReturnType<typeof setInterval>\n >;\n private readonly options: ConnectionRetryOptions;\n\n constructor(options: ConnectionRetryOptions) {\n this.options = options;\n this.budgetConsumed = new Map();\n this.intervalHandles = new Map();\n }\n\n getBackoffMs(user: TransportClientId) {\n if (!this.budgetConsumed.has(user)) return 0;\n\n const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);\n const jitter = Math.floor(Math.random() * this.options.maxJitterMs);\n const backoffMs = Math.min(\n this.options.baseIntervalMs * 2 ** exponent,\n this.options.maxBackoffMs,\n );\n\n return backoffMs + jitter;\n }\n\n get totalBudgetRestoreTime() {\n return (\n this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity\n );\n }\n\n consumeBudget(user: TransportClientId) {\n // If we're consuming again, let's ensure that we're not leaking\n this.stopLeak(user);\n this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);\n }\n\n getBudgetConsumed(user: TransportClientId) {\n return this.budgetConsumed.get(user) ?? 0;\n }\n\n hasBudget(user: TransportClientId) {\n return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;\n }\n\n startRestoringBudget(user: TransportClientId) {\n if (this.intervalHandles.has(user)) {\n return;\n }\n\n const restoreBudgetForUser = () => {\n const currentBudget = this.budgetConsumed.get(user);\n if (!currentBudget) {\n this.stopLeak(user);\n return;\n }\n\n const newBudget = currentBudget - 1;\n if (newBudget === 0) {\n this.budgetConsumed.delete(user);\n return;\n }\n\n this.budgetConsumed.set(user, newBudget);\n };\n\n const intervalHandle = setInterval(\n restoreBudgetForUser,\n this.options.budgetRestoreIntervalMs,\n );\n\n this.intervalHandles.set(user, intervalHandle);\n }\n\n private stopLeak(user: TransportClientId) {\n if (!this.intervalHandles.has(user)) {\n return;\n }\n\n clearInterval(this.intervalHandles.get(user));\n this.intervalHandles.delete(user);\n }\n\n close() {\n for (const user of this.intervalHandles.keys()) {\n this.stopLeak(user);\n }\n }\n}\n"],"mappings":"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","names":["data"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-VRU4IKRT.js";
3
+ } from "./chunk-2FNLANTJ.js";
4
4
 
5
5
  // transport/impls/ws/connection.ts
6
6
  var WebSocketConnection = class extends Connection {
@@ -56,4 +56,4 @@ var WebSocketConnection = class extends Connection {
56
56
  export {
57
57
  WebSocketConnection
58
58
  };
59
- //# sourceMappingURL=chunk-HDBVL7EF.js.map
59
+ //# sourceMappingURL=chunk-SX6HI63Q.js.map