@rivetkit/engine-runner 2.0.25-rc.2 → 2.0.26
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/.turbo/turbo-build.log +10 -10
- package/dist/mod.cjs +230 -126
- package/dist/mod.cjs.map +1 -1
- package/dist/mod.d.cts +9 -1
- package/dist/mod.d.ts +9 -1
- package/dist/mod.js +221 -117
- package/dist/mod.js.map +1 -1
- package/package.json +2 -2
- package/src/actor.ts +18 -4
- package/src/mod.ts +176 -92
- package/src/stringify.ts +26 -26
- package/src/tunnel.ts +4 -13
- package/src/utils.ts +16 -0
package/dist/mod.cjs
CHANGED
|
@@ -83,10 +83,27 @@ function idToStr(id) {
|
|
|
83
83
|
const bytes = new Uint8Array(id);
|
|
84
84
|
return Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
85
85
|
}
|
|
86
|
+
function stringifyError(error) {
|
|
87
|
+
var _a;
|
|
88
|
+
if (error instanceof Error) {
|
|
89
|
+
return `${error.name}: ${error.message}${error.stack ? `
|
|
90
|
+
${error.stack}` : ""}`;
|
|
91
|
+
} else if (typeof error === "string") {
|
|
92
|
+
return error;
|
|
93
|
+
} else if (typeof error === "object" && error !== null) {
|
|
94
|
+
try {
|
|
95
|
+
return `${JSON.stringify(error)}`;
|
|
96
|
+
} catch (e2) {
|
|
97
|
+
return `[object ${((_a = error.constructor) == null ? void 0 : _a.name) || "Object"}]`;
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
return String(error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
86
103
|
|
|
87
104
|
// src/actor.ts
|
|
88
105
|
var RunnerActor = (_class = class {
|
|
89
|
-
constructor(actorId, generation, config, hibernatingRequests) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
|
|
106
|
+
constructor(actorId, generation, config, hibernatingRequests) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);
|
|
90
107
|
this.hibernatingRequests = hibernatingRequests;
|
|
91
108
|
this.actorId = actorId;
|
|
92
109
|
this.generation = generation;
|
|
@@ -99,11 +116,14 @@ var RunnerActor = (_class = class {
|
|
|
99
116
|
__init() {this.pendingRequests = []}
|
|
100
117
|
__init2() {this.webSockets = []}
|
|
101
118
|
|
|
119
|
+
__init3() {this.lastCommandIdx = -1n}
|
|
120
|
+
__init4() {this.nextEventIdx = 0n}
|
|
121
|
+
__init5() {this.eventHistory = []}
|
|
102
122
|
/**
|
|
103
123
|
* If restoreHibernatingRequests has been called. This is used to assert
|
|
104
124
|
* that the caller is implemented correctly.
|
|
105
125
|
**/
|
|
106
|
-
|
|
126
|
+
__init6() {this.hibernationRestored = false}
|
|
107
127
|
// Pending request methods
|
|
108
128
|
getPendingRequest(gatewayId, requestId) {
|
|
109
129
|
var _a;
|
|
@@ -215,6 +235,14 @@ var RunnerActor = (_class = class {
|
|
|
215
235
|
this.webSockets.splice(index, 1);
|
|
216
236
|
}
|
|
217
237
|
}
|
|
238
|
+
handleAckEvents(lastEventIdx) {
|
|
239
|
+
this.eventHistory = this.eventHistory.filter(
|
|
240
|
+
(event) => event.checkpoint.index > lastEventIdx
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
recordEvent(eventWrapper) {
|
|
244
|
+
this.eventHistory.push(eventWrapper);
|
|
245
|
+
}
|
|
218
246
|
}, _class);
|
|
219
247
|
|
|
220
248
|
// src/stringify.ts
|
|
@@ -233,8 +261,6 @@ function stringifyMessageId(messageId) {
|
|
|
233
261
|
}
|
|
234
262
|
function stringifyToServerTunnelMessageKind(kind) {
|
|
235
263
|
switch (kind.tag) {
|
|
236
|
-
case "DeprecatedTunnelAck":
|
|
237
|
-
return "DeprecatedTunnelAck";
|
|
238
264
|
case "ToServerResponseStart": {
|
|
239
265
|
const { status, headers, body, stream } = kind.val;
|
|
240
266
|
const bodyStr = body === null ? "null" : stringifyArrayBuffer(body);
|
|
@@ -268,8 +294,6 @@ function stringifyToServerTunnelMessageKind(kind) {
|
|
|
268
294
|
}
|
|
269
295
|
function stringifyToClientTunnelMessageKind(kind) {
|
|
270
296
|
switch (kind.tag) {
|
|
271
|
-
case "DeprecatedTunnelAck":
|
|
272
|
-
return "DeprecatedTunnelAck";
|
|
273
297
|
case "ToClientRequestStart": {
|
|
274
298
|
const { actorId, method, path, headers, body, stream } = kind.val;
|
|
275
299
|
const bodyStr = body === null ? "null" : stringifyArrayBuffer(body);
|
|
@@ -300,20 +324,20 @@ function stringifyToClientTunnelMessageKind(kind) {
|
|
|
300
324
|
function stringifyCommand(command) {
|
|
301
325
|
switch (command.tag) {
|
|
302
326
|
case "CommandStartActor": {
|
|
303
|
-
const {
|
|
327
|
+
const { generation, config, hibernatingRequests } = command.val;
|
|
304
328
|
const keyStr = config.key === null ? "null" : `"${config.key}"`;
|
|
305
329
|
const inputStr = config.input === null ? "null" : stringifyArrayBuffer(config.input);
|
|
306
330
|
const hibernatingRequestsStr = hibernatingRequests.length > 0 ? `[${hibernatingRequests.map((hr) => `{gatewayId: ${idToStr(hr.gatewayId)}, requestId: ${idToStr(hr.requestId)}}`).join(", ")}]` : "[]";
|
|
307
|
-
return `CommandStartActor{
|
|
331
|
+
return `CommandStartActor{generation: ${generation}, config: {name: "${config.name}", key: ${keyStr}, createTs: ${stringifyBigInt(config.createTs)}, input: ${inputStr}}, hibernatingRequests: ${hibernatingRequestsStr}}`;
|
|
308
332
|
}
|
|
309
333
|
case "CommandStopActor": {
|
|
310
|
-
const {
|
|
311
|
-
return `CommandStopActor{
|
|
334
|
+
const { generation } = command.val;
|
|
335
|
+
return `CommandStopActor{generation: ${generation}}`;
|
|
312
336
|
}
|
|
313
337
|
}
|
|
314
338
|
}
|
|
315
339
|
function stringifyCommandWrapper(wrapper) {
|
|
316
|
-
return `CommandWrapper{index: ${stringifyBigInt(wrapper.index)}, inner: ${stringifyCommand(wrapper.inner)}}`;
|
|
340
|
+
return `CommandWrapper{actorId: "${wrapper.checkpoint.actorId}", index: ${stringifyBigInt(wrapper.checkpoint.index)}, inner: ${stringifyCommand(wrapper.inner)}}`;
|
|
317
341
|
}
|
|
318
342
|
function stringifyEvent(event) {
|
|
319
343
|
switch (event.tag) {
|
|
@@ -344,7 +368,7 @@ function stringifyEvent(event) {
|
|
|
344
368
|
}
|
|
345
369
|
}
|
|
346
370
|
function stringifyEventWrapper(wrapper) {
|
|
347
|
-
return `EventWrapper{index: ${stringifyBigInt(wrapper.index)}, inner: ${stringifyEvent(wrapper.inner)}}`;
|
|
371
|
+
return `EventWrapper{actorId: ${wrapper.checkpoint.actorId}, index: ${stringifyBigInt(wrapper.checkpoint.index)}, inner: ${stringifyEvent(wrapper.inner)}}`;
|
|
348
372
|
}
|
|
349
373
|
function stringifyToServer(message) {
|
|
350
374
|
switch (message.tag) {
|
|
@@ -353,28 +377,27 @@ function stringifyToServer(message) {
|
|
|
353
377
|
name,
|
|
354
378
|
version,
|
|
355
379
|
totalSlots,
|
|
356
|
-
lastCommandIdx,
|
|
357
380
|
prepopulateActorNames,
|
|
358
381
|
metadata
|
|
359
382
|
} = message.val;
|
|
360
|
-
const lastCommandIdxStr = lastCommandIdx === null ? "null" : stringifyBigInt(lastCommandIdx);
|
|
361
383
|
const prepopulateActorNamesStr = prepopulateActorNames === null ? "null" : `Map(${prepopulateActorNames.size})`;
|
|
362
384
|
const metadataStr = metadata === null ? "null" : `"${metadata}"`;
|
|
363
|
-
return `ToServerInit{name: "${name}", version: ${version}, totalSlots: ${totalSlots},
|
|
385
|
+
return `ToServerInit{name: "${name}", version: ${version}, totalSlots: ${totalSlots}, prepopulateActorNames: ${prepopulateActorNamesStr}, metadata: ${metadataStr}}`;
|
|
364
386
|
}
|
|
365
387
|
case "ToServerEvents": {
|
|
366
388
|
const events = message.val;
|
|
367
389
|
return `ToServerEvents{count: ${events.length}, events: [${events.map((e) => stringifyEventWrapper(e)).join(", ")}]}`;
|
|
368
390
|
}
|
|
369
391
|
case "ToServerAckCommands": {
|
|
370
|
-
const {
|
|
371
|
-
|
|
392
|
+
const { lastCommandCheckpoints } = message.val;
|
|
393
|
+
const checkpointsStr = lastCommandCheckpoints.length > 0 ? `[${lastCommandCheckpoints.map((cp) => `{actorId: "${cp.actorId}", index: ${stringifyBigInt(cp.index)}}`).join(", ")}]` : "[]";
|
|
394
|
+
return `ToServerAckCommands{lastCommandCheckpoints: ${checkpointsStr}}`;
|
|
372
395
|
}
|
|
373
396
|
case "ToServerStopping":
|
|
374
397
|
return "ToServerStopping";
|
|
375
|
-
case "
|
|
398
|
+
case "ToServerPong": {
|
|
376
399
|
const { ts } = message.val;
|
|
377
|
-
return `
|
|
400
|
+
return `ToServerPong{ts: ${stringifyBigInt(ts)}}`;
|
|
378
401
|
}
|
|
379
402
|
case "ToServerKvRequest": {
|
|
380
403
|
const { actorId, requestId, data } = message.val;
|
|
@@ -390,19 +413,21 @@ function stringifyToServer(message) {
|
|
|
390
413
|
function stringifyToClient(message) {
|
|
391
414
|
switch (message.tag) {
|
|
392
415
|
case "ToClientInit": {
|
|
393
|
-
const { runnerId,
|
|
416
|
+
const { runnerId, metadata } = message.val;
|
|
394
417
|
const metadataStr = `{runnerLostThreshold: ${stringifyBigInt(metadata.runnerLostThreshold)}}`;
|
|
395
|
-
return `ToClientInit{runnerId: "${runnerId}",
|
|
418
|
+
return `ToClientInit{runnerId: "${runnerId}", metadata: ${metadataStr}}`;
|
|
396
419
|
}
|
|
397
|
-
case "
|
|
398
|
-
|
|
420
|
+
case "ToClientPing":
|
|
421
|
+
const { ts } = message.val;
|
|
422
|
+
return `ToClientPing{ts: ${stringifyBigInt(ts)}}`;
|
|
399
423
|
case "ToClientCommands": {
|
|
400
424
|
const commands = message.val;
|
|
401
425
|
return `ToClientCommands{count: ${commands.length}, commands: [${commands.map((c) => stringifyCommandWrapper(c)).join(", ")}]}`;
|
|
402
426
|
}
|
|
403
427
|
case "ToClientAckEvents": {
|
|
404
|
-
const {
|
|
405
|
-
|
|
428
|
+
const { lastEventCheckpoints } = message.val;
|
|
429
|
+
const checkpointsStr = lastEventCheckpoints.length > 0 ? `[${lastEventCheckpoints.map((cp) => `{actorId: "${cp.actorId}", index: ${stringifyBigInt(cp.index)}}`).join(", ")}]` : "[]";
|
|
430
|
+
return `ToClientAckEvents{lastEventCheckpoints: ${checkpointsStr}}`;
|
|
406
431
|
}
|
|
407
432
|
case "ToClientKvResponse": {
|
|
408
433
|
const { requestId, data } = message.val;
|
|
@@ -479,7 +504,7 @@ function stringifyKvResponseData(data) {
|
|
|
479
504
|
// src/websocket-tunnel-adapter.ts
|
|
480
505
|
var HIBERNATABLE_SYMBOL = Symbol("hibernatable");
|
|
481
506
|
var WebSocketTunnelAdapter = (_class2 = class {
|
|
482
|
-
constructor(tunnel, actorId, requestId, serverMessageIndex, hibernatable, isRestoringHibernatable, request, sendCallback, closeCallback) {;_class2.prototype.
|
|
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);
|
|
483
508
|
this.request = request;
|
|
484
509
|
var _a;
|
|
485
510
|
this.#tunnel = tunnel;
|
|
@@ -866,10 +891,10 @@ var WebSocketTunnelAdapter = (_class2 = class {
|
|
|
866
891
|
static __initStatic2() {this.OPEN = 1}
|
|
867
892
|
static __initStatic3() {this.CLOSING = 2}
|
|
868
893
|
static __initStatic4() {this.CLOSED = 3}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
894
|
+
__init7() {this.CONNECTING = 0}
|
|
895
|
+
__init8() {this.OPEN = 1}
|
|
896
|
+
__init9() {this.CLOSING = 2}
|
|
897
|
+
__init10() {this.CLOSED = 3}
|
|
873
898
|
// Additional methods for compatibility
|
|
874
899
|
ping(data, mask, cb) {
|
|
875
900
|
if (cb) cb(new Error("Ping not supported in tunnel adapter"));
|
|
@@ -893,11 +918,6 @@ var WebSocketTunnelAdapter = (_class2 = class {
|
|
|
893
918
|
}, _class2.__initStatic(), _class2.__initStatic2(), _class2.__initStatic3(), _class2.__initStatic4(), _class2);
|
|
894
919
|
|
|
895
920
|
// src/tunnel.ts
|
|
896
|
-
var RunnerShutdownError = class extends Error {
|
|
897
|
-
constructor() {
|
|
898
|
-
super("Runner shut down");
|
|
899
|
-
}
|
|
900
|
-
};
|
|
901
921
|
var Tunnel = class {
|
|
902
922
|
#runner;
|
|
903
923
|
/** Maps request IDs to actor IDs for lookup */
|
|
@@ -1019,7 +1039,7 @@ var Tunnel = class {
|
|
|
1019
1039
|
(_a2 = this.log) == null ? void 0 : _a2.error({
|
|
1020
1040
|
msg: "error creating websocket during restore",
|
|
1021
1041
|
requestId: requestIdStr,
|
|
1022
|
-
err
|
|
1042
|
+
error: stringifyError(err)
|
|
1023
1043
|
});
|
|
1024
1044
|
this.#sendMessage(gatewayId, requestId, {
|
|
1025
1045
|
tag: "ToServerWebSocketClose",
|
|
@@ -1068,7 +1088,7 @@ var Tunnel = class {
|
|
|
1068
1088
|
(_a2 = this.log) == null ? void 0 : _a2.error({
|
|
1069
1089
|
msg: "error creating stale websocket during restore",
|
|
1070
1090
|
requestId: requestIdStr,
|
|
1071
|
-
err
|
|
1091
|
+
error: stringifyError(err)
|
|
1072
1092
|
});
|
|
1073
1093
|
});
|
|
1074
1094
|
backgroundOperations.push(cleanupOperation);
|
|
@@ -1348,8 +1368,6 @@ var Tunnel = class {
|
|
|
1348
1368
|
message.messageKind.val
|
|
1349
1369
|
);
|
|
1350
1370
|
break;
|
|
1351
|
-
case "DeprecatedTunnelAck":
|
|
1352
|
-
break;
|
|
1353
1371
|
default:
|
|
1354
1372
|
unreachable(message.messageKind);
|
|
1355
1373
|
}
|
|
@@ -1720,7 +1738,7 @@ async function importWebSocket() {
|
|
|
1720
1738
|
const ws = await Promise.resolve().then(() => _interopRequireWildcard(require("ws")));
|
|
1721
1739
|
_WebSocket = ws.default;
|
|
1722
1740
|
(_b = logger()) == null ? void 0 : _b.debug({ msg: "using websocket from npm" });
|
|
1723
|
-
} catch (
|
|
1741
|
+
} catch (e3) {
|
|
1724
1742
|
_WebSocket = class MockWebSocket {
|
|
1725
1743
|
constructor() {
|
|
1726
1744
|
throw new Error(
|
|
@@ -1738,10 +1756,14 @@ async function importWebSocket() {
|
|
|
1738
1756
|
|
|
1739
1757
|
// src/mod.ts
|
|
1740
1758
|
var KV_EXPIRE = 3e4;
|
|
1741
|
-
var PROTOCOL_VERSION =
|
|
1742
|
-
var RUNNER_PING_INTERVAL = 3e3;
|
|
1759
|
+
var PROTOCOL_VERSION = 4;
|
|
1743
1760
|
var EVENT_BACKLOG_WARN_THRESHOLD = 1e4;
|
|
1744
1761
|
var SIGNAL_HANDLERS = [];
|
|
1762
|
+
var RunnerShutdownError = class extends Error {
|
|
1763
|
+
constructor() {
|
|
1764
|
+
super("Runner shut down");
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1745
1767
|
var Runner = class {
|
|
1746
1768
|
#config;
|
|
1747
1769
|
get config() {
|
|
@@ -1751,9 +1773,6 @@ var Runner = class {
|
|
|
1751
1773
|
// WebSocket
|
|
1752
1774
|
|
|
1753
1775
|
|
|
1754
|
-
#lastCommandIdx = -1;
|
|
1755
|
-
#pingLoop;
|
|
1756
|
-
#nextEventIdx = 0n;
|
|
1757
1776
|
#started = false;
|
|
1758
1777
|
#shutdown = false;
|
|
1759
1778
|
#shuttingDown = false;
|
|
@@ -1763,7 +1782,6 @@ var Runner = class {
|
|
|
1763
1782
|
#runnerLostThreshold;
|
|
1764
1783
|
#runnerLostTimeout;
|
|
1765
1784
|
// Event storage for resending
|
|
1766
|
-
#eventHistory = [];
|
|
1767
1785
|
#eventBacklogWarned = false;
|
|
1768
1786
|
// Command acknowledgment
|
|
1769
1787
|
#ackInterval;
|
|
@@ -1794,7 +1812,15 @@ var Runner = class {
|
|
|
1794
1812
|
this.#config = config;
|
|
1795
1813
|
if (this.#config.logger) setLogger(this.#config.logger);
|
|
1796
1814
|
this.#kvCleanupInterval = setInterval(() => {
|
|
1797
|
-
|
|
1815
|
+
var _a;
|
|
1816
|
+
try {
|
|
1817
|
+
this.#cleanupOldKvRequests();
|
|
1818
|
+
} catch (err) {
|
|
1819
|
+
(_a = this.log) == null ? void 0 : _a.error({
|
|
1820
|
+
msg: "error cleaning up kv requests",
|
|
1821
|
+
error: stringifyError(err)
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1798
1824
|
}, 15e3);
|
|
1799
1825
|
}
|
|
1800
1826
|
// MARK: Manage actors
|
|
@@ -1821,14 +1847,28 @@ var Runner = class {
|
|
|
1821
1847
|
this.#removeActor(actorId, generation);
|
|
1822
1848
|
this.#sendActorStateUpdate(actorId, actor.generation, "stopped");
|
|
1823
1849
|
}
|
|
1824
|
-
#
|
|
1850
|
+
#handleLost() {
|
|
1825
1851
|
var _a;
|
|
1826
1852
|
(_a = this.log) == null ? void 0 : _a.info({
|
|
1827
|
-
msg: "stopping all actors due to runner lost threshold
|
|
1853
|
+
msg: "stopping all actors due to runner lost threshold"
|
|
1828
1854
|
});
|
|
1855
|
+
for (const [_, request] of this.#kvRequests.entries()) {
|
|
1856
|
+
request.reject(new RunnerShutdownError());
|
|
1857
|
+
}
|
|
1858
|
+
this.#kvRequests.clear();
|
|
1859
|
+
this.#stopAllActors();
|
|
1860
|
+
}
|
|
1861
|
+
#stopAllActors() {
|
|
1829
1862
|
const actorIds = Array.from(this.#actors.keys());
|
|
1830
1863
|
for (const actorId of actorIds) {
|
|
1831
|
-
this.forceStopActor(actorId)
|
|
1864
|
+
this.forceStopActor(actorId).catch((err) => {
|
|
1865
|
+
var _a;
|
|
1866
|
+
(_a = this.log) == null ? void 0 : _a.error({
|
|
1867
|
+
msg: "error stopping actor",
|
|
1868
|
+
actorId,
|
|
1869
|
+
error: stringifyError(err)
|
|
1870
|
+
});
|
|
1871
|
+
});
|
|
1832
1872
|
}
|
|
1833
1873
|
}
|
|
1834
1874
|
getActor(actorId, generation) {
|
|
@@ -1956,10 +1996,6 @@ var Runner = class {
|
|
|
1956
1996
|
clearTimeout(this.#runnerLostTimeout);
|
|
1957
1997
|
this.#runnerLostTimeout = void 0;
|
|
1958
1998
|
}
|
|
1959
|
-
if (this.#pingLoop) {
|
|
1960
|
-
clearInterval(this.#pingLoop);
|
|
1961
|
-
this.#pingLoop = void 0;
|
|
1962
|
-
}
|
|
1963
1999
|
if (this.#ackInterval) {
|
|
1964
2000
|
clearInterval(this.#ackInterval);
|
|
1965
2001
|
this.#ackInterval = void 0;
|
|
@@ -2167,7 +2203,6 @@ var Runner = class {
|
|
|
2167
2203
|
name: this.#config.runnerName,
|
|
2168
2204
|
version: this.#config.version,
|
|
2169
2205
|
totalSlots: this.#config.totalSlots,
|
|
2170
|
-
lastCommandIdx: this.#lastCommandIdx >= 0 ? BigInt(this.#lastCommandIdx) : null,
|
|
2171
2206
|
prepopulateActorNames: new Map(
|
|
2172
2207
|
Object.entries(this.#config.prepopulateActorNames).map(
|
|
2173
2208
|
([name, data]) => [
|
|
@@ -2182,39 +2217,29 @@ var Runner = class {
|
|
|
2182
2217
|
tag: "ToServerInit",
|
|
2183
2218
|
val: init
|
|
2184
2219
|
});
|
|
2185
|
-
const pingLoop = setInterval(() => {
|
|
2186
|
-
var _a3;
|
|
2187
|
-
if (ws.readyState === 1) {
|
|
2188
|
-
this.__sendToServer({
|
|
2189
|
-
tag: "ToServerPing",
|
|
2190
|
-
val: {
|
|
2191
|
-
ts: BigInt(Date.now())
|
|
2192
|
-
}
|
|
2193
|
-
});
|
|
2194
|
-
} else {
|
|
2195
|
-
clearInterval(pingLoop);
|
|
2196
|
-
(_a3 = this.log) == null ? void 0 : _a3.info({
|
|
2197
|
-
msg: "WebSocket not open, stopping ping loop"
|
|
2198
|
-
});
|
|
2199
|
-
}
|
|
2200
|
-
}, RUNNER_PING_INTERVAL);
|
|
2201
|
-
this.#pingLoop = pingLoop;
|
|
2202
2220
|
const ackInterval = 5 * 60 * 1e3;
|
|
2203
2221
|
const ackLoop = setInterval(() => {
|
|
2204
|
-
var _a3;
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2222
|
+
var _a3, _b2;
|
|
2223
|
+
try {
|
|
2224
|
+
if (ws.readyState === 1) {
|
|
2225
|
+
this.#sendCommandAcknowledgment();
|
|
2226
|
+
} else {
|
|
2227
|
+
clearInterval(ackLoop);
|
|
2228
|
+
(_a3 = this.log) == null ? void 0 : _a3.info({
|
|
2229
|
+
msg: "WebSocket not open, stopping ack loop"
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
} catch (err) {
|
|
2233
|
+
(_b2 = this.log) == null ? void 0 : _b2.error({
|
|
2234
|
+
msg: "error in command acknowledgment loop",
|
|
2235
|
+
error: stringifyError(err)
|
|
2211
2236
|
});
|
|
2212
2237
|
}
|
|
2213
2238
|
}, ackInterval);
|
|
2214
2239
|
this.#ackInterval = ackLoop;
|
|
2215
2240
|
});
|
|
2216
2241
|
ws.addEventListener("message", async (ev) => {
|
|
2217
|
-
var _a2, _b, _c, _d, _e
|
|
2242
|
+
var _a2, _b, _c, _d, _e;
|
|
2218
2243
|
let buf;
|
|
2219
2244
|
if (ev.data instanceof Blob) {
|
|
2220
2245
|
buf = new Uint8Array(await ev.data.arrayBuffer());
|
|
@@ -2232,16 +2257,15 @@ var Runner = class {
|
|
|
2232
2257
|
const init = message.val;
|
|
2233
2258
|
if (this.runnerId !== init.runnerId) {
|
|
2234
2259
|
this.runnerId = init.runnerId;
|
|
2235
|
-
this.#
|
|
2260
|
+
this.#stopAllActors();
|
|
2236
2261
|
}
|
|
2237
2262
|
this.#runnerLostThreshold = ((_b = init.metadata) == null ? void 0 : _b.runnerLostThreshold) ? Number(init.metadata.runnerLostThreshold) : void 0;
|
|
2238
2263
|
(_c = this.log) == null ? void 0 : _c.info({
|
|
2239
2264
|
msg: "received init",
|
|
2240
|
-
lastEventIdx: init.lastEventIdx,
|
|
2241
2265
|
runnerLostThreshold: this.#runnerLostThreshold
|
|
2242
2266
|
});
|
|
2243
2267
|
this.#processUnsentKvRequests();
|
|
2244
|
-
this.#resendUnacknowledgedEvents(
|
|
2268
|
+
this.#resendUnacknowledgedEvents();
|
|
2245
2269
|
(_d = this.#tunnel) == null ? void 0 : _d.resendBufferedEvents();
|
|
2246
2270
|
this.#config.onConnected();
|
|
2247
2271
|
} else if (message.tag === "ToClientCommands") {
|
|
@@ -2253,10 +2277,20 @@ var Runner = class {
|
|
|
2253
2277
|
const kvResponse = message.val;
|
|
2254
2278
|
this.#handleKvResponse(kvResponse);
|
|
2255
2279
|
} else if (message.tag === "ToClientTunnelMessage") {
|
|
2256
|
-
(_e = this.#tunnel) == null ? void 0 : _e.handleTunnelMessage(message.val)
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2280
|
+
(_e = this.#tunnel) == null ? void 0 : _e.handleTunnelMessage(message.val).catch((err) => {
|
|
2281
|
+
var _a3;
|
|
2282
|
+
(_a3 = this.log) == null ? void 0 : _a3.error({
|
|
2283
|
+
msg: "error handling tunnel message",
|
|
2284
|
+
error: stringifyError(err)
|
|
2285
|
+
});
|
|
2286
|
+
});
|
|
2287
|
+
} else if (message.tag === "ToClientPing") {
|
|
2288
|
+
this.__sendToServer({
|
|
2289
|
+
tag: "ToServerPong",
|
|
2290
|
+
val: {
|
|
2291
|
+
ts: message.val.ts
|
|
2292
|
+
}
|
|
2293
|
+
});
|
|
2260
2294
|
} else {
|
|
2261
2295
|
unreachable(message);
|
|
2262
2296
|
}
|
|
@@ -2273,7 +2307,15 @@ var Runner = class {
|
|
|
2273
2307
|
seconds: this.#runnerLostThreshold / 1e3
|
|
2274
2308
|
});
|
|
2275
2309
|
this.#runnerLostTimeout = setTimeout(() => {
|
|
2276
|
-
|
|
2310
|
+
var _a3;
|
|
2311
|
+
try {
|
|
2312
|
+
this.#handleLost();
|
|
2313
|
+
} catch (err) {
|
|
2314
|
+
(_a3 = this.log) == null ? void 0 : _a3.error({
|
|
2315
|
+
msg: "error handling runner lost",
|
|
2316
|
+
error: stringifyError(err)
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2277
2319
|
}, this.#runnerLostThreshold);
|
|
2278
2320
|
}
|
|
2279
2321
|
this.#scheduleReconnect();
|
|
@@ -2299,10 +2341,6 @@ var Runner = class {
|
|
|
2299
2341
|
}
|
|
2300
2342
|
this.#config.onDisconnected(ev.code, ev.reason);
|
|
2301
2343
|
}
|
|
2302
|
-
if (this.#pingLoop) {
|
|
2303
|
-
clearInterval(this.#pingLoop);
|
|
2304
|
-
this.#pingLoop = void 0;
|
|
2305
|
-
}
|
|
2306
2344
|
if (this.#ackInterval) {
|
|
2307
2345
|
clearInterval(this.#ackInterval);
|
|
2308
2346
|
this.#ackInterval = void 0;
|
|
@@ -2314,7 +2352,15 @@ var Runner = class {
|
|
|
2314
2352
|
seconds: this.#runnerLostThreshold / 1e3
|
|
2315
2353
|
});
|
|
2316
2354
|
this.#runnerLostTimeout = setTimeout(() => {
|
|
2317
|
-
|
|
2355
|
+
var _a3;
|
|
2356
|
+
try {
|
|
2357
|
+
this.#handleLost();
|
|
2358
|
+
} catch (err) {
|
|
2359
|
+
(_a3 = this.log) == null ? void 0 : _a3.error({
|
|
2360
|
+
msg: "error handling runner lost",
|
|
2361
|
+
error: stringifyError(err)
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2318
2364
|
}, this.#runnerLostThreshold);
|
|
2319
2365
|
}
|
|
2320
2366
|
this.#scheduleReconnect();
|
|
@@ -2329,43 +2375,75 @@ var Runner = class {
|
|
|
2329
2375
|
});
|
|
2330
2376
|
for (const commandWrapper of commands) {
|
|
2331
2377
|
if (commandWrapper.inner.tag === "CommandStartActor") {
|
|
2332
|
-
this.#handleCommandStartActor(commandWrapper)
|
|
2378
|
+
this.#handleCommandStartActor(commandWrapper).catch((err) => {
|
|
2379
|
+
var _a2;
|
|
2380
|
+
(_a2 = this.log) == null ? void 0 : _a2.error({
|
|
2381
|
+
msg: "error handling start actor command",
|
|
2382
|
+
actorId: commandWrapper.checkpoint.actorId,
|
|
2383
|
+
error: stringifyError(err)
|
|
2384
|
+
});
|
|
2385
|
+
});
|
|
2333
2386
|
} else if (commandWrapper.inner.tag === "CommandStopActor") {
|
|
2334
|
-
this.#handleCommandStopActor(commandWrapper)
|
|
2387
|
+
this.#handleCommandStopActor(commandWrapper).catch((err) => {
|
|
2388
|
+
var _a2;
|
|
2389
|
+
(_a2 = this.log) == null ? void 0 : _a2.error({
|
|
2390
|
+
msg: "error handling stop actor command",
|
|
2391
|
+
actorId: commandWrapper.checkpoint.actorId,
|
|
2392
|
+
error: stringifyError(err)
|
|
2393
|
+
});
|
|
2394
|
+
});
|
|
2335
2395
|
} else {
|
|
2336
2396
|
unreachable(commandWrapper.inner);
|
|
2337
2397
|
}
|
|
2338
|
-
|
|
2398
|
+
const actor = this.getActor(
|
|
2399
|
+
commandWrapper.checkpoint.actorId,
|
|
2400
|
+
commandWrapper.inner.val.generation
|
|
2401
|
+
);
|
|
2402
|
+
if (actor) actor.lastCommandIdx = commandWrapper.checkpoint.index;
|
|
2339
2403
|
}
|
|
2340
2404
|
}
|
|
2341
2405
|
#handleAckEvents(ack) {
|
|
2342
2406
|
var _a;
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2407
|
+
let originalTotalEvents = Array.from(this.#actors).reduce(
|
|
2408
|
+
(s, [_, actor]) => s + actor.eventHistory.length,
|
|
2409
|
+
0
|
|
2410
|
+
);
|
|
2411
|
+
for (const [_, actor] of this.#actors) {
|
|
2412
|
+
let checkpoint = ack.lastEventCheckpoints.find(
|
|
2413
|
+
(x) => x.actorId == actor.actorId
|
|
2414
|
+
);
|
|
2415
|
+
if (checkpoint) actor.handleAckEvents(checkpoint.index);
|
|
2416
|
+
}
|
|
2417
|
+
const totalEvents = Array.from(this.#actors).reduce(
|
|
2418
|
+
(s, [_, actor]) => s + actor.eventHistory.length,
|
|
2419
|
+
0
|
|
2347
2420
|
);
|
|
2348
|
-
const prunedCount =
|
|
2421
|
+
const prunedCount = originalTotalEvents - totalEvents;
|
|
2349
2422
|
if (prunedCount > 0) {
|
|
2350
2423
|
(_a = this.log) == null ? void 0 : _a.info({
|
|
2351
2424
|
msg: "pruned acknowledged events",
|
|
2352
|
-
lastAckedIdx: lastAckedIdx.toString(),
|
|
2353
2425
|
prunedCount
|
|
2354
2426
|
});
|
|
2355
2427
|
}
|
|
2356
|
-
if (
|
|
2428
|
+
if (totalEvents <= EVENT_BACKLOG_WARN_THRESHOLD) {
|
|
2357
2429
|
this.#eventBacklogWarned = false;
|
|
2358
2430
|
}
|
|
2359
2431
|
}
|
|
2360
2432
|
/** Track events to send to the server in case we need to resend it on disconnect. */
|
|
2361
2433
|
#recordEvent(eventWrapper) {
|
|
2362
2434
|
var _a;
|
|
2363
|
-
this
|
|
2364
|
-
if (
|
|
2435
|
+
const actor = this.getActor(eventWrapper.checkpoint.actorId);
|
|
2436
|
+
if (!actor) return;
|
|
2437
|
+
actor.recordEvent(eventWrapper);
|
|
2438
|
+
let totalEvents = Array.from(this.#actors).reduce(
|
|
2439
|
+
(s, [_, actor2]) => s + actor2.eventHistory.length,
|
|
2440
|
+
0
|
|
2441
|
+
);
|
|
2442
|
+
if (totalEvents > EVENT_BACKLOG_WARN_THRESHOLD && !this.#eventBacklogWarned) {
|
|
2365
2443
|
this.#eventBacklogWarned = true;
|
|
2366
2444
|
(_a = this.log) == null ? void 0 : _a.warn({
|
|
2367
2445
|
msg: "unacknowledged event backlog exceeds threshold",
|
|
2368
|
-
backlogSize:
|
|
2446
|
+
backlogSize: totalEvents,
|
|
2369
2447
|
threshold: EVENT_BACKLOG_WARN_THRESHOLD
|
|
2370
2448
|
});
|
|
2371
2449
|
}
|
|
@@ -2374,7 +2452,7 @@ var Runner = class {
|
|
|
2374
2452
|
var _a, _b, _c, _d;
|
|
2375
2453
|
if (!this.#tunnel) throw new Error("missing tunnel on actor start");
|
|
2376
2454
|
const startCommand = commandWrapper.inner.val;
|
|
2377
|
-
const actorId =
|
|
2455
|
+
const actorId = commandWrapper.checkpoint.actorId;
|
|
2378
2456
|
const generation = startCommand.generation;
|
|
2379
2457
|
const config = startCommand.config;
|
|
2380
2458
|
const actorConfig = {
|
|
@@ -2433,11 +2511,13 @@ var Runner = class {
|
|
|
2433
2511
|
}
|
|
2434
2512
|
async #handleCommandStopActor(commandWrapper) {
|
|
2435
2513
|
const stopCommand = commandWrapper.inner.val;
|
|
2436
|
-
const actorId =
|
|
2514
|
+
const actorId = commandWrapper.checkpoint.actorId;
|
|
2437
2515
|
const generation = stopCommand.generation;
|
|
2438
2516
|
await this.forceStopActor(actorId, generation);
|
|
2439
2517
|
}
|
|
2440
2518
|
#sendActorIntent(actorId, generation, intentType) {
|
|
2519
|
+
const actor = this.getActor(actorId, generation);
|
|
2520
|
+
if (!actor) return;
|
|
2441
2521
|
let actorIntent;
|
|
2442
2522
|
if (intentType === "sleep") {
|
|
2443
2523
|
actorIntent = { tag: "ActorIntentSleep", val: null };
|
|
@@ -2454,9 +2534,11 @@ var Runner = class {
|
|
|
2454
2534
|
generation,
|
|
2455
2535
|
intent: actorIntent
|
|
2456
2536
|
};
|
|
2457
|
-
const eventIndex = this.#nextEventIdx++;
|
|
2458
2537
|
const eventWrapper = {
|
|
2459
|
-
|
|
2538
|
+
checkpoint: {
|
|
2539
|
+
actorId,
|
|
2540
|
+
index: actor.nextEventIdx++
|
|
2541
|
+
},
|
|
2460
2542
|
inner: {
|
|
2461
2543
|
tag: "EventActorIntent",
|
|
2462
2544
|
val: intentEvent
|
|
@@ -2469,6 +2551,8 @@ var Runner = class {
|
|
|
2469
2551
|
});
|
|
2470
2552
|
}
|
|
2471
2553
|
#sendActorStateUpdate(actorId, generation, stateType) {
|
|
2554
|
+
const actor = this.getActor(actorId, generation);
|
|
2555
|
+
if (!actor) return;
|
|
2472
2556
|
let actorState;
|
|
2473
2557
|
if (stateType === "running") {
|
|
2474
2558
|
actorState = { tag: "ActorStateRunning", val: null };
|
|
@@ -2488,9 +2572,11 @@ var Runner = class {
|
|
|
2488
2572
|
generation,
|
|
2489
2573
|
state: actorState
|
|
2490
2574
|
};
|
|
2491
|
-
const eventIndex = this.#nextEventIdx++;
|
|
2492
2575
|
const eventWrapper = {
|
|
2493
|
-
|
|
2576
|
+
checkpoint: {
|
|
2577
|
+
actorId,
|
|
2578
|
+
index: actor.nextEventIdx++
|
|
2579
|
+
},
|
|
2494
2580
|
inner: {
|
|
2495
2581
|
tag: "EventActorStateUpdate",
|
|
2496
2582
|
val: stateUpdateEvent
|
|
@@ -2503,13 +2589,20 @@ var Runner = class {
|
|
|
2503
2589
|
});
|
|
2504
2590
|
}
|
|
2505
2591
|
#sendCommandAcknowledgment() {
|
|
2506
|
-
|
|
2507
|
-
|
|
2592
|
+
const lastCommandCheckpoints = [];
|
|
2593
|
+
for (const [_, actor] of this.#actors) {
|
|
2594
|
+
if (actor.lastCommandIdx < 0) {
|
|
2595
|
+
continue;
|
|
2596
|
+
}
|
|
2597
|
+
lastCommandCheckpoints.push({
|
|
2598
|
+
actorId: actor.actorId,
|
|
2599
|
+
index: actor.lastCommandIdx
|
|
2600
|
+
});
|
|
2508
2601
|
}
|
|
2509
2602
|
this.__sendToServer({
|
|
2510
2603
|
tag: "ToServerAckCommands",
|
|
2511
2604
|
val: {
|
|
2512
|
-
|
|
2605
|
+
lastCommandCheckpoints
|
|
2513
2606
|
}
|
|
2514
2607
|
});
|
|
2515
2608
|
}
|
|
@@ -2743,9 +2836,11 @@ var Runner = class {
|
|
|
2743
2836
|
generation: actor.generation,
|
|
2744
2837
|
alarmTs: alarmTs !== null ? BigInt(alarmTs) : null
|
|
2745
2838
|
};
|
|
2746
|
-
const eventIndex = this.#nextEventIdx++;
|
|
2747
2839
|
const eventWrapper = {
|
|
2748
|
-
|
|
2840
|
+
checkpoint: {
|
|
2841
|
+
actorId,
|
|
2842
|
+
index: actor.nextEventIdx++
|
|
2843
|
+
},
|
|
2749
2844
|
inner: {
|
|
2750
2845
|
tag: "EventActorSetAlarm",
|
|
2751
2846
|
val: alarmEvent
|
|
@@ -2872,7 +2967,8 @@ var Runner = class {
|
|
|
2872
2967
|
const data = protocol.encodeToServerlessServer({
|
|
2873
2968
|
tag: "ToServerlessServerInit",
|
|
2874
2969
|
val: {
|
|
2875
|
-
runnerId: this.runnerId
|
|
2970
|
+
runnerId: this.runnerId,
|
|
2971
|
+
runnerProtocolVersion: PROTOCOL_VERSION
|
|
2876
2972
|
}
|
|
2877
2973
|
});
|
|
2878
2974
|
const buffer = Buffer.alloc(data.length + 2);
|
|
@@ -2897,26 +2993,33 @@ var Runner = class {
|
|
|
2897
2993
|
(_b = this.log) == null ? void 0 : _b.debug({
|
|
2898
2994
|
msg: `Scheduling reconnect attempt ${this.#reconnectAttempt + 1} in ${delay}ms`
|
|
2899
2995
|
});
|
|
2900
|
-
this.#reconnectTimeout = setTimeout(
|
|
2996
|
+
this.#reconnectTimeout = setTimeout(() => {
|
|
2901
2997
|
var _a2;
|
|
2902
2998
|
if (!this.#shutdown) {
|
|
2903
2999
|
this.#reconnectAttempt++;
|
|
2904
3000
|
(_a2 = this.log) == null ? void 0 : _a2.debug({
|
|
2905
3001
|
msg: `Attempting to reconnect (attempt ${this.#reconnectAttempt})...`
|
|
2906
3002
|
});
|
|
2907
|
-
|
|
3003
|
+
this.#openPegboardWebSocket().catch((err) => {
|
|
3004
|
+
var _a3;
|
|
3005
|
+
(_a3 = this.log) == null ? void 0 : _a3.error({
|
|
3006
|
+
msg: "error during websocket reconnection",
|
|
3007
|
+
error: stringifyError(err)
|
|
3008
|
+
});
|
|
3009
|
+
});
|
|
2908
3010
|
}
|
|
2909
3011
|
}, delay);
|
|
2910
3012
|
}
|
|
2911
|
-
#resendUnacknowledgedEvents(
|
|
3013
|
+
#resendUnacknowledgedEvents() {
|
|
2912
3014
|
var _a;
|
|
2913
|
-
const eventsToResend =
|
|
2914
|
-
|
|
2915
|
-
|
|
3015
|
+
const eventsToResend = [];
|
|
3016
|
+
for (const [_, actor] of this.#actors) {
|
|
3017
|
+
eventsToResend.push(...actor.eventHistory);
|
|
3018
|
+
}
|
|
2916
3019
|
if (eventsToResend.length === 0) return;
|
|
2917
3020
|
(_a = this.log) == null ? void 0 : _a.info({
|
|
2918
3021
|
msg: "resending unacknowledged events",
|
|
2919
|
-
|
|
3022
|
+
count: eventsToResend.length
|
|
2920
3023
|
});
|
|
2921
3024
|
this.__sendToServer({
|
|
2922
3025
|
tag: "ToServerEvents",
|
|
@@ -2947,5 +3050,6 @@ var Runner = class {
|
|
|
2947
3050
|
|
|
2948
3051
|
|
|
2949
3052
|
|
|
2950
|
-
|
|
3053
|
+
|
|
3054
|
+
exports.Runner = Runner; exports.RunnerActor = RunnerActor; exports.RunnerShutdownError = RunnerShutdownError; exports.idToStr = idToStr;
|
|
2951
3055
|
//# sourceMappingURL=mod.cjs.map
|