@rivetkit/engine-runner 2.1.6 → 2.1.7
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 +48 -12
- 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 +48 -12
- package/dist/mod.js.map +1 -1
- package/package.json +2 -2
- package/src/mod.ts +63 -12
- package/src/stringify.ts +4 -0
- package/src/tunnel.ts +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivetkit/engine-runner",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"pino": "^9.9.5",
|
|
23
23
|
"ws": "^8.18.3",
|
|
24
24
|
"@rivetkit/virtual-websocket": "2.0.33",
|
|
25
|
-
"@rivetkit/engine-runner-protocol": "2.1.
|
|
25
|
+
"@rivetkit/engine-runner-protocol": "2.1.7"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.18.1",
|
package/src/mod.ts
CHANGED
|
@@ -12,13 +12,16 @@ import {
|
|
|
12
12
|
unreachable,
|
|
13
13
|
} from "./utils";
|
|
14
14
|
import { importWebSocket } from "./websocket.js";
|
|
15
|
+
import {
|
|
16
|
+
v4 as uuidv4,
|
|
17
|
+
} from "uuid";
|
|
15
18
|
|
|
16
19
|
export type { HibernatingWebSocketMetadata };
|
|
17
20
|
export { RunnerActor, type ActorConfig };
|
|
18
21
|
export { idToStr } from "./utils";
|
|
19
22
|
|
|
20
23
|
const KV_EXPIRE: number = 30_000;
|
|
21
|
-
const PROTOCOL_VERSION: number =
|
|
24
|
+
const PROTOCOL_VERSION: number = 7;
|
|
22
25
|
|
|
23
26
|
/** Warn once the backlog significantly exceeds the server's ack batch size. */
|
|
24
27
|
const EVENT_BACKLOG_WARN_THRESHOLD = 10_000;
|
|
@@ -40,7 +43,6 @@ export interface RunnerConfig {
|
|
|
40
43
|
namespace: string;
|
|
41
44
|
totalSlots: number;
|
|
42
45
|
runnerName: string;
|
|
43
|
-
runnerKey: string;
|
|
44
46
|
prepopulateActorNames: Record<string, { metadata: Record<string, any> }>;
|
|
45
47
|
metadata?: Record<string, any>;
|
|
46
48
|
onConnected: () => void;
|
|
@@ -175,6 +177,15 @@ export interface RunnerConfig {
|
|
|
175
177
|
|
|
176
178
|
onActorStop: (actorId: string, generation: number) => Promise<void>;
|
|
177
179
|
noAutoShutdown?: boolean;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Debug option to inject artificial latency (in ms) into WebSocket
|
|
183
|
+
* communication. Messages are queued and delivered in order after the
|
|
184
|
+
* configured delay.
|
|
185
|
+
*
|
|
186
|
+
* @experimental For testing only.
|
|
187
|
+
*/
|
|
188
|
+
debugLatencyMs?: number;
|
|
178
189
|
}
|
|
179
190
|
|
|
180
191
|
export interface KvListOptions {
|
|
@@ -193,6 +204,7 @@ interface KvRequestEntry {
|
|
|
193
204
|
|
|
194
205
|
export class Runner {
|
|
195
206
|
#config: RunnerConfig;
|
|
207
|
+
#runnerKey: string = uuidv4();
|
|
196
208
|
|
|
197
209
|
get config(): RunnerConfig {
|
|
198
210
|
return this.#config;
|
|
@@ -710,7 +722,7 @@ export class Runner {
|
|
|
710
722
|
const baseUrl = wsEndpoint.endsWith("/")
|
|
711
723
|
? wsEndpoint.slice(0, -1)
|
|
712
724
|
: wsEndpoint;
|
|
713
|
-
return `${baseUrl}/runners/connect?protocol_version=${PROTOCOL_VERSION}&namespace=${encodeURIComponent(this.#config.namespace)}&runner_key=${encodeURIComponent(this.#
|
|
725
|
+
return `${baseUrl}/runners/connect?protocol_version=${PROTOCOL_VERSION}&namespace=${encodeURIComponent(this.#config.namespace)}&runner_key=${encodeURIComponent(this.#runnerKey)}`;
|
|
714
726
|
}
|
|
715
727
|
|
|
716
728
|
// MARK: Runner protocol
|
|
@@ -740,7 +752,7 @@ export class Runner {
|
|
|
740
752
|
msg: "connecting",
|
|
741
753
|
endpoint: this.pegboardEndpoint,
|
|
742
754
|
namespace: this.#config.namespace,
|
|
743
|
-
runnerKey: this.#
|
|
755
|
+
runnerKey: this.#runnerKey,
|
|
744
756
|
hasToken: !!this.config.token,
|
|
745
757
|
});
|
|
746
758
|
|
|
@@ -828,6 +840,8 @@ export class Runner {
|
|
|
828
840
|
throw new Error(`expected binary data, got ${typeof ev.data}`);
|
|
829
841
|
}
|
|
830
842
|
|
|
843
|
+
await this.#injectLatency();
|
|
844
|
+
|
|
831
845
|
// Parse message
|
|
832
846
|
const message = protocol.decodeToClient(buf);
|
|
833
847
|
this.log?.debug({
|
|
@@ -1556,6 +1570,31 @@ export class Runner {
|
|
|
1556
1570
|
await this.#sendKvRequest(actorId, requestData);
|
|
1557
1571
|
}
|
|
1558
1572
|
|
|
1573
|
+
async kvDeleteRange(
|
|
1574
|
+
actorId: string,
|
|
1575
|
+
start: Uint8Array,
|
|
1576
|
+
end: Uint8Array,
|
|
1577
|
+
): Promise<void> {
|
|
1578
|
+
const startKey: protocol.KvKey = start.buffer.slice(
|
|
1579
|
+
start.byteOffset,
|
|
1580
|
+
start.byteOffset + start.byteLength,
|
|
1581
|
+
) as ArrayBuffer;
|
|
1582
|
+
const endKey: protocol.KvKey = end.buffer.slice(
|
|
1583
|
+
end.byteOffset,
|
|
1584
|
+
end.byteOffset + end.byteLength,
|
|
1585
|
+
) as ArrayBuffer;
|
|
1586
|
+
|
|
1587
|
+
const requestData: protocol.KvRequestData = {
|
|
1588
|
+
tag: "KvDeleteRangeRequest",
|
|
1589
|
+
val: {
|
|
1590
|
+
start: startKey,
|
|
1591
|
+
end: endKey,
|
|
1592
|
+
},
|
|
1593
|
+
};
|
|
1594
|
+
|
|
1595
|
+
await this.#sendKvRequest(actorId, requestData);
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1559
1598
|
async kvDrop(actorId: string): Promise<void> {
|
|
1560
1599
|
const requestData: protocol.KvRequestData = {
|
|
1561
1600
|
tag: "KvDropRequest",
|
|
@@ -1667,6 +1706,13 @@ export class Runner {
|
|
|
1667
1706
|
}
|
|
1668
1707
|
}
|
|
1669
1708
|
|
|
1709
|
+
/** Resolves after the configured debug latency, or immediately if none. */
|
|
1710
|
+
#injectLatency(): Promise<void> {
|
|
1711
|
+
const ms = this.#config.debugLatencyMs;
|
|
1712
|
+
if (!ms) return Promise.resolve();
|
|
1713
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1670
1716
|
/** Asserts WebSocket exists and is ready. */
|
|
1671
1717
|
getPegboardWebSocketIfReady(): WebSocket | undefined {
|
|
1672
1718
|
if (
|
|
@@ -1686,14 +1732,19 @@ export class Runner {
|
|
|
1686
1732
|
});
|
|
1687
1733
|
|
|
1688
1734
|
const encoded = protocol.encodeToServer(message);
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
this.
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1735
|
+
|
|
1736
|
+
// Normally synchronous. When debugLatencyMs is set, the send is
|
|
1737
|
+
// deferred but message order is preserved.
|
|
1738
|
+
this.#injectLatency().then(() => {
|
|
1739
|
+
const pegboardWebSocket = this.getPegboardWebSocketIfReady();
|
|
1740
|
+
if (pegboardWebSocket) {
|
|
1741
|
+
pegboardWebSocket.send(encoded);
|
|
1742
|
+
} else {
|
|
1743
|
+
this.log?.error({
|
|
1744
|
+
msg: "WebSocket not available or not open for sending data",
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1697
1748
|
}
|
|
1698
1749
|
|
|
1699
1750
|
sendHibernatableWebSocketMessageAck(
|
package/src/stringify.ts
CHANGED
|
@@ -303,6 +303,10 @@ function stringifyKvRequestData(data: protocol.KvRequestData): string {
|
|
|
303
303
|
const { keys } = data.val;
|
|
304
304
|
return `KvDeleteRequest{keys: ${keys.length}}`;
|
|
305
305
|
}
|
|
306
|
+
case "KvDeleteRangeRequest": {
|
|
307
|
+
const { start, end } = data.val;
|
|
308
|
+
return `KvDeleteRangeRequest{start: ${stringifyArrayBuffer(start)}, end: ${stringifyArrayBuffer(end)}}`;
|
|
309
|
+
}
|
|
306
310
|
case "KvDropRequest":
|
|
307
311
|
return "KvDropRequest";
|
|
308
312
|
}
|
package/src/tunnel.ts
CHANGED
|
@@ -5,11 +5,6 @@ import type {
|
|
|
5
5
|
RequestId,
|
|
6
6
|
} from "@rivetkit/engine-runner-protocol";
|
|
7
7
|
import type { Logger } from "pino";
|
|
8
|
-
import {
|
|
9
|
-
parse as uuidparse,
|
|
10
|
-
stringify as uuidstringify,
|
|
11
|
-
v4 as uuidv4,
|
|
12
|
-
} from "uuid";
|
|
13
8
|
import { type Runner, type RunnerActor, RunnerShutdownError } from "./mod";
|
|
14
9
|
import {
|
|
15
10
|
stringifyToClientTunnelMessageKind,
|