@rivetkit/engine-runner 2.0.22-rc.2 → 2.0.23

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
@@ -10,6 +10,129 @@ function logger() {
10
10
  return LOGGER;
11
11
  }
12
12
 
13
+ // src/stringify.ts
14
+ function stringifyArrayBuffer(buffer) {
15
+ return `ArrayBuffer(${buffer.byteLength})`;
16
+ }
17
+ function stringifyBigInt(value) {
18
+ return `${value}n`;
19
+ }
20
+ function stringifyMap(map) {
21
+ const entries = Array.from(map.entries()).map(([k, v]) => `"${k}": "${v}"`).join(", ");
22
+ return `Map(${map.size}){${entries}}`;
23
+ }
24
+ function stringifyToServerTunnelMessageKind(kind) {
25
+ switch (kind.tag) {
26
+ case "TunnelAck":
27
+ return "TunnelAck";
28
+ case "ToServerResponseStart": {
29
+ const { status, headers, body, stream } = kind.val;
30
+ const bodyStr = body === null ? "null" : stringifyArrayBuffer(body);
31
+ return `ToServerResponseStart{status: ${status}, headers: ${stringifyMap(headers)}, body: ${bodyStr}, stream: ${stream}}`;
32
+ }
33
+ case "ToServerResponseChunk": {
34
+ const { body, finish } = kind.val;
35
+ return `ToServerResponseChunk{body: ${stringifyArrayBuffer(body)}, finish: ${finish}}`;
36
+ }
37
+ case "ToServerResponseAbort":
38
+ return "ToServerResponseAbort";
39
+ case "ToServerWebSocketOpen": {
40
+ const { canHibernate, lastMsgIndex } = kind.val;
41
+ return `ToServerWebSocketOpen{canHibernate: ${canHibernate}, lastMsgIndex: ${stringifyBigInt(lastMsgIndex)}}`;
42
+ }
43
+ case "ToServerWebSocketMessage": {
44
+ const { data, binary } = kind.val;
45
+ return `ToServerWebSocketMessage{data: ${stringifyArrayBuffer(data)}, binary: ${binary}}`;
46
+ }
47
+ case "ToServerWebSocketMessageAck": {
48
+ const { index } = kind.val;
49
+ return `ToServerWebSocketMessageAck{index: ${index}}`;
50
+ }
51
+ case "ToServerWebSocketClose": {
52
+ const { code, reason, retry } = kind.val;
53
+ const codeStr = code === null ? "null" : code.toString();
54
+ const reasonStr = reason === null ? "null" : `"${reason}"`;
55
+ return `ToServerWebSocketClose{code: ${codeStr}, reason: ${reasonStr}, retry: ${retry}}`;
56
+ }
57
+ }
58
+ }
59
+ function stringifyToClientTunnelMessageKind(kind) {
60
+ switch (kind.tag) {
61
+ case "TunnelAck":
62
+ return "TunnelAck";
63
+ case "ToClientRequestStart": {
64
+ const { actorId, method, path, headers, body, stream } = kind.val;
65
+ const bodyStr = body === null ? "null" : stringifyArrayBuffer(body);
66
+ return `ToClientRequestStart{actorId: "${actorId}", method: "${method}", path: "${path}", headers: ${stringifyMap(headers)}, body: ${bodyStr}, stream: ${stream}}`;
67
+ }
68
+ case "ToClientRequestChunk": {
69
+ const { body, finish } = kind.val;
70
+ return `ToClientRequestChunk{body: ${stringifyArrayBuffer(body)}, finish: ${finish}}`;
71
+ }
72
+ case "ToClientRequestAbort":
73
+ return "ToClientRequestAbort";
74
+ case "ToClientWebSocketOpen": {
75
+ const { actorId, path, headers } = kind.val;
76
+ return `ToClientWebSocketOpen{actorId: "${actorId}", path: "${path}", headers: ${stringifyMap(headers)}}`;
77
+ }
78
+ case "ToClientWebSocketMessage": {
79
+ const { index, data, binary } = kind.val;
80
+ return `ToClientWebSocketMessage{index: ${index}, data: ${stringifyArrayBuffer(data)}, binary: ${binary}}`;
81
+ }
82
+ case "ToClientWebSocketClose": {
83
+ const { code, reason } = kind.val;
84
+ const codeStr = code === null ? "null" : code.toString();
85
+ const reasonStr = reason === null ? "null" : `"${reason}"`;
86
+ return `ToClientWebSocketClose{code: ${codeStr}, reason: ${reasonStr}}`;
87
+ }
88
+ }
89
+ }
90
+ function stringifyCommand(command) {
91
+ switch (command.tag) {
92
+ case "CommandStartActor": {
93
+ const { actorId, generation, config } = command.val;
94
+ const keyStr = config.key === null ? "null" : `"${config.key}"`;
95
+ const inputStr = config.input === null ? "null" : stringifyArrayBuffer(config.input);
96
+ return `CommandStartActor{actorId: "${actorId}", generation: ${generation}, config: {name: "${config.name}", key: ${keyStr}, createTs: ${stringifyBigInt(config.createTs)}, input: ${inputStr}}}`;
97
+ }
98
+ case "CommandStopActor": {
99
+ const { actorId, generation } = command.val;
100
+ return `CommandStopActor{actorId: "${actorId}", generation: ${generation}}`;
101
+ }
102
+ }
103
+ }
104
+ function stringifyCommandWrapper(wrapper) {
105
+ return `CommandWrapper{index: ${stringifyBigInt(wrapper.index)}, inner: ${stringifyCommand(wrapper.inner)}}`;
106
+ }
107
+ function stringifyEvent(event) {
108
+ switch (event.tag) {
109
+ case "EventActorIntent": {
110
+ const { actorId, generation, intent } = event.val;
111
+ const intentStr = intent.tag === "ActorIntentSleep" ? "Sleep" : intent.tag === "ActorIntentStop" ? "Stop" : "Unknown";
112
+ return `EventActorIntent{actorId: "${actorId}", generation: ${generation}, intent: ${intentStr}}`;
113
+ }
114
+ case "EventActorStateUpdate": {
115
+ const { actorId, generation, state } = event.val;
116
+ let stateStr;
117
+ if (state.tag === "ActorStateRunning") {
118
+ stateStr = "Running";
119
+ } else if (state.tag === "ActorStateStopped") {
120
+ const { code, message } = state.val;
121
+ const messageStr = message === null ? "null" : `"${message}"`;
122
+ stateStr = `Stopped{code: ${code}, message: ${messageStr}}`;
123
+ } else {
124
+ stateStr = "Unknown";
125
+ }
126
+ return `EventActorStateUpdate{actorId: "${actorId}", generation: ${generation}, state: ${stateStr}}`;
127
+ }
128
+ case "EventActorSetAlarm": {
129
+ const { actorId, generation, alarmTs } = event.val;
130
+ const alarmTsStr = alarmTs === null ? "null" : stringifyBigInt(alarmTs);
131
+ return `EventActorSetAlarm{actorId: "${actorId}", generation: ${generation}, alarmTs: ${alarmTsStr}}`;
132
+ }
133
+ }
134
+ }
135
+
13
136
  // src/tunnel.ts
14
137
  var _uuid = require('uuid');
15
138
 
@@ -30,6 +153,20 @@ function calculateBackoff(attempt, options = {}) {
30
153
  }
31
154
  return Math.floor(delay);
32
155
  }
156
+ function parseWebSocketCloseReason(reason) {
157
+ var _a;
158
+ const [mainPart, rayId] = reason.split("#");
159
+ const [group, error] = mainPart.split(".");
160
+ if (!group || !error) {
161
+ (_a = logger()) == null ? void 0 : _a.warn({ msg: "failed to parse close reason", reason });
162
+ return void 0;
163
+ }
164
+ return {
165
+ group,
166
+ error,
167
+ rayId
168
+ };
169
+ }
33
170
 
34
171
  // src/websocket-tunnel-adapter.ts
35
172
  var WebSocketTunnelAdapter = (_class = class {
@@ -48,6 +185,7 @@ var WebSocketTunnelAdapter = (_class = class {
48
185
  #url = "";
49
186
  #sendCallback;
50
187
  #closeCallback;
188
+ #canHibernate = false;
51
189
  // Event buffering for events fired before listeners are attached
52
190
  #bufferedEvents = [];
53
191
  constructor(webSocketId, sendCallback, closeCallback) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
@@ -78,6 +216,14 @@ var WebSocketTunnelAdapter = (_class = class {
78
216
  get url() {
79
217
  return this.#url;
80
218
  }
219
+ /** @experimental */
220
+ get canHibernate() {
221
+ return this.#canHibernate;
222
+ }
223
+ /** @experimental */
224
+ set canHibernate(value) {
225
+ this.#canHibernate = value;
226
+ }
81
227
  get onopen() {
82
228
  return this.#onopen;
83
229
  }
@@ -171,18 +317,23 @@ var WebSocketTunnelAdapter = (_class = class {
171
317
  this.#sendCallback(messageData, isBinary);
172
318
  }
173
319
  close(code, reason) {
174
- this.closeInner(code, reason);
320
+ this.closeInner(code, reason, false, true);
175
321
  }
176
322
  __closeWithRetry(code, reason) {
177
- this.closeInner(code, reason, true);
323
+ this.closeInner(code, reason, true, true);
324
+ }
325
+ __closeWithoutCallback(code, reason) {
326
+ this.closeInner(code, reason, false, false);
178
327
  }
179
- closeInner(code, reason, retry = false) {
328
+ closeInner(code, reason, retry, callback) {
180
329
  if (this.#readyState === 2 || // CLOSING
181
330
  this.#readyState === 3) {
182
331
  return;
183
332
  }
184
333
  this.#readyState = 2;
185
- this.#closeCallback(code, reason, retry);
334
+ if (callback) {
335
+ this.#closeCallback(code, reason, retry);
336
+ }
186
337
  this.#readyState = 3;
187
338
  const closeEvent = {
188
339
  wasClean: true,
@@ -472,6 +623,11 @@ var WebSocketTunnelAdapter = (_class = class {
472
623
  // src/tunnel.ts
473
624
  var GC_INTERVAL = 6e4;
474
625
  var MESSAGE_ACK_TIMEOUT = 5e3;
626
+ var RunnerShutdownError = class extends Error {
627
+ constructor() {
628
+ super("Runner shut down");
629
+ }
630
+ };
475
631
  var Tunnel = class {
476
632
  #runner;
477
633
  /** Requests over the tunnel to the actor that are in flight. */
@@ -481,6 +637,9 @@ var Tunnel = class {
481
637
  /** Messages sent from the actor over the tunnel that have not been acked by the gateway. */
482
638
  #pendingTunnelMessages = /* @__PURE__ */ new Map();
483
639
  #gcInterval;
640
+ get log() {
641
+ return this.#runner.log;
642
+ }
484
643
  constructor(runner) {
485
644
  this.#runner = runner;
486
645
  }
@@ -493,20 +652,24 @@ var Tunnel = class {
493
652
  this.#gcInterval = void 0;
494
653
  }
495
654
  for (const [_, request] of this.#actorPendingRequests) {
496
- request.reject(new Error("Tunnel shutting down"));
655
+ request.reject(new RunnerShutdownError());
497
656
  }
498
657
  this.#actorPendingRequests.clear();
499
658
  for (const [_, ws] of this.#actorWebSockets) {
500
- ws.__closeWithRetry();
659
+ if (!ws.canHibernate) {
660
+ ws.__closeWithoutCallback(1e3, "ws.tunnel_shutdown");
661
+ }
501
662
  }
502
663
  this.#actorWebSockets.clear();
503
664
  }
504
665
  #sendMessage(requestId, messageKind) {
505
666
  var _a, _b;
506
667
  if (!this.#runner.__webSocketReady()) {
507
- (_a = logger()) == null ? void 0 : _a.warn(
508
- "cannot send tunnel message, socket not connected to engine"
509
- );
668
+ (_a = this.log) == null ? void 0 : _a.warn({
669
+ msg: "cannot send tunnel message, socket not connected to engine",
670
+ requestId: idToStr(requestId),
671
+ message: stringifyToServerTunnelMessageKind(messageKind)
672
+ });
510
673
  return;
511
674
  }
512
675
  const messageId = generateUuidBuffer();
@@ -516,11 +679,11 @@ var Tunnel = class {
516
679
  sentAt: Date.now(),
517
680
  requestIdStr
518
681
  });
519
- (_b = logger()) == null ? void 0 : _b.debug({
682
+ (_b = this.log) == null ? void 0 : _b.debug({
520
683
  msg: "send tunnel msg",
521
684
  requestId: requestIdStr,
522
685
  messageId: messageIdStr,
523
- message: messageKind
686
+ message: stringifyToServerTunnelMessageKind(messageKind)
524
687
  });
525
688
  const message = {
526
689
  tag: "ToServerTunnelMessage",
@@ -545,7 +708,7 @@ var Tunnel = class {
545
708
  messageKind: { tag: "TunnelAck", val: null }
546
709
  }
547
710
  };
548
- (_a = logger()) == null ? void 0 : _a.debug({
711
+ (_a = this.log) == null ? void 0 : _a.debug({
549
712
  msg: "ack tunnel msg",
550
713
  requestId: idToStr(requestId),
551
714
  messageId: idToStr(messageId)
@@ -591,7 +754,7 @@ var Tunnel = class {
591
754
  }
592
755
  }
593
756
  if (messagesToDelete.length > 0) {
594
- (_a = logger()) == null ? void 0 : _a.warn({
757
+ (_a = this.log) == null ? void 0 : _a.warn({
595
758
  msg: "purging unacked tunnel messages, this indicates that the Rivet Engine is disconnected or not responding",
596
759
  count: messagesToDelete.length
597
760
  });
@@ -610,11 +773,11 @@ var Tunnel = class {
610
773
  }
611
774
  }
612
775
  actor.requests.clear();
613
- for (const webSocketId of actor.webSockets) {
614
- const ws = this.#actorWebSockets.get(webSocketId);
776
+ for (const requestIdStr of actor.webSockets) {
777
+ const ws = this.#actorWebSockets.get(requestIdStr);
615
778
  if (ws) {
616
779
  ws.__closeWithRetry(1e3, "Actor stopped");
617
- this.#actorWebSockets.delete(webSocketId);
780
+ this.#actorWebSockets.delete(requestIdStr);
618
781
  }
619
782
  }
620
783
  actor.webSockets.clear();
@@ -622,7 +785,7 @@ var Tunnel = class {
622
785
  async #fetch(actorId, requestId, request) {
623
786
  var _a;
624
787
  if (!this.#runner.hasActor(actorId)) {
625
- (_a = logger()) == null ? void 0 : _a.warn({
788
+ (_a = this.log) == null ? void 0 : _a.warn({
626
789
  msg: "ignoring request for unknown actor",
627
790
  actorId
628
791
  });
@@ -646,18 +809,18 @@ var Tunnel = class {
646
809
  var _a, _b;
647
810
  const requestIdStr = idToStr(message.requestId);
648
811
  const messageIdStr = idToStr(message.messageId);
649
- (_a = logger()) == null ? void 0 : _a.debug({
812
+ (_a = this.log) == null ? void 0 : _a.debug({
650
813
  msg: "receive tunnel msg",
651
814
  requestId: requestIdStr,
652
815
  messageId: messageIdStr,
653
- message: message.messageKind
816
+ message: stringifyToClientTunnelMessageKind(message.messageKind)
654
817
  });
655
818
  if (message.messageKind.tag === "TunnelAck") {
656
819
  const pending = this.#pendingTunnelMessages.get(messageIdStr);
657
820
  if (pending) {
658
821
  const didDelete = this.#pendingTunnelMessages.delete(messageIdStr);
659
822
  if (!didDelete) {
660
- (_b = logger()) == null ? void 0 : _b.warn({
823
+ (_b = this.log) == null ? void 0 : _b.warn({
661
824
  msg: "received tunnel ack for nonexistent message",
662
825
  requestId: requestIdStr,
663
826
  messageId: messageIdStr
@@ -712,7 +875,7 @@ var Tunnel = class {
712
875
  }
713
876
  }
714
877
  async #handleRequestStart(requestId, req) {
715
- var _a;
878
+ var _a, _b;
716
879
  const requestIdStr = idToStr(requestId);
717
880
  const actor = this.#runner.getActor(req.actorId);
718
881
  if (actor) {
@@ -766,8 +929,16 @@ var Tunnel = class {
766
929
  await this.#sendResponse(requestId, response);
767
930
  }
768
931
  } catch (error) {
769
- (_a = logger()) == null ? void 0 : _a.error({ msg: "error handling request", error });
770
- this.#sendResponseError(requestId, 500, "Internal Server Error");
932
+ if (error instanceof RunnerShutdownError) {
933
+ (_a = this.log) == null ? void 0 : _a.debug({ msg: "catught runner shutdown error" });
934
+ } else {
935
+ (_b = this.log) == null ? void 0 : _b.error({ msg: "error handling request", error });
936
+ this.#sendResponseError(
937
+ requestId,
938
+ 500,
939
+ "Internal Server Error"
940
+ );
941
+ }
771
942
  } finally {
772
943
  const actor2 = this.#runner.getActor(req.actorId);
773
944
  if (actor2) {
@@ -827,11 +998,11 @@ var Tunnel = class {
827
998
  });
828
999
  }
829
1000
  async #handleWebSocketOpen(requestId, open) {
830
- var _a, _b, _c;
831
- const webSocketId = idToStr(requestId);
1001
+ var _a, _b, _c, _d;
1002
+ const requestIdStr = idToStr(requestId);
832
1003
  const actor = this.#runner.getActor(open.actorId);
833
1004
  if (!actor) {
834
- (_a = logger()) == null ? void 0 : _a.warn({
1005
+ (_a = this.log) == null ? void 0 : _a.warn({
835
1006
  msg: "ignoring websocket for unknown actor",
836
1007
  actorId: open.actorId
837
1008
  });
@@ -847,7 +1018,7 @@ var Tunnel = class {
847
1018
  }
848
1019
  const websocketHandler = this.#runner.config.websocket;
849
1020
  if (!websocketHandler) {
850
- (_b = logger()) == null ? void 0 : _b.error({
1021
+ (_b = this.log) == null ? void 0 : _b.error({
851
1022
  msg: "no websocket handler configured for tunnel"
852
1023
  });
853
1024
  this.#sendMessage(requestId, {
@@ -860,12 +1031,20 @@ var Tunnel = class {
860
1031
  });
861
1032
  return;
862
1033
  }
1034
+ const existingAdapter = this.#actorWebSockets.get(requestIdStr);
1035
+ if (existingAdapter) {
1036
+ (_c = this.log) == null ? void 0 : _c.warn({
1037
+ msg: "closing existing websocket for duplicate open event for the same request id",
1038
+ requestId: requestIdStr
1039
+ });
1040
+ existingAdapter.__closeWithoutCallback(1e3, "ws.duplicate_open");
1041
+ }
863
1042
  if (actor) {
864
- actor.webSockets.add(webSocketId);
1043
+ actor.webSockets.add(requestIdStr);
865
1044
  }
866
1045
  try {
867
1046
  const adapter = new WebSocketTunnelAdapter(
868
- webSocketId,
1047
+ requestIdStr,
869
1048
  (data, isBinary) => {
870
1049
  const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data).buffer : data;
871
1050
  this.#sendMessage(requestId, {
@@ -885,13 +1064,13 @@ var Tunnel = class {
885
1064
  retry
886
1065
  }
887
1066
  });
888
- this.#actorWebSockets.delete(webSocketId);
1067
+ this.#actorWebSockets.delete(requestIdStr);
889
1068
  if (actor) {
890
- actor.webSockets.delete(webSocketId);
1069
+ actor.webSockets.delete(requestIdStr);
891
1070
  }
892
1071
  }
893
1072
  );
894
- this.#actorWebSockets.set(webSocketId, adapter);
1073
+ this.#actorWebSockets.set(requestIdStr, adapter);
895
1074
  const headerInit = {};
896
1075
  if (open.headers) {
897
1076
  for (const [k, v] of open.headers) {
@@ -909,6 +1088,7 @@ var Tunnel = class {
909
1088
  requestId,
910
1089
  request
911
1090
  );
1091
+ adapter.canHibernate = hibernationConfig.enabled;
912
1092
  this.#sendMessage(requestId, {
913
1093
  tag: "ToServerWebSocketOpen",
914
1094
  val: {
@@ -925,7 +1105,7 @@ var Tunnel = class {
925
1105
  request
926
1106
  );
927
1107
  } catch (error) {
928
- (_c = logger()) == null ? void 0 : _c.error({ msg: "error handling websocket open", error });
1108
+ (_d = this.log) == null ? void 0 : _d.error({ msg: "error handling websocket open", error });
929
1109
  this.#sendMessage(requestId, {
930
1110
  tag: "ToServerWebSocketClose",
931
1111
  val: {
@@ -934,16 +1114,16 @@ var Tunnel = class {
934
1114
  retry: false
935
1115
  }
936
1116
  });
937
- this.#actorWebSockets.delete(webSocketId);
1117
+ this.#actorWebSockets.delete(requestIdStr);
938
1118
  if (actor) {
939
- actor.webSockets.delete(webSocketId);
1119
+ actor.webSockets.delete(requestIdStr);
940
1120
  }
941
1121
  }
942
1122
  }
943
1123
  /// Returns false if the message was sent off
944
1124
  async #handleWebSocketMessage(requestId, msg) {
945
- const webSocketId = idToStr(requestId);
946
- const adapter = this.#actorWebSockets.get(webSocketId);
1125
+ const requestIdStr = idToStr(requestId);
1126
+ const adapter = this.#actorWebSockets.get(requestIdStr);
947
1127
  if (adapter) {
948
1128
  const data = msg.binary ? new Uint8Array(msg.data) : new TextDecoder().decode(new Uint8Array(msg.data));
949
1129
  return adapter._handleMessage(
@@ -958,7 +1138,7 @@ var Tunnel = class {
958
1138
  }
959
1139
  __ackWebsocketMessage(requestId, index) {
960
1140
  var _a;
961
- (_a = logger()) == null ? void 0 : _a.debug({
1141
+ (_a = this.log) == null ? void 0 : _a.debug({
962
1142
  msg: "ack ws msg",
963
1143
  requestId: idToStr(requestId),
964
1144
  index
@@ -1064,6 +1244,23 @@ var Runner = class {
1064
1244
  #kvCleanupInterval;
1065
1245
  // Tunnel for HTTP/WebSocket forwarding
1066
1246
  #tunnel;
1247
+ // Cached child logger with runner-specific attributes
1248
+ #logCached;
1249
+ get log() {
1250
+ if (this.#logCached) return this.#logCached;
1251
+ const l = logger();
1252
+ if (l) {
1253
+ if (this.runnerId) {
1254
+ this.#logCached = l.child({
1255
+ runnerId: this.runnerId
1256
+ });
1257
+ return this.#logCached;
1258
+ } else {
1259
+ return l;
1260
+ }
1261
+ }
1262
+ return void 0;
1263
+ }
1067
1264
  constructor(config) {
1068
1265
  this.#config = config;
1069
1266
  if (this.#config.logger) setLogger(this.#config.logger);
@@ -1073,6 +1270,13 @@ var Runner = class {
1073
1270
  }
1074
1271
  // MARK: Manage actors
1075
1272
  sleepActor(actorId, generation) {
1273
+ var _a;
1274
+ if (this.#shutdown) {
1275
+ (_a = this.log) == null ? void 0 : _a.warn({
1276
+ msg: "runner is shut down, cannot sleep actor"
1277
+ });
1278
+ return;
1279
+ }
1076
1280
  const actor = this.getActor(actorId, generation);
1077
1281
  if (!actor) return;
1078
1282
  this.#sendActorIntent(actorId, actor.generation, "sleep");
@@ -1096,9 +1300,8 @@ var Runner = class {
1096
1300
  }
1097
1301
  #stopAllActors() {
1098
1302
  var _a;
1099
- (_a = logger()) == null ? void 0 : _a.info({
1100
- msg: "stopping all actors due to runner lost threshold exceeded",
1101
- runnerId: this.runnerId
1303
+ (_a = this.log) == null ? void 0 : _a.info({
1304
+ msg: "stopping all actors due to runner lost threshold exceeded"
1102
1305
  });
1103
1306
  const actorIds = Array.from(this.#actors.keys());
1104
1307
  for (const actorId of actorIds) {
@@ -1109,17 +1312,15 @@ var Runner = class {
1109
1312
  var _a, _b;
1110
1313
  const actor = this.#actors.get(actorId);
1111
1314
  if (!actor) {
1112
- (_a = logger()) == null ? void 0 : _a.error({
1315
+ (_a = this.log) == null ? void 0 : _a.error({
1113
1316
  msg: "actor not found",
1114
- runnerId: this.runnerId,
1115
1317
  actorId
1116
1318
  });
1117
1319
  return void 0;
1118
1320
  }
1119
1321
  if (generation !== void 0 && actor.generation !== generation) {
1120
- (_b = logger()) == null ? void 0 : _b.error({
1322
+ (_b = this.log) == null ? void 0 : _b.error({
1121
1323
  msg: "actor generation mismatch",
1122
- runnerId: this.runnerId,
1123
1324
  actorId,
1124
1325
  generation
1125
1326
  });
@@ -1136,17 +1337,15 @@ var Runner = class {
1136
1337
  var _a, _b;
1137
1338
  const actor = this.#actors.get(actorId);
1138
1339
  if (!actor) {
1139
- (_a = logger()) == null ? void 0 : _a.error({
1340
+ (_a = this.log) == null ? void 0 : _a.error({
1140
1341
  msg: "actor not found for removal",
1141
- runnerId: this.runnerId,
1142
1342
  actorId
1143
1343
  });
1144
1344
  return void 0;
1145
1345
  }
1146
1346
  if (generation !== void 0 && actor.generation !== generation) {
1147
- (_b = logger()) == null ? void 0 : _b.error({
1347
+ (_b = this.log) == null ? void 0 : _b.error({
1148
1348
  msg: "actor generation mismatch",
1149
- runnerId: this.runnerId,
1150
1349
  actorId,
1151
1350
  generation
1152
1351
  });
@@ -1160,7 +1359,7 @@ var Runner = class {
1160
1359
  var _a, _b;
1161
1360
  if (this.#started) throw new Error("Cannot call runner.start twice");
1162
1361
  this.#started = true;
1163
- (_a = logger()) == null ? void 0 : _a.info({ msg: "starting runner" });
1362
+ (_a = this.log) == null ? void 0 : _a.info({ msg: "starting runner" });
1164
1363
  this.#tunnel = new Tunnel(this);
1165
1364
  this.#tunnel.start();
1166
1365
  try {
@@ -1173,7 +1372,7 @@ var Runner = class {
1173
1372
  if (!SIGNAL_HANDLERS.length) {
1174
1373
  process.on("SIGTERM", () => {
1175
1374
  var _a2;
1176
- (_a2 = logger()) == null ? void 0 : _a2.debug("received SIGTERM");
1375
+ (_a2 = this.log) == null ? void 0 : _a2.debug("received SIGTERM");
1177
1376
  for (const handler of SIGNAL_HANDLERS) {
1178
1377
  handler();
1179
1378
  }
@@ -1181,13 +1380,13 @@ var Runner = class {
1181
1380
  });
1182
1381
  process.on("SIGINT", () => {
1183
1382
  var _a2;
1184
- (_a2 = logger()) == null ? void 0 : _a2.debug("received SIGINT");
1383
+ (_a2 = this.log) == null ? void 0 : _a2.debug("received SIGINT");
1185
1384
  for (const handler of SIGNAL_HANDLERS) {
1186
1385
  handler();
1187
1386
  }
1188
1387
  process.exit(0);
1189
1388
  });
1190
- (_b = logger()) == null ? void 0 : _b.debug({
1389
+ (_b = this.log) == null ? void 0 : _b.debug({
1191
1390
  msg: "added SIGTERM listeners"
1192
1391
  });
1193
1392
  }
@@ -1201,9 +1400,8 @@ var Runner = class {
1201
1400
  // MARK: Shutdown
1202
1401
  async shutdown(immediate, exit = false) {
1203
1402
  var _a, _b, _c, _d, _e, _f, _g, _h;
1204
- (_a = logger()) == null ? void 0 : _a.info({
1403
+ (_a = this.log) == null ? void 0 : _a.info({
1205
1404
  msg: "starting shutdown",
1206
- runnerId: this.runnerId,
1207
1405
  immediate,
1208
1406
  exit
1209
1407
  });
@@ -1237,12 +1435,11 @@ var Runner = class {
1237
1435
  if (this.#pegboardWebSocket && this.#pegboardWebSocket.readyState === 1) {
1238
1436
  const pegboardWebSocket = this.#pegboardWebSocket;
1239
1437
  if (immediate) {
1240
- pegboardWebSocket.close(1e3, "Stopping");
1438
+ pegboardWebSocket.close(1e3, "pegboard.runner_shutdown");
1241
1439
  } else {
1242
1440
  try {
1243
- (_b = logger()) == null ? void 0 : _b.info({
1441
+ (_b = this.log) == null ? void 0 : _b.info({
1244
1442
  msg: "sending stopping message",
1245
- runnerId: this.runnerId,
1246
1443
  readyState: pegboardWebSocket.readyState
1247
1444
  });
1248
1445
  const encoded = protocol.encodeToServer({
@@ -1252,7 +1449,7 @@ var Runner = class {
1252
1449
  if (this.#pegboardWebSocket && this.#pegboardWebSocket.readyState === 1) {
1253
1450
  this.#pegboardWebSocket.send(encoded);
1254
1451
  } else {
1255
- (_c = logger()) == null ? void 0 : _c.error(
1452
+ (_c = this.log) == null ? void 0 : _c.error(
1256
1453
  "WebSocket not available or not open for sending data"
1257
1454
  );
1258
1455
  }
@@ -1261,38 +1458,33 @@ var Runner = class {
1261
1458
  throw new Error("missing pegboardWebSocket");
1262
1459
  pegboardWebSocket.addEventListener("close", (ev) => {
1263
1460
  var _a2;
1264
- (_a2 = logger()) == null ? void 0 : _a2.info({
1461
+ (_a2 = this.log) == null ? void 0 : _a2.info({
1265
1462
  msg: "connection closed",
1266
- runnerId: this.runnerId,
1267
1463
  code: ev.code,
1268
1464
  reason: ev.reason.toString()
1269
1465
  });
1270
1466
  resolve();
1271
1467
  });
1272
1468
  });
1273
- (_d = logger()) == null ? void 0 : _d.info({
1274
- msg: "closing WebSocket",
1275
- runnerId: this.runnerId
1469
+ (_d = this.log) == null ? void 0 : _d.info({
1470
+ msg: "closing WebSocket"
1276
1471
  });
1277
- pegboardWebSocket.close(1e3, "Stopping");
1472
+ pegboardWebSocket.close(1e3, "pegboard.runner_shutdown");
1278
1473
  await closePromise;
1279
- (_e = logger()) == null ? void 0 : _e.info({
1280
- msg: "websocket shutdown completed",
1281
- runnerId: this.runnerId
1474
+ (_e = this.log) == null ? void 0 : _e.info({
1475
+ msg: "websocket shutdown completed"
1282
1476
  });
1283
1477
  } catch (error) {
1284
- (_f = logger()) == null ? void 0 : _f.error({
1478
+ (_f = this.log) == null ? void 0 : _f.error({
1285
1479
  msg: "error during websocket shutdown:",
1286
- runnerId: this.runnerId,
1287
1480
  error
1288
1481
  });
1289
1482
  pegboardWebSocket.close();
1290
1483
  }
1291
1484
  }
1292
1485
  } else {
1293
- (_h = logger()) == null ? void 0 : _h.warn({
1486
+ (_h = this.log) == null ? void 0 : _h.debug({
1294
1487
  msg: "no runner WebSocket to shutdown or already closed",
1295
- runnerId: this.runnerId,
1296
1488
  readyState: (_g = this.#pegboardWebSocket) == null ? void 0 : _g.readyState
1297
1489
  });
1298
1490
  }
@@ -1321,7 +1513,7 @@ var Runner = class {
1321
1513
  const WS = await importWebSocket();
1322
1514
  const ws = new WS(this.pegboardUrl, protocols);
1323
1515
  this.#pegboardWebSocket = ws;
1324
- (_a = logger()) == null ? void 0 : _a.info({
1516
+ (_a = this.log) == null ? void 0 : _a.info({
1325
1517
  msg: "connecting",
1326
1518
  endpoint: this.pegboardEndpoint,
1327
1519
  namespace: this.#config.namespace,
@@ -1329,8 +1521,21 @@ var Runner = class {
1329
1521
  hasToken: !!this.config.token
1330
1522
  });
1331
1523
  ws.addEventListener("open", () => {
1332
- var _a2;
1333
- (_a2 = logger()) == null ? void 0 : _a2.info({ msg: "connected" });
1524
+ var _a2, _b;
1525
+ if (this.#reconnectAttempt > 0) {
1526
+ (_a2 = this.log) == null ? void 0 : _a2.info({
1527
+ msg: "runner reconnected",
1528
+ namespace: this.#config.namespace,
1529
+ runnerName: this.#config.runnerName,
1530
+ reconnectAttempt: this.#reconnectAttempt
1531
+ });
1532
+ } else {
1533
+ (_b = this.log) == null ? void 0 : _b.debug({
1534
+ msg: "runner connected",
1535
+ namespace: this.#config.namespace,
1536
+ runnerName: this.#config.runnerName
1537
+ });
1538
+ }
1334
1539
  this.#reconnectAttempt = 0;
1335
1540
  if (this.#reconnectTimeout) {
1336
1541
  clearTimeout(this.#reconnectTimeout);
@@ -1371,9 +1576,8 @@ var Runner = class {
1371
1576
  });
1372
1577
  } else {
1373
1578
  clearInterval(pingLoop);
1374
- (_a3 = logger()) == null ? void 0 : _a3.info({
1375
- msg: "WebSocket not open, stopping ping loop",
1376
- runnerId: this.runnerId
1579
+ (_a3 = this.log) == null ? void 0 : _a3.info({
1580
+ msg: "WebSocket not open, stopping ping loop"
1377
1581
  });
1378
1582
  }
1379
1583
  }, RUNNER_PING_INTERVAL);
@@ -1385,9 +1589,8 @@ var Runner = class {
1385
1589
  this.#sendCommandAcknowledgment();
1386
1590
  } else {
1387
1591
  clearInterval(ackLoop);
1388
- (_a3 = logger()) == null ? void 0 : _a3.info({
1389
- msg: "WebSocket not open, stopping ack loop",
1390
- runnerId: this.runnerId
1592
+ (_a3 = this.log) == null ? void 0 : _a3.info({
1593
+ msg: "WebSocket not open, stopping ack loop"
1391
1594
  });
1392
1595
  }
1393
1596
  }, ackInterval);
@@ -1411,9 +1614,8 @@ var Runner = class {
1411
1614
  this.#eventHistory.length = 0;
1412
1615
  }
1413
1616
  this.#runnerLostThreshold = ((_a2 = init.metadata) == null ? void 0 : _a2.runnerLostThreshold) ? Number(init.metadata.runnerLostThreshold) : void 0;
1414
- (_b = logger()) == null ? void 0 : _b.info({
1617
+ (_b = this.log) == null ? void 0 : _b.info({
1415
1618
  msg: "received init",
1416
- runnerId: init.runnerId,
1417
1619
  lastEventIdx: init.lastEventIdx,
1418
1620
  runnerLostThreshold: this.#runnerLostThreshold
1419
1621
  });
@@ -1438,15 +1640,13 @@ var Runner = class {
1438
1640
  });
1439
1641
  ws.addEventListener("error", (ev) => {
1440
1642
  var _a2, _b;
1441
- (_a2 = logger()) == null ? void 0 : _a2.error({
1442
- msg: `WebSocket error: ${ev.error}`,
1443
- runnerId: this.runnerId
1643
+ (_a2 = this.log) == null ? void 0 : _a2.error({
1644
+ msg: `WebSocket error: ${ev.error}`
1444
1645
  });
1445
1646
  if (!this.#shutdown) {
1446
1647
  if (!this.#runnerLostTimeout && this.#runnerLostThreshold && this.#runnerLostThreshold > 0) {
1447
- (_b = logger()) == null ? void 0 : _b.info({
1648
+ (_b = this.log) == null ? void 0 : _b.info({
1448
1649
  msg: "starting runner lost timeout",
1449
- runnerId: this.runnerId,
1450
1650
  seconds: this.#runnerLostThreshold / 1e3
1451
1651
  });
1452
1652
  this.#runnerLostTimeout = setTimeout(() => {
@@ -1457,20 +1657,24 @@ var Runner = class {
1457
1657
  }
1458
1658
  });
1459
1659
  ws.addEventListener("close", async (ev) => {
1460
- var _a2, _b, _c;
1461
- (_a2 = logger()) == null ? void 0 : _a2.info({
1462
- msg: "connection closed",
1463
- runnerId: this.runnerId,
1464
- code: ev.code,
1465
- reason: ev.reason.toString()
1466
- });
1467
- this.#config.onDisconnected(ev.code, ev.reason);
1468
- if (ev.reason.toString().startsWith("ws.eviction")) {
1469
- (_b = logger()) == null ? void 0 : _b.info({
1470
- msg: "runner evicted",
1471
- runnerId: this.runnerId
1472
- });
1660
+ var _a2, _b, _c, _d;
1661
+ const closeError = parseWebSocketCloseReason(ev.reason);
1662
+ if ((closeError == null ? void 0 : closeError.group) === "ws" && (closeError == null ? void 0 : closeError.error) === "eviction") {
1663
+ (_a2 = this.log) == null ? void 0 : _a2.info("runner websocket evicted");
1664
+ this.#config.onDisconnected(ev.code, ev.reason);
1473
1665
  await this.shutdown(true);
1666
+ } else {
1667
+ if ((closeError == null ? void 0 : closeError.group) === "pegboard" && (closeError == null ? void 0 : closeError.error) === "runner_shutdown") {
1668
+ (_b = this.log) == null ? void 0 : _b.info("runner shutdown");
1669
+ } else {
1670
+ (_c = this.log) == null ? void 0 : _c.warn({
1671
+ msg: "runner disconnected",
1672
+ code: ev.code,
1673
+ reason: ev.reason.toString(),
1674
+ closeError
1675
+ });
1676
+ }
1677
+ this.#config.onDisconnected(ev.code, ev.reason);
1474
1678
  }
1475
1679
  if (this.#pingLoop) {
1476
1680
  clearInterval(this.#pingLoop);
@@ -1482,9 +1686,8 @@ var Runner = class {
1482
1686
  }
1483
1687
  if (!this.#shutdown) {
1484
1688
  if (!this.#runnerLostTimeout && this.#runnerLostThreshold && this.#runnerLostThreshold > 0) {
1485
- (_c = logger()) == null ? void 0 : _c.info({
1689
+ (_d = this.log) == null ? void 0 : _d.info({
1486
1690
  msg: "starting runner lost timeout",
1487
- runnerId: this.runnerId,
1488
1691
  seconds: this.#runnerLostThreshold / 1e3
1489
1692
  });
1490
1693
  this.#runnerLostTimeout = setTimeout(() => {
@@ -1497,16 +1700,14 @@ var Runner = class {
1497
1700
  }
1498
1701
  #handleCommands(commands) {
1499
1702
  var _a, _b;
1500
- (_a = logger()) == null ? void 0 : _a.info({
1703
+ (_a = this.log) == null ? void 0 : _a.info({
1501
1704
  msg: "received commands",
1502
- runnerId: this.runnerId,
1503
1705
  commandCount: commands.length
1504
1706
  });
1505
1707
  for (const commandWrapper of commands) {
1506
- (_b = logger()) == null ? void 0 : _b.info({
1708
+ (_b = this.log) == null ? void 0 : _b.info({
1507
1709
  msg: "received command",
1508
- runnerId: this.runnerId,
1509
- commandWrapper
1710
+ command: stringifyCommandWrapper(commandWrapper)
1510
1711
  });
1511
1712
  if (commandWrapper.inner.tag === "CommandStartActor") {
1512
1713
  this.#handleCommandStartActor(commandWrapper);
@@ -1527,9 +1728,8 @@ var Runner = class {
1527
1728
  );
1528
1729
  const prunedCount = originalLength - this.#eventHistory.length;
1529
1730
  if (prunedCount > 0) {
1530
- (_a = logger()) == null ? void 0 : _a.info({
1731
+ (_a = this.log) == null ? void 0 : _a.info({
1531
1732
  msg: "pruned acknowledged events",
1532
- runnerId: this.runnerId,
1533
1733
  lastAckedIdx: lastAckedIdx.toString(),
1534
1734
  prunedCount
1535
1735
  });
@@ -1544,9 +1744,8 @@ var Runner = class {
1544
1744
  this.#eventHistory.push(eventWrapper);
1545
1745
  if (this.#eventHistory.length > EVENT_BACKLOG_WARN_THRESHOLD && !this.#eventBacklogWarned) {
1546
1746
  this.#eventBacklogWarned = true;
1547
- (_a = logger()) == null ? void 0 : _a.warn({
1747
+ (_a = this.log) == null ? void 0 : _a.warn({
1548
1748
  msg: "unacknowledged event backlog exceeds threshold",
1549
- runnerId: this.runnerId,
1550
1749
  backlogSize: this.#eventHistory.length,
1551
1750
  threshold: EVENT_BACKLOG_WARN_THRESHOLD
1552
1751
  });
@@ -1574,9 +1773,8 @@ var Runner = class {
1574
1773
  this.#sendActorStateUpdate(actorId, generation, "running");
1575
1774
  this.#config.onActorStart(actorId, generation, actorConfig).catch((err) => {
1576
1775
  var _a;
1577
- (_a = logger()) == null ? void 0 : _a.error({
1776
+ (_a = this.log) == null ? void 0 : _a.error({
1578
1777
  msg: "error in onactorstart for actor",
1579
- runnerId: this.runnerId,
1580
1778
  actorId,
1581
1779
  err
1582
1780
  });
@@ -1592,9 +1790,9 @@ var Runner = class {
1592
1790
  #sendActorIntent(actorId, generation, intentType) {
1593
1791
  var _a, _b;
1594
1792
  if (this.#shutdown) {
1595
- (_a = logger()) == null ? void 0 : _a.warn({
1596
- msg: "Runner is shut down, cannot send actor intent",
1597
- runnerId: this.runnerId
1793
+ console.trace("send actor intent", actorId, intentType);
1794
+ (_a = this.log) == null ? void 0 : _a.warn({
1795
+ msg: "Runner is shut down, cannot send actor intent"
1598
1796
  });
1599
1797
  return;
1600
1798
  }
@@ -1623,12 +1821,10 @@ var Runner = class {
1623
1821
  }
1624
1822
  };
1625
1823
  this.#recordEvent(eventWrapper);
1626
- (_b = logger()) == null ? void 0 : _b.info({
1824
+ (_b = this.log) == null ? void 0 : _b.info({
1627
1825
  msg: "sending event to server",
1628
- runnerId: this.runnerId,
1629
- index: eventWrapper.index,
1630
- tag: eventWrapper.inner.tag,
1631
- val: eventWrapper.inner.val
1826
+ event: stringifyEvent(eventWrapper.inner),
1827
+ index: eventWrapper.index.toString()
1632
1828
  });
1633
1829
  this.__sendToServer({
1634
1830
  tag: "ToServerEvents",
@@ -1638,9 +1834,8 @@ var Runner = class {
1638
1834
  #sendActorStateUpdate(actorId, generation, stateType) {
1639
1835
  var _a, _b;
1640
1836
  if (this.#shutdown) {
1641
- (_a = logger()) == null ? void 0 : _a.warn({
1642
- msg: "Runner is shut down, cannot send actor state update",
1643
- runnerId: this.runnerId
1837
+ (_a = this.log) == null ? void 0 : _a.warn({
1838
+ msg: "Runner is shut down, cannot send actor state update"
1644
1839
  });
1645
1840
  return;
1646
1841
  }
@@ -1672,12 +1867,10 @@ var Runner = class {
1672
1867
  }
1673
1868
  };
1674
1869
  this.#recordEvent(eventWrapper);
1675
- (_b = logger()) == null ? void 0 : _b.info({
1870
+ (_b = this.log) == null ? void 0 : _b.info({
1676
1871
  msg: "sending event to server",
1677
- runnerId: this.runnerId,
1678
- index: eventWrapper.index,
1679
- tag: eventWrapper.inner.tag,
1680
- val: eventWrapper.inner.val
1872
+ event: stringifyEvent(eventWrapper.inner),
1873
+ index: eventWrapper.index.toString()
1681
1874
  });
1682
1875
  this.__sendToServer({
1683
1876
  tag: "ToServerEvents",
@@ -1687,9 +1880,8 @@ var Runner = class {
1687
1880
  #sendCommandAcknowledgment() {
1688
1881
  var _a;
1689
1882
  if (this.#shutdown) {
1690
- (_a = logger()) == null ? void 0 : _a.warn({
1691
- msg: "Runner is shut down, cannot send command acknowledgment",
1692
- runnerId: this.runnerId
1883
+ (_a = this.log) == null ? void 0 : _a.warn({
1884
+ msg: "Runner is shut down, cannot send command acknowledgment"
1693
1885
  });
1694
1886
  return;
1695
1887
  }
@@ -1708,8 +1900,10 @@ var Runner = class {
1708
1900
  const requestId = response.requestId;
1709
1901
  const request = this.#kvRequests.get(requestId);
1710
1902
  if (!request) {
1711
- const msg = "received kv response for unknown request id";
1712
- (_a = logger()) == null ? void 0 : _a.error({ msg, runnerId: this.runnerId, requestId });
1903
+ (_a = this.log) == null ? void 0 : _a.error({
1904
+ msg: "received kv response for unknown request id",
1905
+ requestId
1906
+ });
1713
1907
  return;
1714
1908
  }
1715
1909
  this.#kvRequests.delete(requestId);
@@ -2014,9 +2208,8 @@ var Runner = class {
2014
2208
  __sendToServer(message) {
2015
2209
  var _a, _b;
2016
2210
  if (this.#shutdown) {
2017
- (_a = logger()) == null ? void 0 : _a.warn({
2018
- msg: "Runner is shut down, cannot send message to server",
2019
- runnerId: this.runnerId
2211
+ (_a = this.log) == null ? void 0 : _a.warn({
2212
+ msg: "Runner is shut down, cannot send message to server"
2020
2213
  });
2021
2214
  return;
2022
2215
  }
@@ -2024,9 +2217,8 @@ var Runner = class {
2024
2217
  if (this.#pegboardWebSocket && this.#pegboardWebSocket.readyState === 1) {
2025
2218
  this.#pegboardWebSocket.send(encoded);
2026
2219
  } else {
2027
- (_b = logger()) == null ? void 0 : _b.error({
2028
- msg: "WebSocket not available or not open for sending data",
2029
- runnerId: this.runnerId
2220
+ (_b = this.log) == null ? void 0 : _b.error({
2221
+ msg: "WebSocket not available or not open for sending data"
2030
2222
  });
2031
2223
  }
2032
2224
  }
@@ -2050,9 +2242,8 @@ var Runner = class {
2050
2242
  #scheduleReconnect() {
2051
2243
  var _a, _b;
2052
2244
  if (this.#shutdown) {
2053
- (_a = logger()) == null ? void 0 : _a.debug({
2054
- msg: "Runner is shut down, not attempting reconnect",
2055
- runnerId: this.runnerId
2245
+ (_a = this.log) == null ? void 0 : _a.debug({
2246
+ msg: "Runner is shut down, not attempting reconnect"
2056
2247
  });
2057
2248
  return;
2058
2249
  }
@@ -2062,17 +2253,15 @@ var Runner = class {
2062
2253
  multiplier: 2,
2063
2254
  jitter: true
2064
2255
  });
2065
- (_b = logger()) == null ? void 0 : _b.debug({
2066
- msg: `Scheduling reconnect attempt ${this.#reconnectAttempt + 1} in ${delay}ms`,
2067
- runnerId: this.runnerId
2256
+ (_b = this.log) == null ? void 0 : _b.debug({
2257
+ msg: `Scheduling reconnect attempt ${this.#reconnectAttempt + 1} in ${delay}ms`
2068
2258
  });
2069
2259
  this.#reconnectTimeout = setTimeout(async () => {
2070
2260
  var _a2;
2071
2261
  if (!this.#shutdown) {
2072
2262
  this.#reconnectAttempt++;
2073
- (_a2 = logger()) == null ? void 0 : _a2.debug({
2074
- msg: `Attempting to reconnect (attempt ${this.#reconnectAttempt})...`,
2075
- runnerId: this.runnerId
2263
+ (_a2 = this.log) == null ? void 0 : _a2.debug({
2264
+ msg: `Attempting to reconnect (attempt ${this.#reconnectAttempt})...`
2076
2265
  });
2077
2266
  await this.#openPegboardWebSocket();
2078
2267
  }