@rivetkit/engine-runner 2.0.33 → 2.0.34-rc.1

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.
package/dist/mod.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } var _class; var _class2;// src/mod.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } var _class;// src/mod.ts
2
2
  var _enginerunnerprotocol = require('@rivetkit/engine-runner-protocol'); var protocol = _interopRequireWildcard(_enginerunnerprotocol);
3
3
 
4
4
  // src/log.ts
@@ -502,9 +502,10 @@ function stringifyKvResponseData(data) {
502
502
  }
503
503
 
504
504
  // src/websocket-tunnel-adapter.ts
505
+ var _virtualwebsocket = require('@rivetkit/virtual-websocket');
505
506
  var HIBERNATABLE_SYMBOL = Symbol("hibernatable");
506
- var WebSocketTunnelAdapter = (_class2 = class {
507
- constructor(tunnel, actorId, requestId, serverMessageIndex, hibernatable, isRestoringHibernatable, request, sendCallback, closeCallback) {;_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);
507
+ var WebSocketTunnelAdapter = class {
508
+ constructor(tunnel, actorId, requestId, serverMessageIndex, hibernatable, isRestoringHibernatable, request, sendCallback, closeCallback) {
508
509
  this.request = request;
509
510
  var _a;
510
511
  this.#tunnel = tunnel;
@@ -514,69 +515,65 @@ var WebSocketTunnelAdapter = (_class2 = class {
514
515
  this.#serverMessageIndex = serverMessageIndex;
515
516
  this.#sendCallback = sendCallback;
516
517
  this.#closeCallback = closeCallback;
518
+ this.#ws = new (0, _virtualwebsocket.VirtualWebSocket)({
519
+ getReadyState: () => this.#readyState,
520
+ onSend: (data) => this.#handleSend(data),
521
+ onClose: (code, reason) => this.#close(code, reason, true),
522
+ onTerminate: () => this.#terminate()
523
+ });
517
524
  if (isRestoringHibernatable) {
518
525
  (_a = this.#log) == null ? void 0 : _a.debug({
519
526
  msg: "setting WebSocket to OPEN state for restored connection",
520
527
  actorId: this.#actorId,
521
- requestId: this.#requestId,
522
- hibernatable: this.#hibernatable
528
+ requestId: this.#requestId
523
529
  });
524
530
  this.#readyState = 1;
525
531
  }
526
532
  }
527
- // MARK: - WebSocket Compat Variables
528
533
  #readyState = 0;
529
- // CONNECTING
530
- #eventListeners = /* @__PURE__ */ new Map();
531
- #onopen = null;
532
- #onclose = null;
533
- #onerror = null;
534
- #onmessage = null;
535
- #bufferedAmount = 0;
536
534
  #binaryType = "nodebuffer";
537
- #extensions = "";
538
- #protocol = "";
539
- #url = "";
540
- // mARK: - Internal State
535
+ #ws;
541
536
  #tunnel;
542
537
  #actorId;
543
538
  #requestId;
544
539
  #hibernatable;
545
540
  #serverMessageIndex;
541
+ #sendCallback;
542
+ #closeCallback;
546
543
  get [HIBERNATABLE_SYMBOL]() {
547
544
  return this.#hibernatable;
548
545
  }
549
- /**
550
- * Called when sending a message from this WebSocket.
551
- *
552
- * Used to send a tunnel message from Tunnel.
553
- */
554
- #sendCallback;
555
- /**
556
- * Called when closing this WebSocket.
557
- *
558
- * Used to send a tunnel message from Tunnel
559
- */
560
- #closeCallback;
561
546
  get #log() {
562
547
  return this.#tunnel.log;
563
548
  }
564
- // MARK: - Lifecycle
565
- get bufferedAmount() {
566
- return this.#bufferedAmount;
549
+ get websocket() {
550
+ return this.#ws;
567
551
  }
568
- _handleOpen(requestId) {
569
- if (this.#readyState !== 0) {
570
- return;
552
+ #handleSend(data) {
553
+ let isBinary = false;
554
+ let messageData;
555
+ if (typeof data === "string") {
556
+ messageData = data;
557
+ } else if (data instanceof ArrayBuffer) {
558
+ isBinary = true;
559
+ messageData = data;
560
+ } else if (ArrayBuffer.isView(data)) {
561
+ isBinary = true;
562
+ const view = data;
563
+ const buffer = view.buffer instanceof SharedArrayBuffer ? new Uint8Array(view.buffer, view.byteOffset, view.byteLength).slice().buffer : view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
564
+ messageData = buffer;
565
+ } else {
566
+ throw new Error("Unsupported data type");
571
567
  }
568
+ this.#sendCallback(messageData, isBinary);
569
+ }
570
+ // Called by Tunnel when WebSocket is opened
571
+ _handleOpen(requestId) {
572
+ if (this.#readyState !== 0) return;
572
573
  this.#readyState = 1;
573
- const event = {
574
- type: "open",
575
- rivetRequestId: requestId,
576
- target: this
577
- };
578
- this.#fireEvent("open", event);
574
+ this.#ws.dispatchEvent({ type: "open", rivetRequestId: requestId, target: this.#ws });
579
575
  }
576
+ // Called by Tunnel when message is received
580
577
  _handleMessage(requestId, data, serverMessageIndex, isBinary) {
581
578
  var _a, _b, _c;
582
579
  if (this.#readyState !== 1) {
@@ -584,10 +581,7 @@ var WebSocketTunnelAdapter = (_class2 = class {
584
581
  msg: "WebSocket message ignored - not in OPEN state",
585
582
  requestId: this.#requestId,
586
583
  actorId: this.#actorId,
587
- currentReadyState: this.#readyState,
588
- expectedReadyState: 1,
589
- serverMessageIndex,
590
- hibernatable: this.#hibernatable
584
+ currentReadyState: this.#readyState
591
585
  });
592
586
  return true;
593
587
  }
@@ -595,11 +589,10 @@ var WebSocketTunnelAdapter = (_class2 = class {
595
589
  const previousIndex = this.#serverMessageIndex;
596
590
  if (wrappingLteU16(serverMessageIndex, previousIndex)) {
597
591
  (_b = this.#log) == null ? void 0 : _b.info({
598
- msg: "received duplicate hibernating websocket message, this indicates the actor failed to ack the message index before restarting",
592
+ msg: "received duplicate hibernating websocket message",
599
593
  requestId,
600
594
  actorId: this.#actorId,
601
595
  previousIndex,
602
- expectedIndex: wrappingAddU16(previousIndex, 1),
603
596
  receivedIndex: serverMessageIndex
604
597
  });
605
598
  return true;
@@ -615,307 +608,55 @@ var WebSocketTunnelAdapter = (_class2 = class {
615
608
  expectedIndex,
616
609
  receivedIndex: serverMessageIndex,
617
610
  closeReason,
618
- gap: wrappingSubU16(
619
- wrappingSubU16(serverMessageIndex, previousIndex),
620
- 1
621
- )
611
+ gap: wrappingSubU16(wrappingSubU16(serverMessageIndex, previousIndex), 1)
622
612
  });
623
- this.close(1008, closeReason);
613
+ this.#close(1008, closeReason, true);
624
614
  return true;
625
615
  }
626
616
  this.#serverMessageIndex = serverMessageIndex;
627
617
  }
628
- let messageData;
629
- if (isBinary) {
618
+ let messageData = data;
619
+ if (isBinary && data instanceof Uint8Array) {
630
620
  if (this.#binaryType === "nodebuffer") {
631
621
  messageData = Buffer.from(data);
632
622
  } else if (this.#binaryType === "arraybuffer") {
633
- if (data instanceof Uint8Array) {
634
- messageData = data.buffer.slice(
635
- data.byteOffset,
636
- data.byteOffset + data.byteLength
637
- );
638
- } else {
639
- messageData = data;
640
- }
641
- } else {
642
- throw new Error(
643
- "Blob binaryType not supported in tunnel adapter"
644
- );
623
+ messageData = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
645
624
  }
646
- } else {
647
- messageData = data;
648
625
  }
649
- const event = {
626
+ this.#ws.dispatchEvent({
650
627
  type: "message",
651
628
  data: messageData,
652
629
  rivetRequestId: requestId,
653
630
  rivetMessageIndex: serverMessageIndex,
654
- target: this
655
- };
656
- this.#fireEvent("message", event);
631
+ target: this.#ws
632
+ });
657
633
  return false;
658
634
  }
635
+ // Called by Tunnel when close is received
659
636
  _handleClose(_requestId, code, reason) {
660
- this.#closeInner(code, reason, true);
661
- }
662
- _handleError(error) {
663
- const event = {
664
- type: "error",
665
- target: this,
666
- error
667
- };
668
- this.#fireEvent("error", event);
637
+ this.#close(code, reason, true);
669
638
  }
639
+ // Close without sending close message to tunnel
670
640
  _closeWithoutCallback(code, reason) {
671
- this.#closeInner(code, reason, false);
641
+ this.#close(code, reason, false);
672
642
  }
673
- #fireEvent(type, event) {
674
- var _a, _b, _c, _d, _e;
675
- const listeners = this.#eventListeners.get(type);
676
- if (listeners && listeners.size > 0) {
677
- for (const listener of listeners) {
678
- try {
679
- listener.call(this, event);
680
- } catch (error) {
681
- (_a = logger()) == null ? void 0 : _a.error({
682
- msg: "error in websocket event listener",
683
- error,
684
- type
685
- });
686
- }
687
- }
688
- }
689
- switch (type) {
690
- case "open":
691
- if (this.#onopen) {
692
- try {
693
- this.#onopen.call(this, event);
694
- } catch (error) {
695
- (_b = logger()) == null ? void 0 : _b.error({
696
- msg: "error in onopen handler",
697
- error
698
- });
699
- }
700
- }
701
- break;
702
- case "close":
703
- if (this.#onclose) {
704
- try {
705
- this.#onclose.call(this, event);
706
- } catch (error) {
707
- (_c = logger()) == null ? void 0 : _c.error({
708
- msg: "error in onclose handler",
709
- error
710
- });
711
- }
712
- }
713
- break;
714
- case "error":
715
- if (this.#onerror) {
716
- try {
717
- this.#onerror.call(this, event);
718
- } catch (error) {
719
- (_d = logger()) == null ? void 0 : _d.error({
720
- msg: "error in onerror handler",
721
- error
722
- });
723
- }
724
- }
725
- break;
726
- case "message":
727
- if (this.#onmessage) {
728
- try {
729
- this.#onmessage.call(this, event);
730
- } catch (error) {
731
- (_e = logger()) == null ? void 0 : _e.error({
732
- msg: "error in onmessage handler",
733
- error
734
- });
735
- }
736
- }
737
- break;
738
- }
643
+ // Public close method (used by tunnel.ts for stale websocket cleanup)
644
+ close(code, reason) {
645
+ this.#close(code, reason, true);
739
646
  }
740
- #closeInner(code, reason, callback) {
741
- if (this.#readyState === 2 || // CLOSING
742
- this.#readyState === 3) {
743
- return;
744
- }
647
+ #close(code, reason, sendCallback) {
648
+ if (this.#readyState >= 2) return;
745
649
  this.#readyState = 2;
746
- if (callback) {
747
- this.#closeCallback(code, reason);
748
- }
650
+ if (sendCallback) this.#closeCallback(code, reason);
749
651
  this.#readyState = 3;
750
- const closeEvent = {
751
- wasClean: true,
752
- code: code || 1e3,
753
- reason: reason || "",
754
- type: "close",
755
- target: this
756
- };
757
- this.#fireEvent("close", closeEvent);
758
- }
759
- // MARK: - WebSocket Compatible API
760
- get readyState() {
761
- return this.#readyState;
652
+ this.#ws.triggerClose(_nullishCoalesce(code, () => ( 1e3)), _nullishCoalesce(reason, () => ( "")));
762
653
  }
763
- get binaryType() {
764
- return this.#binaryType;
765
- }
766
- set binaryType(value) {
767
- if (value === "nodebuffer" || value === "arraybuffer" || value === "blob") {
768
- this.#binaryType = value;
769
- }
770
- }
771
- get extensions() {
772
- return this.#extensions;
773
- }
774
- get protocol() {
775
- return this.#protocol;
776
- }
777
- get url() {
778
- return this.#url;
779
- }
780
- get onopen() {
781
- return this.#onopen;
782
- }
783
- set onopen(value) {
784
- this.#onopen = value;
785
- }
786
- get onclose() {
787
- return this.#onclose;
788
- }
789
- set onclose(value) {
790
- this.#onclose = value;
791
- }
792
- get onerror() {
793
- return this.#onerror;
794
- }
795
- set onerror(value) {
796
- this.#onerror = value;
797
- }
798
- get onmessage() {
799
- return this.#onmessage;
800
- }
801
- set onmessage(value) {
802
- this.#onmessage = value;
803
- }
804
- send(data) {
805
- if (this.#readyState === 0) {
806
- throw new DOMException(
807
- "WebSocket is still in CONNECTING state",
808
- "InvalidStateError"
809
- );
810
- }
811
- if (this.#readyState === 2 || this.#readyState === 3) {
812
- return;
813
- }
814
- let isBinary = false;
815
- let messageData;
816
- if (typeof data === "string") {
817
- messageData = data;
818
- } else if (data instanceof ArrayBuffer) {
819
- isBinary = true;
820
- messageData = data;
821
- } else if (ArrayBuffer.isView(data)) {
822
- isBinary = true;
823
- const view = data;
824
- if (view.buffer instanceof SharedArrayBuffer) {
825
- const bytes = new Uint8Array(
826
- view.buffer,
827
- view.byteOffset,
828
- view.byteLength
829
- );
830
- messageData = bytes.buffer.slice(
831
- bytes.byteOffset,
832
- bytes.byteOffset + bytes.byteLength
833
- );
834
- } else {
835
- messageData = view.buffer.slice(
836
- view.byteOffset,
837
- view.byteOffset + view.byteLength
838
- );
839
- }
840
- } else if (data instanceof Blob) {
841
- throw new Error("Blob sending not implemented in tunnel adapter");
842
- } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
843
- isBinary = true;
844
- const buf = data;
845
- if (buf.buffer instanceof SharedArrayBuffer) {
846
- const bytes = new Uint8Array(
847
- buf.buffer,
848
- buf.byteOffset,
849
- buf.byteLength
850
- );
851
- messageData = bytes.buffer.slice(
852
- bytes.byteOffset,
853
- bytes.byteOffset + bytes.byteLength
854
- );
855
- } else {
856
- messageData = buf.buffer.slice(
857
- buf.byteOffset,
858
- buf.byteOffset + buf.byteLength
859
- );
860
- }
861
- } else {
862
- throw new Error("Invalid data type");
863
- }
864
- this.#sendCallback(messageData, isBinary);
865
- }
866
- close(code, reason) {
867
- this.#closeInner(code, reason, true);
868
- }
869
- addEventListener(type, listener, options) {
870
- if (typeof listener === "function") {
871
- let listeners = this.#eventListeners.get(type);
872
- if (!listeners) {
873
- listeners = /* @__PURE__ */ new Set();
874
- this.#eventListeners.set(type, listeners);
875
- }
876
- listeners.add(listener);
877
- }
878
- }
879
- removeEventListener(type, listener, options) {
880
- if (typeof listener === "function") {
881
- const listeners = this.#eventListeners.get(type);
882
- if (listeners) {
883
- listeners.delete(listener);
884
- }
885
- }
886
- }
887
- dispatchEvent(event) {
888
- return true;
889
- }
890
- static __initStatic() {this.CONNECTING = 0}
891
- static __initStatic2() {this.OPEN = 1}
892
- static __initStatic3() {this.CLOSING = 2}
893
- static __initStatic4() {this.CLOSED = 3}
894
- __init7() {this.CONNECTING = 0}
895
- __init8() {this.OPEN = 1}
896
- __init9() {this.CLOSING = 2}
897
- __init10() {this.CLOSED = 3}
898
- // Additional methods for compatibility
899
- ping(data, mask, cb) {
900
- if (cb) cb(new Error("Ping not supported in tunnel adapter"));
901
- }
902
- pong(data, mask, cb) {
903
- if (cb) cb(new Error("Pong not supported in tunnel adapter"));
904
- }
905
- /** @experimental */
906
- terminate() {
654
+ #terminate() {
907
655
  this.#readyState = 3;
908
656
  this.#closeCallback(1006, "Abnormal Closure");
909
- const event = {
910
- wasClean: false,
911
- code: 1006,
912
- reason: "Abnormal Closure",
913
- type: "close",
914
- target: this
915
- };
916
- this.#fireEvent("close", event);
657
+ this.#ws.triggerClose(1006, "Abnormal Closure", false);
917
658
  }
918
- }, _class2.__initStatic(), _class2.__initStatic2(), _class2.__initStatic3(), _class2.__initStatic4(), _class2);
659
+ };
919
660
 
920
661
  // src/tunnel.ts
921
662
  var Tunnel = class {
@@ -1167,7 +908,7 @@ var Tunnel = class {
1167
908
  await this.#runner.config.websocket(
1168
909
  this.#runner,
1169
910
  actorId,
1170
- adapter,
911
+ adapter.websocket,
1171
912
  gatewayId,
1172
913
  requestId,
1173
914
  request,
@@ -1220,7 +961,7 @@ var Tunnel = class {
1220
961
  }
1221
962
  #sendMessage(gatewayId, requestId, messageKind) {
1222
963
  var _a, _b, _c, _d;
1223
- if (!this.#runner.__webSocketReady()) {
964
+ if (!this.#runner.getPegboardWebSocketIfReady()) {
1224
965
  (_a = this.log) == null ? void 0 : _a.debug({
1225
966
  msg: "buffering tunnel message, socket not connected to engine",
1226
967
  requestId: idToStr(requestId),
@@ -1771,7 +1512,7 @@ var Runner = class {
1771
1512
  }
1772
1513
  #actors = /* @__PURE__ */ new Map();
1773
1514
  // WebSocket
1774
-
1515
+ #pegboardWebSocket;
1775
1516
 
1776
1517
  #started = false;
1777
1518
  #shutdown = false;
@@ -2014,8 +1755,8 @@ var Runner = class {
2014
1755
  );
2015
1756
  }
2016
1757
  this.#kvRequests.clear();
2017
- if (this.__webSocketReady()) {
2018
- const pegboardWebSocket = this.__pegboardWebSocket;
1758
+ const pegboardWebSocket = this.getPegboardWebSocketIfReady();
1759
+ if (pegboardWebSocket) {
2019
1760
  if (immediate) {
2020
1761
  pegboardWebSocket.close(1e3, "pegboard.runner_shutdown");
2021
1762
  } else {
@@ -2061,7 +1802,7 @@ var Runner = class {
2061
1802
  } else {
2062
1803
  (_h = this.log) == null ? void 0 : _h.debug({
2063
1804
  msg: "no runner WebSocket to shutdown or already closed",
2064
- readyState: (_g = this.__pegboardWebSocket) == null ? void 0 : _g.readyState
1805
+ readyState: (_g = this.#pegboardWebSocket) == null ? void 0 : _g.readyState
2065
1806
  });
2066
1807
  }
2067
1808
  if (this.#tunnel) {
@@ -2164,14 +1905,20 @@ var Runner = class {
2164
1905
  }
2165
1906
  // MARK: Runner protocol
2166
1907
  async #openPegboardWebSocket() {
2167
- var _a;
1908
+ var _a, _b;
2168
1909
  const protocols = ["rivet"];
2169
1910
  if (this.config.token)
2170
1911
  protocols.push(`rivet_token.${this.config.token}`);
2171
1912
  const WS = await importWebSocket();
1913
+ if (this.#pegboardWebSocket && (this.#pegboardWebSocket.readyState === WS.CONNECTING || this.#pegboardWebSocket.readyState === WS.OPEN)) {
1914
+ (_a = this.log) == null ? void 0 : _a.error(
1915
+ "found duplicate pegboardWebSocket, closing previous"
1916
+ );
1917
+ this.#pegboardWebSocket.close(1e3, "duplicate_websocket");
1918
+ }
2172
1919
  const ws = new WS(this.pegboardUrl, protocols);
2173
- this.__pegboardWebSocket = ws;
2174
- (_a = this.log) == null ? void 0 : _a.info({
1920
+ this.#pegboardWebSocket = ws;
1921
+ (_b = this.log) == null ? void 0 : _b.info({
2175
1922
  msg: "connecting",
2176
1923
  endpoint: this.pegboardEndpoint,
2177
1924
  namespace: this.#config.namespace,
@@ -2179,7 +1926,7 @@ var Runner = class {
2179
1926
  hasToken: !!this.config.token
2180
1927
  });
2181
1928
  ws.addEventListener("open", () => {
2182
- var _a2, _b;
1929
+ var _a2, _b2;
2183
1930
  if (this.#reconnectAttempt > 0) {
2184
1931
  (_a2 = this.log) == null ? void 0 : _a2.info({
2185
1932
  msg: "runner reconnected",
@@ -2188,7 +1935,7 @@ var Runner = class {
2188
1935
  reconnectAttempt: this.#reconnectAttempt
2189
1936
  });
2190
1937
  } else {
2191
- (_b = this.log) == null ? void 0 : _b.debug({
1938
+ (_b2 = this.log) == null ? void 0 : _b2.debug({
2192
1939
  msg: "runner connected",
2193
1940
  namespace: this.#config.namespace,
2194
1941
  runnerName: this.#config.runnerName
@@ -2223,7 +1970,7 @@ var Runner = class {
2223
1970
  });
2224
1971
  const ackInterval = 5 * 60 * 1e3;
2225
1972
  const ackLoop = setInterval(() => {
2226
- var _a3, _b2;
1973
+ var _a3, _b3;
2227
1974
  try {
2228
1975
  if (ws.readyState === 1) {
2229
1976
  this.#sendCommandAcknowledgment();
@@ -2234,7 +1981,7 @@ var Runner = class {
2234
1981
  });
2235
1982
  }
2236
1983
  } catch (err) {
2237
- (_b2 = this.log) == null ? void 0 : _b2.error({
1984
+ (_b3 = this.log) == null ? void 0 : _b3.error({
2238
1985
  msg: "error in command acknowledgment loop",
2239
1986
  error: stringifyError(err)
2240
1987
  });
@@ -2243,7 +1990,7 @@ var Runner = class {
2243
1990
  this.#ackInterval = ackLoop;
2244
1991
  });
2245
1992
  ws.addEventListener("message", async (ev) => {
2246
- var _a2, _b, _c, _d, _e;
1993
+ var _a2, _b2, _c, _d, _e;
2247
1994
  let buf;
2248
1995
  if (ev.data instanceof Blob) {
2249
1996
  buf = new Uint8Array(await ev.data.arrayBuffer());
@@ -2263,7 +2010,7 @@ var Runner = class {
2263
2010
  this.runnerId = init.runnerId;
2264
2011
  this.#stopAllActors();
2265
2012
  }
2266
- this.#runnerLostThreshold = ((_b = init.metadata) == null ? void 0 : _b.runnerLostThreshold) ? Number(init.metadata.runnerLostThreshold) : void 0;
2013
+ this.#runnerLostThreshold = ((_b2 = init.metadata) == null ? void 0 : _b2.runnerLostThreshold) ? Number(init.metadata.runnerLostThreshold) : void 0;
2267
2014
  (_c = this.log) == null ? void 0 : _c.info({
2268
2015
  msg: "received init",
2269
2016
  runnerLostThreshold: this.#runnerLostThreshold
@@ -2300,13 +2047,13 @@ var Runner = class {
2300
2047
  }
2301
2048
  });
2302
2049
  ws.addEventListener("error", (ev) => {
2303
- var _a2, _b;
2050
+ var _a2, _b2;
2304
2051
  (_a2 = this.log) == null ? void 0 : _a2.error({
2305
2052
  msg: `WebSocket error: ${ev.error}`
2306
2053
  });
2307
2054
  if (!this.#shutdown) {
2308
2055
  if (!this.#runnerLostTimeout && this.#runnerLostThreshold && this.#runnerLostThreshold > 0) {
2309
- (_b = this.log) == null ? void 0 : _b.info({
2056
+ (_b2 = this.log) == null ? void 0 : _b2.info({
2310
2057
  msg: "starting runner lost timeout",
2311
2058
  seconds: this.#runnerLostThreshold / 1e3
2312
2059
  });
@@ -2326,7 +2073,7 @@ var Runner = class {
2326
2073
  }
2327
2074
  });
2328
2075
  ws.addEventListener("close", async (ev) => {
2329
- var _a2, _b, _c, _d;
2076
+ var _a2, _b2, _c, _d;
2330
2077
  const closeError = parseWebSocketCloseReason(ev.reason);
2331
2078
  if ((closeError == null ? void 0 : closeError.group) === "ws" && (closeError == null ? void 0 : closeError.error) === "eviction") {
2332
2079
  (_a2 = this.log) == null ? void 0 : _a2.info("runner websocket evicted");
@@ -2334,7 +2081,7 @@ var Runner = class {
2334
2081
  await this.shutdown(true);
2335
2082
  } else {
2336
2083
  if ((closeError == null ? void 0 : closeError.group) === "pegboard" && (closeError == null ? void 0 : closeError.error) === "runner_shutdown") {
2337
- (_b = this.log) == null ? void 0 : _b.info("runner shutdown");
2084
+ (_b2 = this.log) == null ? void 0 : _b2.info("runner shutdown");
2338
2085
  } else {
2339
2086
  (_c = this.log) == null ? void 0 : _c.warn({
2340
2087
  msg: "runner disconnected",
@@ -2870,7 +2617,7 @@ var Runner = class {
2870
2617
  timestamp: Date.now()
2871
2618
  };
2872
2619
  this.#kvRequests.set(requestId, requestEntry);
2873
- if (this.__webSocketReady()) {
2620
+ if (this.getPegboardWebSocketIfReady()) {
2874
2621
  this.#sendSingleKvRequest(requestId);
2875
2622
  }
2876
2623
  });
@@ -2896,7 +2643,7 @@ var Runner = class {
2896
2643
  }
2897
2644
  }
2898
2645
  #processUnsentKvRequests() {
2899
- if (!this.__webSocketReady()) {
2646
+ if (!this.getPegboardWebSocketIfReady()) {
2900
2647
  return;
2901
2648
  }
2902
2649
  let processedCount = 0;
@@ -2910,8 +2657,12 @@ var Runner = class {
2910
2657
  }
2911
2658
  }
2912
2659
  /** Asserts WebSocket exists and is ready. */
2913
- __webSocketReady() {
2914
- return !!this.__pegboardWebSocket && this.__pegboardWebSocket.readyState === 1;
2660
+ getPegboardWebSocketIfReady() {
2661
+ if (!!this.#pegboardWebSocket && this.#pegboardWebSocket.readyState === 1) {
2662
+ return this.#pegboardWebSocket;
2663
+ } else {
2664
+ return void 0;
2665
+ }
2915
2666
  }
2916
2667
  __sendToServer(message) {
2917
2668
  var _a, _b;
@@ -2920,8 +2671,9 @@ var Runner = class {
2920
2671
  data: stringifyToServer(message)
2921
2672
  });
2922
2673
  const encoded = protocol.encodeToServer(message);
2923
- if (this.__webSocketReady()) {
2924
- this.__pegboardWebSocket.send(encoded);
2674
+ const pegboardWebSocket = this.getPegboardWebSocketIfReady();
2675
+ if (pegboardWebSocket) {
2676
+ pegboardWebSocket.send(encoded);
2925
2677
  } else {
2926
2678
  (_b = this.log) == null ? void 0 : _b.error({
2927
2679
  msg: "WebSocket not available or not open for sending data"
@@ -2980,7 +2732,7 @@ var Runner = class {
2980
2732
  return buffer.toString("base64");
2981
2733
  }
2982
2734
  #scheduleReconnect() {
2983
- var _a, _b;
2735
+ var _a, _b, _c;
2984
2736
  if (this.#shutdown) {
2985
2737
  (_a = this.log) == null ? void 0 : _a.debug({
2986
2738
  msg: "Runner is shut down, not attempting reconnect"
@@ -2996,6 +2748,12 @@ var Runner = class {
2996
2748
  (_b = this.log) == null ? void 0 : _b.debug({
2997
2749
  msg: `Scheduling reconnect attempt ${this.#reconnectAttempt + 1} in ${delay}ms`
2998
2750
  });
2751
+ if (this.#reconnectTimeout) {
2752
+ (_c = this.log) == null ? void 0 : _c.info(
2753
+ "clearing previous reconnect timeout in schedule reconnect"
2754
+ );
2755
+ clearTimeout(this.#reconnectTimeout);
2756
+ }
2999
2757
  this.#reconnectTimeout = setTimeout(() => {
3000
2758
  var _a2;
3001
2759
  if (!this.#shutdown) {