@replit/river 0.207.2 → 0.207.3

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 (56) hide show
  1. package/dist/adapter-f2b6e211.d.ts +46 -0
  2. package/dist/{chunk-4HE7UYRL.js → chunk-B7REV3ZV.js} +6 -5
  3. package/dist/{chunk-4HE7UYRL.js.map → chunk-B7REV3ZV.js.map} +1 -1
  4. package/dist/{chunk-24EWYOGK.js → chunk-BO7MFCO6.js} +1136 -143
  5. package/dist/chunk-BO7MFCO6.js.map +1 -0
  6. package/dist/{chunk-46IVOKJU.js → chunk-QGPYCXV4.js} +2 -2
  7. package/dist/{chunk-46IVOKJU.js.map → chunk-QGPYCXV4.js.map} +1 -1
  8. package/dist/codec/index.cjs +157 -23
  9. package/dist/codec/index.cjs.map +1 -1
  10. package/dist/codec/index.d.cts +5 -1
  11. package/dist/codec/index.d.ts +5 -1
  12. package/dist/codec/index.js +6 -20
  13. package/dist/codec/index.js.map +1 -1
  14. package/dist/{connection-a18e31d5.d.ts → connection-06d72f2e.d.ts} +3 -2
  15. package/dist/index-02554794.d.ts +37 -0
  16. package/dist/logging/index.d.cts +2 -1
  17. package/dist/logging/index.d.ts +2 -1
  18. package/dist/{message-ffacb98a.d.ts → message-01c3e85a.d.ts} +1 -35
  19. package/dist/router/index.cjs +1 -1
  20. package/dist/router/index.cjs.map +1 -1
  21. package/dist/router/index.d.cts +6 -5
  22. package/dist/router/index.d.ts +6 -5
  23. package/dist/router/index.js +1 -1
  24. package/dist/{services-43528f4b.d.ts → services-87887bc5.d.ts} +16 -12
  25. package/dist/testUtil/index.cjs +809 -657
  26. package/dist/testUtil/index.cjs.map +1 -1
  27. package/dist/testUtil/index.d.cts +4 -3
  28. package/dist/testUtil/index.d.ts +4 -3
  29. package/dist/testUtil/index.js +18 -13
  30. package/dist/testUtil/index.js.map +1 -1
  31. package/dist/transport/impls/ws/client.cjs +293 -204
  32. package/dist/transport/impls/ws/client.cjs.map +1 -1
  33. package/dist/transport/impls/ws/client.d.cts +5 -4
  34. package/dist/transport/impls/ws/client.d.ts +5 -4
  35. package/dist/transport/impls/ws/client.js +5 -7
  36. package/dist/transport/impls/ws/client.js.map +1 -1
  37. package/dist/transport/impls/ws/server.cjs +230 -128
  38. package/dist/transport/impls/ws/server.cjs.map +1 -1
  39. package/dist/transport/impls/ws/server.d.cts +5 -4
  40. package/dist/transport/impls/ws/server.d.ts +5 -4
  41. package/dist/transport/impls/ws/server.js +5 -7
  42. package/dist/transport/impls/ws/server.js.map +1 -1
  43. package/dist/transport/index.cjs +408 -270
  44. package/dist/transport/index.cjs.map +1 -1
  45. package/dist/transport/index.d.cts +7 -6
  46. package/dist/transport/index.d.ts +7 -6
  47. package/dist/transport/index.js +4 -9
  48. package/package.json +1 -1
  49. package/dist/chunk-24EWYOGK.js.map +0 -1
  50. package/dist/chunk-A7RGOVRV.js +0 -438
  51. package/dist/chunk-A7RGOVRV.js.map +0 -1
  52. package/dist/chunk-AJGIY2UB.js +0 -56
  53. package/dist/chunk-AJGIY2UB.js.map +0 -1
  54. package/dist/chunk-XV4RQ62N.js +0 -377
  55. package/dist/chunk-XV4RQ62N.js.map +0 -1
  56. package/dist/types-3e5768ec.d.ts +0 -20
@@ -99,7 +99,8 @@ var ProtocolError = {
99
99
  RetriesExceeded: "conn_retry_exceeded",
100
100
  HandshakeFailed: "handshake_failed",
101
101
  MessageOrderingViolated: "message_ordering_violated",
102
- InvalidMessage: "invalid_message"
102
+ InvalidMessage: "invalid_message",
103
+ MessageSendFailure: "message_send_failure"
103
104
  };
104
105
  var EventDispatcher = class {
105
106
  eventListeners = {};
@@ -164,23 +165,20 @@ var NaiveJsonCodec = {
164
165
  );
165
166
  },
166
167
  fromBuffer: (buff) => {
167
- try {
168
- const parsed = JSON.parse(
169
- decoder.decode(buff),
170
- function reviver(_key, val) {
171
- if (val?.$t) {
172
- return base64ToUint8Array(val.$t);
173
- } else {
174
- return val;
175
- }
168
+ const parsed = JSON.parse(
169
+ decoder.decode(buff),
170
+ function reviver(_key, val) {
171
+ if (val?.$t) {
172
+ return base64ToUint8Array(val.$t);
173
+ } else {
174
+ return val;
176
175
  }
177
- );
178
- if (typeof parsed === "object")
179
- return parsed;
180
- return null;
181
- } catch {
182
- return null;
176
+ }
177
+ );
178
+ if (typeof parsed !== "object" || parsed === null) {
179
+ throw new Error("unpacked msg is not an object");
183
180
  }
181
+ return parsed;
184
182
  }
185
183
  };
186
184
 
@@ -209,9 +207,6 @@ var defaultServerTransportOptions = {
209
207
  ...defaultTransportOptions
210
208
  };
211
209
 
212
- // transport/message.ts
213
- var import_typebox = require("@sinclair/typebox");
214
-
215
210
  // transport/id.ts
216
211
  var import_nanoid = require("nanoid");
217
212
  var alphabet = (0, import_nanoid.customAlphabet)(
@@ -219,148 +214,7 @@ var alphabet = (0, import_nanoid.customAlphabet)(
219
214
  );
220
215
  var generateId = () => alphabet(12);
221
216
 
222
- // transport/message.ts
223
- var TransportMessageSchema = (t) => import_typebox.Type.Object({
224
- id: import_typebox.Type.String(),
225
- from: import_typebox.Type.String(),
226
- to: import_typebox.Type.String(),
227
- seq: import_typebox.Type.Integer(),
228
- ack: import_typebox.Type.Integer(),
229
- serviceName: import_typebox.Type.Optional(import_typebox.Type.String()),
230
- procedureName: import_typebox.Type.Optional(import_typebox.Type.String()),
231
- streamId: import_typebox.Type.String(),
232
- controlFlags: import_typebox.Type.Integer(),
233
- tracing: import_typebox.Type.Optional(
234
- import_typebox.Type.Object({
235
- traceparent: import_typebox.Type.String(),
236
- tracestate: import_typebox.Type.String()
237
- })
238
- ),
239
- payload: t
240
- });
241
- var ControlMessageAckSchema = import_typebox.Type.Object({
242
- type: import_typebox.Type.Literal("ACK")
243
- });
244
- var ControlMessageCloseSchema = import_typebox.Type.Object({
245
- type: import_typebox.Type.Literal("CLOSE")
246
- });
247
- var currentProtocolVersion = "v2.0";
248
- var acceptedProtocolVersions = ["v1.1", currentProtocolVersion];
249
- function isAcceptedProtocolVersion(version2) {
250
- return acceptedProtocolVersions.includes(version2);
251
- }
252
- var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
253
- type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
254
- protocolVersion: import_typebox.Type.String(),
255
- sessionId: import_typebox.Type.String(),
256
- /**
257
- * Specifies what the server's expected session state (from the pov of the client). This can be
258
- * used by the server to know whether this is a new or a reestablished connection, and whether it
259
- * is compatible with what it already has.
260
- */
261
- expectedSessionState: import_typebox.Type.Object({
262
- // what the client expects the server to send next
263
- nextExpectedSeq: import_typebox.Type.Integer(),
264
- nextSentSeq: import_typebox.Type.Integer()
265
- }),
266
- metadata: import_typebox.Type.Optional(import_typebox.Type.Unknown())
267
- });
268
- var HandshakeErrorRetriableResponseCodes = import_typebox.Type.Union([
269
- import_typebox.Type.Literal("SESSION_STATE_MISMATCH")
270
- ]);
271
- var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox.Type.Union([
272
- // The custom validation handler rejected the handler because the client is unsupported.
273
- import_typebox.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
274
- // The custom validation handler rejected the handshake.
275
- import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
276
- ]);
277
- var HandshakeErrorFatalResponseCodes = import_typebox.Type.Union([
278
- HandshakeErrorCustomHandlerFatalResponseCodes,
279
- // The ciient sent a handshake that doesn't comply with the extended handshake metadata.
280
- import_typebox.Type.Literal("MALFORMED_HANDSHAKE_META"),
281
- // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
282
- import_typebox.Type.Literal("MALFORMED_HANDSHAKE"),
283
- // The client's protocol version does not match the server's.
284
- import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH")
285
- ]);
286
- var HandshakeErrorResponseCodes = import_typebox.Type.Union([
287
- HandshakeErrorRetriableResponseCodes,
288
- HandshakeErrorFatalResponseCodes
289
- ]);
290
- var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
291
- type: import_typebox.Type.Literal("HANDSHAKE_RESP"),
292
- status: import_typebox.Type.Union([
293
- import_typebox.Type.Object({
294
- ok: import_typebox.Type.Literal(true),
295
- sessionId: import_typebox.Type.String()
296
- }),
297
- import_typebox.Type.Object({
298
- ok: import_typebox.Type.Literal(false),
299
- reason: import_typebox.Type.String(),
300
- code: HandshakeErrorResponseCodes
301
- })
302
- ])
303
- });
304
- var ControlMessagePayloadSchema = import_typebox.Type.Union([
305
- ControlMessageCloseSchema,
306
- ControlMessageAckSchema,
307
- ControlMessageHandshakeRequestSchema,
308
- ControlMessageHandshakeResponseSchema
309
- ]);
310
- var OpaqueTransportMessageSchema = TransportMessageSchema(
311
- import_typebox.Type.Unknown()
312
- );
313
- function handshakeRequestMessage({
314
- from,
315
- to,
316
- sessionId,
317
- expectedSessionState,
318
- metadata,
319
- tracing
320
- }) {
321
- return {
322
- id: generateId(),
323
- from,
324
- to,
325
- seq: 0,
326
- ack: 0,
327
- streamId: generateId(),
328
- controlFlags: 0,
329
- tracing,
330
- payload: {
331
- type: "HANDSHAKE_REQ",
332
- protocolVersion: currentProtocolVersion,
333
- sessionId,
334
- expectedSessionState,
335
- metadata
336
- }
337
- };
338
- }
339
- function handshakeResponseMessage({
340
- from,
341
- to,
342
- status
343
- }) {
344
- return {
345
- id: generateId(),
346
- from,
347
- to,
348
- seq: 0,
349
- ack: 0,
350
- streamId: generateId(),
351
- controlFlags: 0,
352
- payload: {
353
- type: "HANDSHAKE_RESP",
354
- status
355
- }
356
- };
357
- }
358
- function isAck(controlFlag) {
359
- return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
360
- }
361
-
362
217
  // transport/sessionStateMachine/common.ts
363
- var import_value = require("@sinclair/typebox/value");
364
218
  var SessionState = /* @__PURE__ */ ((SessionState2) => {
365
219
  SessionState2["NoConnection"] = "NoConnection";
366
220
  SessionState2["BackingOff"] = "BackingOff";
@@ -429,34 +283,16 @@ var StateMachineState = class {
429
283
  var CommonSession = class extends StateMachineState {
430
284
  from;
431
285
  options;
286
+ codec;
432
287
  tracer;
433
288
  log;
434
- constructor({ from, options, log, tracer }) {
289
+ constructor({ from, options, log, tracer, codec }) {
435
290
  super();
436
291
  this.from = from;
437
292
  this.options = options;
438
293
  this.log = log;
439
294
  this.tracer = tracer;
440
- }
441
- parseMsg(msg) {
442
- const parsedMsg = this.options.codec.fromBuffer(msg);
443
- if (parsedMsg === null) {
444
- this.log?.error(
445
- `received malformed msg: ${Buffer.from(msg).toString("base64")}`,
446
- this.loggingMetadata
447
- );
448
- return null;
449
- }
450
- if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
451
- this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {
452
- ...this.loggingMetadata,
453
- validationErrors: [
454
- ...import_value.Value.Errors(OpaqueTransportMessageSchema, parsedMsg)
455
- ]
456
- });
457
- return null;
458
- }
459
- return parsedMsg;
295
+ this.codec = codec;
460
296
  }
461
297
  };
462
298
  var IdentifiedSession = class extends CommonSession {
@@ -516,9 +352,6 @@ var IdentifiedSession = class extends CommonSession {
516
352
  return metadata;
517
353
  }
518
354
  constructMsg(partialMsg) {
519
- if (this._isConsumed) {
520
- throw new Error(ERR_CONSUMED);
521
- }
522
355
  const msg = {
523
356
  ...partialMsg,
524
357
  id: generateId(),
@@ -536,7 +369,10 @@ var IdentifiedSession = class extends CommonSession {
536
369
  send(msg) {
537
370
  const constructedMsg = this.constructMsg(msg);
538
371
  this.sendBuffer.push(constructedMsg);
539
- return constructedMsg.id;
372
+ return {
373
+ ok: true,
374
+ value: constructedMsg.id
375
+ };
540
376
  }
541
377
  _handleStateExit() {
542
378
  }
@@ -568,6 +404,23 @@ var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
568
404
  super._handleClose();
569
405
  }
570
406
  };
407
+ function sendMessage(conn, codec, msg) {
408
+ const buff = codec.toBuffer(msg);
409
+ if (!buff.ok) {
410
+ return buff;
411
+ }
412
+ const sent = conn.send(buff.value);
413
+ if (!sent) {
414
+ return {
415
+ ok: false,
416
+ reason: "failed to send message"
417
+ };
418
+ }
419
+ return {
420
+ ok: true,
421
+ value: msg.id
422
+ };
423
+ }
571
424
 
572
425
  // transport/sessionStateMachine/SessionConnecting.ts
573
426
  var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
@@ -620,8 +473,8 @@ var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
620
473
  }
621
474
  }
622
475
  _handleClose() {
623
- this.bestEffortClose();
624
476
  super._handleClose();
477
+ this.bestEffortClose();
625
478
  }
626
479
  };
627
480
 
@@ -639,6 +492,147 @@ var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
639
492
  // tracing/index.ts
640
493
  var import_api2 = require("@opentelemetry/api");
641
494
 
495
+ // transport/message.ts
496
+ var import_typebox = require("@sinclair/typebox");
497
+ var TransportMessageSchema = (t) => import_typebox.Type.Object({
498
+ id: import_typebox.Type.String(),
499
+ from: import_typebox.Type.String(),
500
+ to: import_typebox.Type.String(),
501
+ seq: import_typebox.Type.Integer(),
502
+ ack: import_typebox.Type.Integer(),
503
+ serviceName: import_typebox.Type.Optional(import_typebox.Type.String()),
504
+ procedureName: import_typebox.Type.Optional(import_typebox.Type.String()),
505
+ streamId: import_typebox.Type.String(),
506
+ controlFlags: import_typebox.Type.Integer(),
507
+ tracing: import_typebox.Type.Optional(
508
+ import_typebox.Type.Object({
509
+ traceparent: import_typebox.Type.String(),
510
+ tracestate: import_typebox.Type.String()
511
+ })
512
+ ),
513
+ payload: t
514
+ });
515
+ var ControlMessageAckSchema = import_typebox.Type.Object({
516
+ type: import_typebox.Type.Literal("ACK")
517
+ });
518
+ var ControlMessageCloseSchema = import_typebox.Type.Object({
519
+ type: import_typebox.Type.Literal("CLOSE")
520
+ });
521
+ var currentProtocolVersion = "v2.0";
522
+ var acceptedProtocolVersions = ["v1.1", currentProtocolVersion];
523
+ function isAcceptedProtocolVersion(version2) {
524
+ return acceptedProtocolVersions.includes(version2);
525
+ }
526
+ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
527
+ type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
528
+ protocolVersion: import_typebox.Type.String(),
529
+ sessionId: import_typebox.Type.String(),
530
+ /**
531
+ * Specifies what the server's expected session state (from the pov of the client). This can be
532
+ * used by the server to know whether this is a new or a reestablished connection, and whether it
533
+ * is compatible with what it already has.
534
+ */
535
+ expectedSessionState: import_typebox.Type.Object({
536
+ // what the client expects the server to send next
537
+ nextExpectedSeq: import_typebox.Type.Integer(),
538
+ nextSentSeq: import_typebox.Type.Integer()
539
+ }),
540
+ metadata: import_typebox.Type.Optional(import_typebox.Type.Unknown())
541
+ });
542
+ var HandshakeErrorRetriableResponseCodes = import_typebox.Type.Union([
543
+ import_typebox.Type.Literal("SESSION_STATE_MISMATCH")
544
+ ]);
545
+ var HandshakeErrorCustomHandlerFatalResponseCodes = import_typebox.Type.Union([
546
+ // The custom validation handler rejected the handler because the client is unsupported.
547
+ import_typebox.Type.Literal("REJECTED_UNSUPPORTED_CLIENT"),
548
+ // The custom validation handler rejected the handshake.
549
+ import_typebox.Type.Literal("REJECTED_BY_CUSTOM_HANDLER")
550
+ ]);
551
+ var HandshakeErrorFatalResponseCodes = import_typebox.Type.Union([
552
+ HandshakeErrorCustomHandlerFatalResponseCodes,
553
+ // The ciient sent a handshake that doesn't comply with the extended handshake metadata.
554
+ import_typebox.Type.Literal("MALFORMED_HANDSHAKE_META"),
555
+ // The ciient sent a handshake that doesn't comply with ControlMessageHandshakeRequestSchema.
556
+ import_typebox.Type.Literal("MALFORMED_HANDSHAKE"),
557
+ // The client's protocol version does not match the server's.
558
+ import_typebox.Type.Literal("PROTOCOL_VERSION_MISMATCH")
559
+ ]);
560
+ var HandshakeErrorResponseCodes = import_typebox.Type.Union([
561
+ HandshakeErrorRetriableResponseCodes,
562
+ HandshakeErrorFatalResponseCodes
563
+ ]);
564
+ var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
565
+ type: import_typebox.Type.Literal("HANDSHAKE_RESP"),
566
+ status: import_typebox.Type.Union([
567
+ import_typebox.Type.Object({
568
+ ok: import_typebox.Type.Literal(true),
569
+ sessionId: import_typebox.Type.String()
570
+ }),
571
+ import_typebox.Type.Object({
572
+ ok: import_typebox.Type.Literal(false),
573
+ reason: import_typebox.Type.String(),
574
+ code: HandshakeErrorResponseCodes
575
+ })
576
+ ])
577
+ });
578
+ var ControlMessagePayloadSchema = import_typebox.Type.Union([
579
+ ControlMessageCloseSchema,
580
+ ControlMessageAckSchema,
581
+ ControlMessageHandshakeRequestSchema,
582
+ ControlMessageHandshakeResponseSchema
583
+ ]);
584
+ var OpaqueTransportMessageSchema = TransportMessageSchema(
585
+ import_typebox.Type.Unknown()
586
+ );
587
+ function handshakeRequestMessage({
588
+ from,
589
+ to,
590
+ sessionId,
591
+ expectedSessionState,
592
+ metadata,
593
+ tracing
594
+ }) {
595
+ return {
596
+ id: generateId(),
597
+ from,
598
+ to,
599
+ seq: 0,
600
+ ack: 0,
601
+ streamId: generateId(),
602
+ controlFlags: 0,
603
+ tracing,
604
+ payload: {
605
+ type: "HANDSHAKE_REQ",
606
+ protocolVersion: currentProtocolVersion,
607
+ sessionId,
608
+ expectedSessionState,
609
+ metadata
610
+ }
611
+ };
612
+ }
613
+ function handshakeResponseMessage({
614
+ from,
615
+ to,
616
+ status
617
+ }) {
618
+ return {
619
+ id: generateId(),
620
+ from,
621
+ to,
622
+ seq: 0,
623
+ ack: 0,
624
+ streamId: generateId(),
625
+ controlFlags: 0,
626
+ payload: {
627
+ type: "HANDSHAKE_RESP",
628
+ status
629
+ }
630
+ };
631
+ }
632
+ function isAck(controlFlag) {
633
+ return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
634
+ }
635
+
642
636
  // transport/stringifyError.ts
643
637
  function coerceErrorString(err) {
644
638
  if (err instanceof Error) {
@@ -648,7 +642,7 @@ function coerceErrorString(err) {
648
642
  }
649
643
 
650
644
  // package.json
651
- var version = "0.207.2";
645
+ var version = "0.207.3";
652
646
 
653
647
  // tracing/index.ts
654
648
  function getPropagationContext(ctx) {
@@ -720,18 +714,18 @@ var SessionWaitingForHandshake = class extends CommonSession {
720
714
  };
721
715
  }
722
716
  onHandshakeData = (msg) => {
723
- const parsedMsg = this.parseMsg(msg);
724
- if (parsedMsg === null) {
717
+ const parsedMsgRes = this.codec.fromBuffer(msg);
718
+ if (!parsedMsgRes.ok) {
725
719
  this.listeners.onInvalidHandshake(
726
- "could not parse message",
720
+ `could not parse handshake message: ${parsedMsgRes.reason}`,
727
721
  "MALFORMED_HANDSHAKE"
728
722
  );
729
723
  return;
730
724
  }
731
- this.listeners.onHandshake(parsedMsg);
725
+ this.listeners.onHandshake(parsedMsgRes.value);
732
726
  };
733
727
  sendHandshake(msg) {
734
- return this.conn.send(this.options.codec.toBuffer(msg));
728
+ return sendMessage(this.conn, this.codec, msg);
735
729
  }
736
730
  _handleStateExit() {
737
731
  this.conn.removeDataListener(this.onHandshakeData);
@@ -769,18 +763,18 @@ var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
769
763
  };
770
764
  }
771
765
  onHandshakeData = (msg) => {
772
- const parsedMsg = this.parseMsg(msg);
773
- if (parsedMsg === null) {
766
+ const parsedMsgRes = this.codec.fromBuffer(msg);
767
+ if (!parsedMsgRes.ok) {
774
768
  this.listeners.onInvalidHandshake(
775
- "could not parse message",
769
+ `could not parse handshake message: ${parsedMsgRes.reason}`,
776
770
  "MALFORMED_HANDSHAKE"
777
771
  );
778
772
  return;
779
773
  }
780
- this.listeners.onHandshake(parsedMsg);
774
+ this.listeners.onHandshake(parsedMsgRes.value);
781
775
  };
782
776
  sendHandshake(msg) {
783
- return this.conn.send(this.options.codec.toBuffer(msg));
777
+ return sendMessage(this.conn, this.codec, msg);
784
778
  }
785
779
  _handleStateExit() {
786
780
  super._handleStateExit();
@@ -805,25 +799,15 @@ var SessionConnected = class extends IdentifiedSession {
805
799
  conn;
806
800
  listeners;
807
801
  heartbeatHandle;
808
- heartbeatMisses = 0;
809
- isActivelyHeartbeating;
810
- lastConstructedMsgs = [];
811
- pushLastConstructedMsgs = (msg) => {
812
- const trackedMsg = {
813
- id: msg.id,
814
- seq: msg.seq,
815
- streamId: msg.streamId,
816
- stack: new Error().stack
817
- };
818
- this.lastConstructedMsgs.push(trackedMsg);
819
- if (this.lastConstructedMsgs.length > 10) {
820
- this.lastConstructedMsgs.shift();
821
- }
822
- };
802
+ heartbeatMissTimeout;
803
+ isActivelyHeartbeating = false;
823
804
  updateBookkeeping(ack, seq) {
824
805
  this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
825
806
  this.ack = seq + 1;
826
- this.heartbeatMisses = 0;
807
+ if (this.heartbeatMissTimeout) {
808
+ clearTimeout(this.heartbeatMissTimeout);
809
+ }
810
+ this.startMissingHeartbeatTimeout();
827
811
  }
828
812
  assertSendOrdering(constructedMsg) {
829
813
  if (constructedMsg.seq > this.seqSent + 1) {
@@ -831,22 +815,22 @@ var SessionConnected = class extends IdentifiedSession {
831
815
  this.log?.error(msg, {
832
816
  ...this.loggingMetadata,
833
817
  transportMessage: constructedMsg,
834
- tags: ["invariant-violation"],
835
- extras: {
836
- lastConstructedMsgs: this.lastConstructedMsgs
837
- }
818
+ tags: ["invariant-violation"]
838
819
  });
839
820
  throw new Error(msg);
840
821
  }
841
822
  }
842
823
  send(msg) {
843
824
  const constructedMsg = this.constructMsg(msg);
844
- this.pushLastConstructedMsgs(constructedMsg);
845
825
  this.assertSendOrdering(constructedMsg);
846
826
  this.sendBuffer.push(constructedMsg);
847
- this.conn.send(this.options.codec.toBuffer(constructedMsg));
827
+ const res = sendMessage(this.conn, this.codec, constructedMsg);
828
+ if (!res.ok) {
829
+ this.listeners.onMessageSendFailure(constructedMsg, res.reason);
830
+ return res;
831
+ }
848
832
  this.seqSent = constructedMsg.seq;
849
- return constructedMsg.id;
833
+ return res;
850
834
  }
851
835
  constructor(props) {
852
836
  super(props);
@@ -855,6 +839,8 @@ var SessionConnected = class extends IdentifiedSession {
855
839
  this.conn.addDataListener(this.onMessageData);
856
840
  this.conn.addCloseListener(this.listeners.onConnectionClosed);
857
841
  this.conn.addErrorListener(this.listeners.onConnectionErrored);
842
+ }
843
+ sendBufferedMessages() {
858
844
  if (this.sendBuffer.length > 0) {
859
845
  this.log?.info(
860
846
  `sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
@@ -862,30 +848,15 @@ var SessionConnected = class extends IdentifiedSession {
862
848
  );
863
849
  for (const msg of this.sendBuffer) {
864
850
  this.assertSendOrdering(msg);
865
- this.conn.send(this.options.codec.toBuffer(msg));
851
+ const res = sendMessage(this.conn, this.codec, msg);
852
+ if (!res.ok) {
853
+ this.listeners.onMessageSendFailure(msg, res.reason);
854
+ return res;
855
+ }
866
856
  this.seqSent = msg.seq;
867
857
  }
868
858
  }
869
- this.isActivelyHeartbeating = false;
870
- this.heartbeatHandle = setInterval(() => {
871
- const misses = this.heartbeatMisses;
872
- const missDuration = misses * this.options.heartbeatIntervalMs;
873
- if (misses >= this.options.heartbeatsUntilDead) {
874
- this.log?.info(
875
- `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
876
- this.loggingMetadata
877
- );
878
- this.telemetry.span.addEvent("closing connection due to inactivity");
879
- this.conn.close();
880
- clearInterval(this.heartbeatHandle);
881
- this.heartbeatHandle = void 0;
882
- return;
883
- }
884
- if (this.isActivelyHeartbeating) {
885
- this.sendHeartbeat();
886
- }
887
- this.heartbeatMisses++;
888
- }, this.options.heartbeatIntervalMs);
859
+ return { ok: true, value: void 0 };
889
860
  }
890
861
  get loggingMetadata() {
891
862
  return {
@@ -893,25 +864,46 @@ var SessionConnected = class extends IdentifiedSession {
893
864
  ...this.conn.loggingMetadata
894
865
  };
895
866
  }
867
+ startMissingHeartbeatTimeout() {
868
+ const maxMisses = this.options.heartbeatsUntilDead;
869
+ const missDuration = maxMisses * this.options.heartbeatIntervalMs;
870
+ this.heartbeatMissTimeout = setTimeout(() => {
871
+ this.log?.info(
872
+ `closing connection to ${this.to} due to inactivity (missed ${maxMisses} heartbeats which is ${missDuration}ms)`,
873
+ this.loggingMetadata
874
+ );
875
+ this.telemetry.span.addEvent(
876
+ "closing connection due to missing heartbeat"
877
+ );
878
+ this.conn.close();
879
+ }, missDuration);
880
+ }
896
881
  startActiveHeartbeat() {
897
882
  this.isActivelyHeartbeating = true;
883
+ this.heartbeatHandle = setInterval(() => {
884
+ this.sendHeartbeat();
885
+ }, this.options.heartbeatIntervalMs);
898
886
  }
899
887
  sendHeartbeat() {
900
888
  this.log?.debug("sending heartbeat", this.loggingMetadata);
901
- this.send({
889
+ const heartbeat = {
902
890
  streamId: "heartbeat",
903
891
  controlFlags: 1 /* AckBit */,
904
892
  payload: {
905
893
  type: "ACK"
906
894
  }
907
- });
895
+ };
896
+ this.send(heartbeat);
908
897
  }
909
898
  onMessageData = (msg) => {
910
- const parsedMsg = this.parseMsg(msg);
911
- if (parsedMsg === null) {
912
- this.listeners.onInvalidMessage("could not parse message");
899
+ const parsedMsgRes = this.codec.fromBuffer(msg);
900
+ if (!parsedMsgRes.ok) {
901
+ this.listeners.onInvalidMessage(
902
+ `could not parse message: ${parsedMsgRes.reason}`
903
+ );
913
904
  return;
914
905
  }
906
+ const parsedMsg = parsedMsgRes.value;
915
907
  if (parsedMsg.seq !== this.ack) {
916
908
  if (parsedMsg.seq < this.ack) {
917
909
  this.log?.debug(
@@ -950,9 +942,7 @@ var SessionConnected = class extends IdentifiedSession {
950
942
  transportMessage: parsedMsg
951
943
  });
952
944
  if (!this.isActivelyHeartbeating) {
953
- void Promise.resolve().then(() => {
954
- this.sendHeartbeat();
955
- });
945
+ this.sendHeartbeat();
956
946
  }
957
947
  };
958
948
  _handleStateExit() {
@@ -964,6 +954,10 @@ var SessionConnected = class extends IdentifiedSession {
964
954
  clearInterval(this.heartbeatHandle);
965
955
  this.heartbeatHandle = void 0;
966
956
  }
957
+ if (this.heartbeatMissTimeout) {
958
+ clearTimeout(this.heartbeatMissTimeout);
959
+ this.heartbeatMissTimeout = void 0;
960
+ }
967
961
  }
968
962
  _handleClose() {
969
963
  super._handleClose();
@@ -995,6 +989,47 @@ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
995
989
  }
996
990
  };
997
991
 
992
+ // codec/adapter.ts
993
+ var import_value = require("@sinclair/typebox/value");
994
+ var CodecMessageAdapter = class {
995
+ constructor(codec) {
996
+ this.codec = codec;
997
+ }
998
+ toBuffer(msg) {
999
+ try {
1000
+ return {
1001
+ ok: true,
1002
+ value: this.codec.toBuffer(msg)
1003
+ };
1004
+ } catch (e) {
1005
+ return {
1006
+ ok: false,
1007
+ reason: coerceErrorString(e)
1008
+ };
1009
+ }
1010
+ }
1011
+ fromBuffer(buf) {
1012
+ try {
1013
+ const parsedMsg = this.codec.fromBuffer(buf);
1014
+ if (!import_value.Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
1015
+ return {
1016
+ ok: false,
1017
+ reason: "transport message schema mismatch"
1018
+ };
1019
+ }
1020
+ return {
1021
+ ok: true,
1022
+ value: parsedMsg
1023
+ };
1024
+ } catch (e) {
1025
+ return {
1026
+ ok: false,
1027
+ reason: coerceErrorString(e)
1028
+ };
1029
+ }
1030
+ }
1031
+ };
1032
+
998
1033
  // transport/sessionStateMachine/transitions.ts
999
1034
  function inheritSharedSession(session) {
1000
1035
  return {
@@ -1009,7 +1044,8 @@ function inheritSharedSession(session) {
1009
1044
  options: session.options,
1010
1045
  log: session.log,
1011
1046
  tracer: session.tracer,
1012
- protocolVersion: session.protocolVersion
1047
+ protocolVersion: session.protocolVersion,
1048
+ codec: session.codec
1013
1049
  };
1014
1050
  }
1015
1051
  function inheritSharedSessionWithGrace(session) {
@@ -1038,7 +1074,8 @@ var SessionStateGraph = {
1038
1074
  options,
1039
1075
  protocolVersion,
1040
1076
  tracer,
1041
- log
1077
+ log,
1078
+ codec: new CodecMessageAdapter(options.codec)
1042
1079
  });
1043
1080
  session.log?.info(`session ${session.id} created in NoConnection state`, {
1044
1081
  ...session.loggingMetadata,
@@ -1053,7 +1090,8 @@ var SessionStateGraph = {
1053
1090
  from,
1054
1091
  options,
1055
1092
  tracer,
1056
- log
1093
+ log,
1094
+ codec: new CodecMessageAdapter(options.codec)
1057
1095
  });
1058
1096
  session.log?.info(`session created in WaitingForHandshake state`, {
1059
1097
  ...session.loggingMetadata,
@@ -1131,6 +1169,7 @@ var SessionStateGraph = {
1131
1169
  listeners,
1132
1170
  ...carriedState
1133
1171
  });
1172
+ session.startMissingHeartbeatTimeout();
1134
1173
  session.log?.info(
1135
1174
  `session ${session.id} transition from Handshaking to Connected`,
1136
1175
  {
@@ -1166,7 +1205,8 @@ var SessionStateGraph = {
1166
1205
  options,
1167
1206
  tracer: pendingSession.tracer,
1168
1207
  log: pendingSession.log,
1169
- protocolVersion
1208
+ protocolVersion,
1209
+ codec: new CodecMessageAdapter(options.codec)
1170
1210
  }
1171
1211
  );
1172
1212
  pendingSession._handleStateExit();
@@ -1176,6 +1216,7 @@ var SessionStateGraph = {
1176
1216
  listeners,
1177
1217
  ...carriedState
1178
1218
  });
1219
+ session.startMissingHeartbeatTimeout();
1179
1220
  conn.telemetry = createConnectionTelemetryInfo(
1180
1221
  session.tracer,
1181
1222
  conn,
@@ -1516,12 +1557,16 @@ var Transport = class {
1516
1557
  );
1517
1558
  }
1518
1559
  const sameSession = session.id === sessionId;
1519
- if (!sameSession) {
1560
+ if (!sameSession || session._isConsumed) {
1520
1561
  throw new Error(
1521
1562
  `session scope for ${sessionId} has ended (transition), can't send`
1522
1563
  );
1523
1564
  }
1524
- return session.send(msg);
1565
+ const res = session.send(msg);
1566
+ if (!res.ok) {
1567
+ throw new Error(res.reason);
1568
+ }
1569
+ return res.value;
1525
1570
  };
1526
1571
  }
1527
1572
  };
@@ -1792,13 +1837,41 @@ var ClientTransport = class extends Transport {
1792
1837
  this.handleMsg(msg2);
1793
1838
  },
1794
1839
  onInvalidMessage: (reason) => {
1795
- this.deleteSession(connectedSession, { unhealthy: true });
1840
+ this.log?.error(`invalid message: ${reason}`, {
1841
+ ...connectedSession.loggingMetadata,
1842
+ transportMessage: msg
1843
+ });
1796
1844
  this.protocolError({
1797
1845
  type: ProtocolError.InvalidMessage,
1798
1846
  message: reason
1799
1847
  });
1848
+ this.deleteSession(connectedSession, { unhealthy: true });
1849
+ },
1850
+ onMessageSendFailure: (msg2, reason) => {
1851
+ this.log?.error(`failed to send message: ${reason}`, {
1852
+ ...connectedSession.loggingMetadata,
1853
+ transportMessage: msg2
1854
+ });
1855
+ this.protocolError({
1856
+ type: ProtocolError.MessageSendFailure,
1857
+ message: reason
1858
+ });
1859
+ this.deleteSession(connectedSession, { unhealthy: true });
1800
1860
  }
1801
1861
  });
1862
+ const res = connectedSession.sendBufferedMessages();
1863
+ if (!res.ok) {
1864
+ this.log?.error(`failed to send buffered messages: ${res.reason}`, {
1865
+ ...connectedSession.loggingMetadata,
1866
+ transportMessage: msg
1867
+ });
1868
+ this.protocolError({
1869
+ type: ProtocolError.MessageSendFailure,
1870
+ message: res.reason
1871
+ });
1872
+ this.deleteSession(connectedSession, { unhealthy: true });
1873
+ return;
1874
+ }
1802
1875
  this.updateSession(connectedSession);
1803
1876
  this.retryBudget.startRestoringBudget();
1804
1877
  }
@@ -1937,7 +2010,18 @@ var ClientTransport = class extends Transport {
1937
2010
  ...session.loggingMetadata,
1938
2011
  transportMessage: requestMsg
1939
2012
  });
1940
- session.sendHandshake(requestMsg);
2013
+ const res = session.sendHandshake(requestMsg);
2014
+ if (!res.ok) {
2015
+ this.log?.error(`failed to send handshake request: ${res.reason}`, {
2016
+ ...session.loggingMetadata,
2017
+ transportMessage: requestMsg
2018
+ });
2019
+ this.protocolError({
2020
+ type: ProtocolError.MessageSendFailure,
2021
+ message: res.reason
2022
+ });
2023
+ this.deleteSession(session, { unhealthy: true });
2024
+ }
1941
2025
  }
1942
2026
  close() {
1943
2027
  this.retryBudget.close();
@@ -2061,17 +2145,28 @@ var ServerTransport = class extends Transport {
2061
2145
  message: reason
2062
2146
  });
2063
2147
  this.log?.warn(reason, metadata);
2064
- session.sendHandshake(
2065
- handshakeResponseMessage({
2066
- from: this.clientId,
2067
- to,
2068
- status: {
2069
- ok: false,
2070
- code,
2071
- reason
2072
- }
2073
- })
2074
- );
2148
+ const responseMsg = handshakeResponseMessage({
2149
+ from: this.clientId,
2150
+ to,
2151
+ status: {
2152
+ ok: false,
2153
+ code,
2154
+ reason
2155
+ }
2156
+ });
2157
+ const res = session.sendHandshake(responseMsg);
2158
+ if (!res.ok) {
2159
+ this.log?.error(`failed to send handshake response: ${res.reason}`, {
2160
+ ...session.loggingMetadata,
2161
+ transportMessage: responseMsg
2162
+ });
2163
+ this.protocolError({
2164
+ type: ProtocolError.MessageSendFailure,
2165
+ message: res.reason
2166
+ });
2167
+ this.deletePendingSession(session);
2168
+ return;
2169
+ }
2075
2170
  this.protocolError({
2076
2171
  type: ProtocolError.HandshakeFailed,
2077
2172
  code,
@@ -2255,7 +2350,20 @@ var ServerTransport = class extends Transport {
2255
2350
  sessionId
2256
2351
  }
2257
2352
  });
2258
- session.sendHandshake(responseMsg);
2353
+ const res = session.sendHandshake(responseMsg);
2354
+ if (!res.ok) {
2355
+ this.log?.error(`failed to send handshake response: ${res.reason}`, {
2356
+ ...session.loggingMetadata,
2357
+ transportMessage: responseMsg
2358
+ });
2359
+ this.protocolError({
2360
+ type: ProtocolError.MessageSendFailure,
2361
+ message: res.reason
2362
+ });
2363
+ this.deletePendingSession(session);
2364
+ return;
2365
+ }
2366
+ this.pendingSessions.delete(session);
2259
2367
  const connectedSession = ServerSessionStateGraph.transition.WaitingForHandshakeToConnected(
2260
2368
  session,
2261
2369
  // by this point oldSession is either no connection or we dont have an old session
@@ -2282,22 +2390,52 @@ var ServerTransport = class extends Transport {
2282
2390
  this.handleMsg(msg2);
2283
2391
  },
2284
2392
  onInvalidMessage: (reason) => {
2393
+ this.log?.error(`invalid message: ${reason}`, {
2394
+ ...connectedSession.loggingMetadata,
2395
+ transportMessage: msg
2396
+ });
2285
2397
  this.protocolError({
2286
2398
  type: ProtocolError.InvalidMessage,
2287
2399
  message: reason
2288
2400
  });
2289
2401
  this.deleteSession(connectedSession, { unhealthy: true });
2402
+ },
2403
+ onMessageSendFailure: (msg2, reason) => {
2404
+ this.log?.error(`failed to send message: ${reason}`, {
2405
+ ...connectedSession.loggingMetadata,
2406
+ transportMessage: msg2
2407
+ });
2408
+ this.protocolError({
2409
+ type: ProtocolError.MessageSendFailure,
2410
+ message: reason
2411
+ });
2412
+ this.deleteSession(connectedSession, { unhealthy: true });
2290
2413
  }
2291
2414
  },
2292
2415
  gotVersion
2293
2416
  );
2417
+ const bufferSendRes = connectedSession.sendBufferedMessages();
2418
+ if (!bufferSendRes.ok) {
2419
+ this.log?.error(
2420
+ `failed to send buffered messages: ${bufferSendRes.reason}`,
2421
+ {
2422
+ ...connectedSession.loggingMetadata,
2423
+ transportMessage: msg
2424
+ }
2425
+ );
2426
+ this.protocolError({
2427
+ type: ProtocolError.MessageSendFailure,
2428
+ message: bufferSendRes.reason
2429
+ });
2430
+ this.deleteSession(connectedSession, { unhealthy: true });
2431
+ return;
2432
+ }
2294
2433
  this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);
2295
2434
  if (oldSession) {
2296
2435
  this.updateSession(connectedSession);
2297
2436
  } else {
2298
2437
  this.createSession(connectedSession);
2299
2438
  }
2300
- this.pendingSessions.delete(session);
2301
2439
  connectedSession.startActiveHeartbeat();
2302
2440
  }
2303
2441
  };