@replit/river 0.207.1 → 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-7LMZNSVC.js → chunk-B7REV3ZV.js} +6 -5
  3. package/dist/{chunk-7LMZNSVC.js.map → chunk-B7REV3ZV.js.map} +1 -1
  4. package/dist/{chunk-QMAVXV4Z.js → chunk-BO7MFCO6.js} +1136 -132
  5. package/dist/chunk-BO7MFCO6.js.map +1 -0
  6. package/dist/{chunk-BCCZA7SX.js → chunk-QGPYCXV4.js} +2 -2
  7. package/dist/{chunk-BCCZA7SX.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-933c87b2.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-4cd29829.d.ts → services-87887bc5.d.ts} +16 -11
  25. package/dist/testUtil/index.cjs +992 -829
  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 -193
  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 -117
  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 -259
  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-AJGIY2UB.js +0 -56
  50. package/dist/chunk-AJGIY2UB.js.map +0 -1
  51. package/dist/chunk-CRD3HDVN.js +0 -438
  52. package/dist/chunk-CRD3HDVN.js.map +0 -1
  53. package/dist/chunk-I27WBSMZ.js +0 -377
  54. package/dist/chunk-I27WBSMZ.js.map +0 -1
  55. package/dist/chunk-QMAVXV4Z.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.1";
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,12 +799,15 @@ var SessionConnected = class extends IdentifiedSession {
805
799
  conn;
806
800
  listeners;
807
801
  heartbeatHandle;
808
- heartbeatMisses = 0;
809
- isActivelyHeartbeating;
802
+ heartbeatMissTimeout;
803
+ isActivelyHeartbeating = false;
810
804
  updateBookkeeping(ack, seq) {
811
805
  this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
812
806
  this.ack = seq + 1;
813
- this.heartbeatMisses = 0;
807
+ if (this.heartbeatMissTimeout) {
808
+ clearTimeout(this.heartbeatMissTimeout);
809
+ }
810
+ this.startMissingHeartbeatTimeout();
814
811
  }
815
812
  assertSendOrdering(constructedMsg) {
816
813
  if (constructedMsg.seq > this.seqSent + 1) {
@@ -827,9 +824,13 @@ var SessionConnected = class extends IdentifiedSession {
827
824
  const constructedMsg = this.constructMsg(msg);
828
825
  this.assertSendOrdering(constructedMsg);
829
826
  this.sendBuffer.push(constructedMsg);
830
- 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
+ }
831
832
  this.seqSent = constructedMsg.seq;
832
- return constructedMsg.id;
833
+ return res;
833
834
  }
834
835
  constructor(props) {
835
836
  super(props);
@@ -838,6 +839,8 @@ var SessionConnected = class extends IdentifiedSession {
838
839
  this.conn.addDataListener(this.onMessageData);
839
840
  this.conn.addCloseListener(this.listeners.onConnectionClosed);
840
841
  this.conn.addErrorListener(this.listeners.onConnectionErrored);
842
+ }
843
+ sendBufferedMessages() {
841
844
  if (this.sendBuffer.length > 0) {
842
845
  this.log?.info(
843
846
  `sending ${this.sendBuffer.length} buffered messages, starting at seq ${this.nextSeq()}`,
@@ -845,30 +848,15 @@ var SessionConnected = class extends IdentifiedSession {
845
848
  );
846
849
  for (const msg of this.sendBuffer) {
847
850
  this.assertSendOrdering(msg);
848
- 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
+ }
849
856
  this.seqSent = msg.seq;
850
857
  }
851
858
  }
852
- this.isActivelyHeartbeating = false;
853
- this.heartbeatHandle = setInterval(() => {
854
- const misses = this.heartbeatMisses;
855
- const missDuration = misses * this.options.heartbeatIntervalMs;
856
- if (misses >= this.options.heartbeatsUntilDead) {
857
- this.log?.info(
858
- `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
859
- this.loggingMetadata
860
- );
861
- this.telemetry.span.addEvent("closing connection due to inactivity");
862
- this.conn.close();
863
- clearInterval(this.heartbeatHandle);
864
- this.heartbeatHandle = void 0;
865
- return;
866
- }
867
- if (this.isActivelyHeartbeating) {
868
- this.sendHeartbeat();
869
- }
870
- this.heartbeatMisses++;
871
- }, this.options.heartbeatIntervalMs);
859
+ return { ok: true, value: void 0 };
872
860
  }
873
861
  get loggingMetadata() {
874
862
  return {
@@ -876,31 +864,46 @@ var SessionConnected = class extends IdentifiedSession {
876
864
  ...this.conn.loggingMetadata
877
865
  };
878
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
+ }
879
881
  startActiveHeartbeat() {
880
882
  this.isActivelyHeartbeating = true;
883
+ this.heartbeatHandle = setInterval(() => {
884
+ this.sendHeartbeat();
885
+ }, this.options.heartbeatIntervalMs);
881
886
  }
882
887
  sendHeartbeat() {
883
888
  this.log?.debug("sending heartbeat", this.loggingMetadata);
884
- this.send({
889
+ const heartbeat = {
885
890
  streamId: "heartbeat",
886
891
  controlFlags: 1 /* AckBit */,
887
892
  payload: {
888
893
  type: "ACK"
889
894
  }
890
- });
891
- }
892
- closeConnection() {
893
- this.conn.removeDataListener(this.onMessageData);
894
- this.conn.removeCloseListener(this.listeners.onConnectionClosed);
895
- this.conn.removeErrorListener(this.listeners.onConnectionErrored);
896
- this.conn.close();
895
+ };
896
+ this.send(heartbeat);
897
897
  }
898
898
  onMessageData = (msg) => {
899
- const parsedMsg = this.parseMsg(msg);
900
- if (parsedMsg === null) {
901
- 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
+ );
902
904
  return;
903
905
  }
906
+ const parsedMsg = parsedMsgRes.value;
904
907
  if (parsedMsg.seq !== this.ack) {
905
908
  if (parsedMsg.seq < this.ack) {
906
909
  this.log?.debug(
@@ -921,7 +924,7 @@ var SessionConnected = class extends IdentifiedSession {
921
924
  code: import_api3.SpanStatusCode.ERROR,
922
925
  message: reason
923
926
  });
924
- this.closeConnection();
927
+ this.conn.close();
925
928
  }
926
929
  return;
927
930
  }
@@ -939,9 +942,7 @@ var SessionConnected = class extends IdentifiedSession {
939
942
  transportMessage: parsedMsg
940
943
  });
941
944
  if (!this.isActivelyHeartbeating) {
942
- void Promise.resolve().then(() => {
943
- this.sendHeartbeat();
944
- });
945
+ this.sendHeartbeat();
945
946
  }
946
947
  };
947
948
  _handleStateExit() {
@@ -953,6 +954,10 @@ var SessionConnected = class extends IdentifiedSession {
953
954
  clearInterval(this.heartbeatHandle);
954
955
  this.heartbeatHandle = void 0;
955
956
  }
957
+ if (this.heartbeatMissTimeout) {
958
+ clearTimeout(this.heartbeatMissTimeout);
959
+ this.heartbeatMissTimeout = void 0;
960
+ }
956
961
  }
957
962
  _handleClose() {
958
963
  super._handleClose();
@@ -984,6 +989,47 @@ var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
984
989
  }
985
990
  };
986
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
+
987
1033
  // transport/sessionStateMachine/transitions.ts
988
1034
  function inheritSharedSession(session) {
989
1035
  return {
@@ -998,7 +1044,8 @@ function inheritSharedSession(session) {
998
1044
  options: session.options,
999
1045
  log: session.log,
1000
1046
  tracer: session.tracer,
1001
- protocolVersion: session.protocolVersion
1047
+ protocolVersion: session.protocolVersion,
1048
+ codec: session.codec
1002
1049
  };
1003
1050
  }
1004
1051
  function inheritSharedSessionWithGrace(session) {
@@ -1027,7 +1074,8 @@ var SessionStateGraph = {
1027
1074
  options,
1028
1075
  protocolVersion,
1029
1076
  tracer,
1030
- log
1077
+ log,
1078
+ codec: new CodecMessageAdapter(options.codec)
1031
1079
  });
1032
1080
  session.log?.info(`session ${session.id} created in NoConnection state`, {
1033
1081
  ...session.loggingMetadata,
@@ -1042,7 +1090,8 @@ var SessionStateGraph = {
1042
1090
  from,
1043
1091
  options,
1044
1092
  tracer,
1045
- log
1093
+ log,
1094
+ codec: new CodecMessageAdapter(options.codec)
1046
1095
  });
1047
1096
  session.log?.info(`session created in WaitingForHandshake state`, {
1048
1097
  ...session.loggingMetadata,
@@ -1120,6 +1169,7 @@ var SessionStateGraph = {
1120
1169
  listeners,
1121
1170
  ...carriedState
1122
1171
  });
1172
+ session.startMissingHeartbeatTimeout();
1123
1173
  session.log?.info(
1124
1174
  `session ${session.id} transition from Handshaking to Connected`,
1125
1175
  {
@@ -1155,7 +1205,8 @@ var SessionStateGraph = {
1155
1205
  options,
1156
1206
  tracer: pendingSession.tracer,
1157
1207
  log: pendingSession.log,
1158
- protocolVersion
1208
+ protocolVersion,
1209
+ codec: new CodecMessageAdapter(options.codec)
1159
1210
  }
1160
1211
  );
1161
1212
  pendingSession._handleStateExit();
@@ -1165,6 +1216,7 @@ var SessionStateGraph = {
1165
1216
  listeners,
1166
1217
  ...carriedState
1167
1218
  });
1219
+ session.startMissingHeartbeatTimeout();
1168
1220
  conn.telemetry = createConnectionTelemetryInfo(
1169
1221
  session.tracer,
1170
1222
  conn,
@@ -1505,12 +1557,16 @@ var Transport = class {
1505
1557
  );
1506
1558
  }
1507
1559
  const sameSession = session.id === sessionId;
1508
- if (!sameSession) {
1560
+ if (!sameSession || session._isConsumed) {
1509
1561
  throw new Error(
1510
1562
  `session scope for ${sessionId} has ended (transition), can't send`
1511
1563
  );
1512
1564
  }
1513
- 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;
1514
1570
  };
1515
1571
  }
1516
1572
  };
@@ -1781,13 +1837,41 @@ var ClientTransport = class extends Transport {
1781
1837
  this.handleMsg(msg2);
1782
1838
  },
1783
1839
  onInvalidMessage: (reason) => {
1784
- this.deleteSession(connectedSession, { unhealthy: true });
1840
+ this.log?.error(`invalid message: ${reason}`, {
1841
+ ...connectedSession.loggingMetadata,
1842
+ transportMessage: msg
1843
+ });
1785
1844
  this.protocolError({
1786
1845
  type: ProtocolError.InvalidMessage,
1787
1846
  message: reason
1788
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 });
1789
1860
  }
1790
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
+ }
1791
1875
  this.updateSession(connectedSession);
1792
1876
  this.retryBudget.startRestoringBudget();
1793
1877
  }
@@ -1926,7 +2010,18 @@ var ClientTransport = class extends Transport {
1926
2010
  ...session.loggingMetadata,
1927
2011
  transportMessage: requestMsg
1928
2012
  });
1929
- 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
+ }
1930
2025
  }
1931
2026
  close() {
1932
2027
  this.retryBudget.close();
@@ -2050,17 +2145,28 @@ var ServerTransport = class extends Transport {
2050
2145
  message: reason
2051
2146
  });
2052
2147
  this.log?.warn(reason, metadata);
2053
- session.sendHandshake(
2054
- handshakeResponseMessage({
2055
- from: this.clientId,
2056
- to,
2057
- status: {
2058
- ok: false,
2059
- code,
2060
- reason
2061
- }
2062
- })
2063
- );
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
+ }
2064
2170
  this.protocolError({
2065
2171
  type: ProtocolError.HandshakeFailed,
2066
2172
  code,
@@ -2244,7 +2350,20 @@ var ServerTransport = class extends Transport {
2244
2350
  sessionId
2245
2351
  }
2246
2352
  });
2247
- 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);
2248
2367
  const connectedSession = ServerSessionStateGraph.transition.WaitingForHandshakeToConnected(
2249
2368
  session,
2250
2369
  // by this point oldSession is either no connection or we dont have an old session
@@ -2271,22 +2390,52 @@ var ServerTransport = class extends Transport {
2271
2390
  this.handleMsg(msg2);
2272
2391
  },
2273
2392
  onInvalidMessage: (reason) => {
2393
+ this.log?.error(`invalid message: ${reason}`, {
2394
+ ...connectedSession.loggingMetadata,
2395
+ transportMessage: msg
2396
+ });
2274
2397
  this.protocolError({
2275
2398
  type: ProtocolError.InvalidMessage,
2276
2399
  message: reason
2277
2400
  });
2278
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 });
2279
2413
  }
2280
2414
  },
2281
2415
  gotVersion
2282
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
+ }
2283
2433
  this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);
2284
2434
  if (oldSession) {
2285
2435
  this.updateSession(connectedSession);
2286
2436
  } else {
2287
2437
  this.createSession(connectedSession);
2288
2438
  }
2289
- this.pendingSessions.delete(session);
2290
2439
  connectedSession.startActiveHeartbeat();
2291
2440
  }
2292
2441
  };