@rivetkit/engine-runner 2.1.5 → 2.1.6-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.d.cts CHANGED
@@ -127,7 +127,6 @@ interface RunnerConfig {
127
127
  namespace: string;
128
128
  totalSlots: number;
129
129
  runnerName: string;
130
- runnerKey: string;
131
130
  prepopulateActorNames: Record<string, {
132
131
  metadata: Record<string, any>;
133
132
  }>;
@@ -233,6 +232,14 @@ interface RunnerConfig {
233
232
  onActorStart: (actorId: string, generation: number, config: ActorConfig) => Promise<void>;
234
233
  onActorStop: (actorId: string, generation: number) => Promise<void>;
235
234
  noAutoShutdown?: boolean;
235
+ /**
236
+ * Debug option to inject artificial latency (in ms) into WebSocket
237
+ * communication. Messages are queued and delivered in order after the
238
+ * configured delay.
239
+ *
240
+ * @experimental For testing only.
241
+ */
242
+ debugLatencyMs?: number;
236
243
  }
237
244
  interface KvListOptions {
238
245
  reverse?: boolean;
@@ -261,6 +268,7 @@ declare class Runner {
261
268
  kvListPrefix(actorId: string, prefix: Uint8Array, options?: KvListOptions): Promise<[Uint8Array, Uint8Array][]>;
262
269
  kvPut(actorId: string, entries: [Uint8Array, Uint8Array][]): Promise<void>;
263
270
  kvDelete(actorId: string, keys: Uint8Array[]): Promise<void>;
271
+ kvDeleteRange(actorId: string, start: Uint8Array, end: Uint8Array): Promise<void>;
264
272
  kvDrop(actorId: string): Promise<void>;
265
273
  setAlarm(actorId: string, alarmTs: number | null, generation?: number): void;
266
274
  clearAlarm(actorId: string, generation?: number): void;
package/dist/mod.d.ts CHANGED
@@ -127,7 +127,6 @@ interface RunnerConfig {
127
127
  namespace: string;
128
128
  totalSlots: number;
129
129
  runnerName: string;
130
- runnerKey: string;
131
130
  prepopulateActorNames: Record<string, {
132
131
  metadata: Record<string, any>;
133
132
  }>;
@@ -233,6 +232,14 @@ interface RunnerConfig {
233
232
  onActorStart: (actorId: string, generation: number, config: ActorConfig) => Promise<void>;
234
233
  onActorStop: (actorId: string, generation: number) => Promise<void>;
235
234
  noAutoShutdown?: boolean;
235
+ /**
236
+ * Debug option to inject artificial latency (in ms) into WebSocket
237
+ * communication. Messages are queued and delivered in order after the
238
+ * configured delay.
239
+ *
240
+ * @experimental For testing only.
241
+ */
242
+ debugLatencyMs?: number;
236
243
  }
237
244
  interface KvListOptions {
238
245
  reverse?: boolean;
@@ -261,6 +268,7 @@ declare class Runner {
261
268
  kvListPrefix(actorId: string, prefix: Uint8Array, options?: KvListOptions): Promise<[Uint8Array, Uint8Array][]>;
262
269
  kvPut(actorId: string, entries: [Uint8Array, Uint8Array][]): Promise<void>;
263
270
  kvDelete(actorId: string, keys: Uint8Array[]): Promise<void>;
271
+ kvDeleteRange(actorId: string, start: Uint8Array, end: Uint8Array): Promise<void>;
264
272
  kvDrop(actorId: string): Promise<void>;
265
273
  setAlarm(actorId: string, alarmTs: number | null, generation?: number): void;
266
274
  clearAlarm(actorId: string, generation?: number): void;
package/dist/mod.js CHANGED
@@ -461,6 +461,10 @@ function stringifyKvRequestData(data) {
461
461
  const { keys } = data.val;
462
462
  return `KvDeleteRequest{keys: ${keys.length}}`;
463
463
  }
464
+ case "KvDeleteRangeRequest": {
465
+ const { start, end } = data.val;
466
+ return `KvDeleteRangeRequest{start: ${stringifyArrayBuffer(start)}, end: ${stringifyArrayBuffer(end)}}`;
467
+ }
464
468
  case "KvDropRequest":
465
469
  return "KvDropRequest";
466
470
  }
@@ -1506,8 +1510,11 @@ async function importWebSocket() {
1506
1510
  }
1507
1511
 
1508
1512
  // src/mod.ts
1513
+ import {
1514
+ v4 as uuidv4
1515
+ } from "uuid";
1509
1516
  var KV_EXPIRE = 3e4;
1510
- var PROTOCOL_VERSION = 6;
1517
+ var PROTOCOL_VERSION = 7;
1511
1518
  var EVENT_BACKLOG_WARN_THRESHOLD = 1e4;
1512
1519
  var SIGNAL_HANDLERS = [];
1513
1520
  var RunnerShutdownError = class extends Error {
@@ -1517,6 +1524,7 @@ var RunnerShutdownError = class extends Error {
1517
1524
  };
1518
1525
  var Runner = class {
1519
1526
  #config;
1527
+ #runnerKey = uuidv4();
1520
1528
  get config() {
1521
1529
  return this.#config;
1522
1530
  }
@@ -1830,6 +1838,9 @@ var Runner = class {
1830
1838
  * - All actors are stopped
1831
1839
  * - The WebSocket connection is closed
1832
1840
  * - The shutdown timeout is reached (120 seconds)
1841
+ *
1842
+ * When changing this timeout, update
1843
+ * website/src/content/docs/actors/versions.mdx (SIGTERM Handling section).
1833
1844
  */
1834
1845
  async #waitForActorsToStop(ws) {
1835
1846
  const shutdownTimeout = 12e4;
@@ -1910,7 +1921,7 @@ var Runner = class {
1910
1921
  get pegboardUrl() {
1911
1922
  const wsEndpoint = this.pegboardEndpoint.replace("http://", "ws://").replace("https://", "wss://");
1912
1923
  const baseUrl = wsEndpoint.endsWith("/") ? wsEndpoint.slice(0, -1) : wsEndpoint;
1913
- return `${baseUrl}/runners/connect?protocol_version=${PROTOCOL_VERSION}&namespace=${encodeURIComponent(this.#config.namespace)}&runner_key=${encodeURIComponent(this.#config.runnerKey)}`;
1924
+ return `${baseUrl}/runners/connect?protocol_version=${PROTOCOL_VERSION}&namespace=${encodeURIComponent(this.#config.namespace)}&runner_key=${encodeURIComponent(this.#runnerKey)}`;
1914
1925
  }
1915
1926
  // MARK: Runner protocol
1916
1927
  async #openPegboardWebSocket() {
@@ -1931,7 +1942,7 @@ var Runner = class {
1931
1942
  msg: "connecting",
1932
1943
  endpoint: this.pegboardEndpoint,
1933
1944
  namespace: this.#config.namespace,
1934
- runnerKey: this.#config.runnerKey,
1945
+ runnerKey: this.#runnerKey,
1935
1946
  hasToken: !!this.config.token
1936
1947
  });
1937
1948
  ws.addEventListener("open", () => {
@@ -2008,6 +2019,7 @@ var Runner = class {
2008
2019
  } else {
2009
2020
  throw new Error(`expected binary data, got ${typeof ev.data}`);
2010
2021
  }
2022
+ await this.#injectLatency();
2011
2023
  const message = protocol.decodeToClient(buf);
2012
2024
  (_a2 = this.log) == null ? void 0 : _a2.debug({
2013
2025
  msg: "received runner message",
@@ -2567,6 +2579,24 @@ var Runner = class {
2567
2579
  };
2568
2580
  await this.#sendKvRequest(actorId, requestData);
2569
2581
  }
2582
+ async kvDeleteRange(actorId, start, end) {
2583
+ const startKey = start.buffer.slice(
2584
+ start.byteOffset,
2585
+ start.byteOffset + start.byteLength
2586
+ );
2587
+ const endKey = end.buffer.slice(
2588
+ end.byteOffset,
2589
+ end.byteOffset + end.byteLength
2590
+ );
2591
+ const requestData = {
2592
+ tag: "KvDeleteRangeRequest",
2593
+ val: {
2594
+ start: startKey,
2595
+ end: endKey
2596
+ }
2597
+ };
2598
+ await this.#sendKvRequest(actorId, requestData);
2599
+ }
2570
2600
  async kvDrop(actorId) {
2571
2601
  const requestData = {
2572
2602
  tag: "KvDropRequest",
@@ -2652,6 +2682,12 @@ var Runner = class {
2652
2682
  if (processedCount > 0) {
2653
2683
  }
2654
2684
  }
2685
+ /** Resolves after the configured debug latency, or immediately if none. */
2686
+ #injectLatency() {
2687
+ const ms = this.#config.debugLatencyMs;
2688
+ if (!ms) return Promise.resolve();
2689
+ return new Promise((resolve) => setTimeout(resolve, ms));
2690
+ }
2655
2691
  /** Asserts WebSocket exists and is ready. */
2656
2692
  getPegboardWebSocketIfReady() {
2657
2693
  if (!!this.#pegboardWebSocket && this.#pegboardWebSocket.readyState === 1) {
@@ -2661,20 +2697,23 @@ var Runner = class {
2661
2697
  }
2662
2698
  }
2663
2699
  __sendToServer(message) {
2664
- var _a, _b;
2700
+ var _a;
2665
2701
  (_a = this.log) == null ? void 0 : _a.debug({
2666
2702
  msg: "sending runner message",
2667
2703
  data: stringifyToServer(message)
2668
2704
  });
2669
2705
  const encoded = protocol.encodeToServer(message);
2670
- const pegboardWebSocket = this.getPegboardWebSocketIfReady();
2671
- if (pegboardWebSocket) {
2672
- pegboardWebSocket.send(encoded);
2673
- } else {
2674
- (_b = this.log) == null ? void 0 : _b.error({
2675
- msg: "WebSocket not available or not open for sending data"
2676
- });
2677
- }
2706
+ this.#injectLatency().then(() => {
2707
+ var _a2;
2708
+ const pegboardWebSocket = this.getPegboardWebSocketIfReady();
2709
+ if (pegboardWebSocket) {
2710
+ pegboardWebSocket.send(encoded);
2711
+ } else {
2712
+ (_a2 = this.log) == null ? void 0 : _a2.error({
2713
+ msg: "WebSocket not available or not open for sending data"
2714
+ });
2715
+ }
2716
+ });
2678
2717
  }
2679
2718
  sendHibernatableWebSocketMessageAck(gatewayId, requestId, index) {
2680
2719
  if (!this.#tunnel)