@rivetkit/engine-runner 2.0.28 → 2.0.29

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/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@rivetkit/engine-runner",
3
- "version": "2.0.28",
3
+ "version": "2.0.29",
4
4
  "type": "module",
5
+ "files": [
6
+ "dist",
7
+ "src",
8
+ "package.json"
9
+ ],
5
10
  "exports": {
6
11
  "import": {
7
12
  "types": "./dist/mod.d.ts",
@@ -16,7 +21,7 @@
16
21
  "uuid": "^12.0.0",
17
22
  "pino": "^9.9.5",
18
23
  "ws": "^8.18.3",
19
- "@rivetkit/engine-runner-protocol": "2.0.28"
24
+ "@rivetkit/engine-runner-protocol": "2.0.29"
20
25
  },
21
26
  "devDependencies": {
22
27
  "@types/node": "^22.18.1",
@@ -1,22 +0,0 @@
1
-
2
- > @rivetkit/engine-runner@2.0.28 build /home/runner/work/rivet/rivet/engine/sdks/typescript/runner
3
- > tsup src/mod.ts
4
-
5
- CLI Building entry: src/mod.ts
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.0
8
- CLI Using tsup config: /home/runner/work/rivet/rivet/engine/sdks/typescript/runner/tsup.config.ts
9
- CLI Target: node16
10
- CLI Cleaning output folder
11
- CJS Build start
12
- ESM Build start
13
- ESM dist/mod.js 93.71 KB
14
- ESM dist/mod.js.map 184.98 KB
15
- ESM ⚡️ Build success in 605ms
16
- CJS dist/mod.cjs 94.95 KB
17
- CJS dist/mod.cjs.map 157.62 KB
18
- CJS ⚡️ Build success in 610ms
19
- DTS Build start
20
- DTS ⚡️ Build success in 3637ms
21
- DTS dist/mod.d.cts 14.77 KB
22
- DTS dist/mod.d.ts 14.77 KB
@@ -1,190 +0,0 @@
1
- // import { Bench } from "tinybench";
2
- // import { Runner } from "@/mod";
3
- // import type { ActorConfig } from "@/mod";
4
- // import {
5
- // createActor,
6
- // destroyActor,
7
- // setupBenchmarkRunner,
8
- // createPromiseResolver,
9
- // RIVET_ENDPOINT,
10
- // } from "./utils.js";
11
- // import { afterEach } from "node:test";
12
- //
13
- // async function runActorLifecycleBenchmark() {
14
- // // Shared state for benchmarks
15
- // let runner: Runner | null = null;
16
- // let namespaceName: string;
17
- // let runnerName: string;
18
- // let createdActors: string[] = [];
19
- // let wakeActorId: string | null = null;
20
- // let stopped: { promise: Promise<void>; resolve: () => void };
21
- // let started: { promise: Promise<void>; resolve: () => void };
22
- //
23
- // const bench = new Bench({
24
- // time: 1000,
25
- // iterations: 10,
26
- // warmupTime: 0,
27
- // warmupIterations: 0,
28
- // throws: true,
29
- // setup: async (task) => {
30
- // // Setup benchmark runner
31
- // console.log("Setting up benchmark runner...");
32
- // stopped = createPromiseResolver<void>();
33
- // started = createPromiseResolver<void>();
34
- //
35
- // const setup = await setupBenchmarkRunner(
36
- // "lifecycle",
37
- // 5054,
38
- // async (
39
- // _actorId: string,
40
- // _generation: number,
41
- // _config: ActorConfig,
42
- // ) => {
43
- // started.resolve();
44
- // },
45
- // async (_actorId: string, _generation: number) => {
46
- // stopped.resolve();
47
- // },
48
- // );
49
- // runner = setup.runner;
50
- // namespaceName = setup.namespaceName;
51
- // runnerName = setup.runnerName;
52
- //
53
- // console.log(
54
- // `Benchmark setup complete. Namespace: ${namespaceName}, Runner: ${runnerName}`,
55
- // );
56
- // },
57
- // teardown: async () => {
58
- // if (runner) {
59
- // await runner.shutdown(true);
60
- // }
61
- //
62
- // // Clean up created actors from creation benchmark
63
- // console.log(
64
- // `Cleaning up ${createdActors.length} actors in ${namespaceName}...`,
65
- // );
66
- // const cleanupActor = createdActors;
67
- // createdActors = [];
68
- // wakeActorId = null;
69
- // for (const actorId of cleanupActor) {
70
- // try {
71
- // await destroyActor(namespaceName, actorId);
72
- // } catch (err) {
73
- // console.warn(`Failed to clean up actor ${actorId}:`, err);
74
- // }
75
- // }
76
- //
77
- // console.log("Benchmark teardown complete!");
78
- // },
79
- // });
80
- //
81
- // bench.add("create actor", async () => {
82
- // const actorResponse = await createActor(
83
- // namespaceName,
84
- // runnerName,
85
- // false,
86
- // );
87
- // const actorId = actorResponse.actor.actor_id;
88
- // createdActors.push(actorId);
89
- //
90
- // // Ping the actor
91
- // const pingResponse = await fetch(`${RIVET_ENDPOINT}/ping`, {
92
- // method: "GET",
93
- // headers: {
94
- // "x-rivet-target": "actor",
95
- // "x-rivet-actor": actorId,
96
- // },
97
- // });
98
- // if (!pingResponse.ok) throw "Request failed";
99
- // });
100
- //
101
- // //bench.add(
102
- // // "wake actor from sleep",
103
- // // async () => {
104
- // // if (!wakeActorId) throw "No wake actor ID";
105
- // //
106
- // // // Ping the actor
107
- // // const pingResponse = await fetch(`${RIVET_ENDPOINT}/ping`, {
108
- // // method: "GET",
109
- // // headers: {
110
- // // "x-rivet-target": "actor",
111
- // // "x-rivet-actor": wakeActorId,
112
- // // },
113
- // // });
114
- // //
115
- // // if (!pingResponse.ok) {
116
- // // console.error(
117
- // // `Ping failed: ${pingResponse.status} ${pingResponse.statusText}`,
118
- // // );
119
- // // const errorText = await pingResponse.text();
120
- // // console.error(`Error response: ${errorText}`);
121
- // // throw `Request failed: ${pingResponse.status} ${pingResponse.statusText}`;
122
- // // }
123
- // // },
124
- // // {
125
- // // beforeEach: async () => {
126
- // // // Reset promise resolvers for this iteration
127
- // // started = createPromiseResolver<void>();
128
- // // stopped = createPromiseResolver<void>();
129
- // //
130
- // // // Create the actor that will be used for wake benchmarking
131
- // // console.log('Creating actor');
132
- // // const wakeActorResponse = await createActor(
133
- // // namespaceName,
134
- // // runnerName,
135
- // // false,
136
- // // "wake-bench-actor",
137
- // // );
138
- // // wakeActorId = wakeActorResponse.actor.actor_id;
139
- // // createdActors.push(wakeActorId!);
140
- // //
141
- // // // Wait for actor to start
142
- // // await started.promise;
143
- // //
144
- // // // Put actor to sleep initially
145
- // // runner!.sleepActor(wakeActorId!);
146
- // // await stopped.promise;
147
- // // },
148
- // // },
149
- // // // TODO(RVT-4979): Add back after sleep cycles fixed
150
- // // //{
151
- // // // beforeAll: async () => {
152
- // // // // Create the actor that will be used for wake benchmarking
153
- // // // console.log("Creating wake actor...");
154
- // // // const wakeActorResponse = await createActor(
155
- // // // namespaceName,
156
- // // // runnerName,
157
- // // // false,
158
- // // // "wake-bench-actor",
159
- // // // );
160
- // // // wakeActorId = wakeActorResponse.actor.actor_id;
161
- // // // createdActors.push(wakeActorId!);
162
- // // //
163
- // // // // Wait for actor to start
164
- // // // await started.promise;
165
- // // // },
166
- // // // beforeEach: async () => {
167
- // // // console.log("Putting actor to sleep...");
168
- // // //
169
- // // // // Put actor to sleep initially
170
- // // // stopped = createPromiseResolver<void>();
171
- // // // runner!.sleepActor(wakeActorId!);
172
- // // // await stopped.promise;
173
- // // // },
174
- // // //},
175
- // //);
176
- //
177
- // // Run the benchmark
178
- // console.log("Running benchmarks...");
179
- // await bench.run();
180
- //
181
- // // Display results
182
- // console.table(bench.table());
183
- //
184
- // console.log("Benchmark complete!");
185
- // }
186
- //
187
- // // Run the benchmark if this file is executed directly
188
- // if (import.meta.url === `file://${process.argv[1]}`) {
189
- // runActorLifecycleBenchmark();
190
- // }
package/benches/utils.ts DELETED
@@ -1,143 +0,0 @@
1
- // import { Runner } from "@/mod";
2
- // import type { RunnerConfig, ActorConfig } from "@/mod";
3
- //
4
- // export const RIVET_ENDPOINT =
5
- // process.env.RIVET_ENDPOINT ?? "http://localhost:6420";
6
- //
7
- // export async function createActor(
8
- // namespaceName: string,
9
- // runnerNameSelector: string,
10
- // durable: boolean,
11
- // actorName: string = "bench-actor",
12
- // ): Promise<any> {
13
- // const response = await fetch(
14
- // `${RIVET_ENDPOINT}/actors?namespace=${namespaceName}`,
15
- // {
16
- // method: "POST",
17
- // headers: {
18
- // "Content-Type": "application/json",
19
- // },
20
- // body: JSON.stringify({
21
- // name: actorName,
22
- // input: btoa("bench-input"),
23
- // runner_name_selector: runnerNameSelector,
24
- // durable,
25
- // }),
26
- // },
27
- // );
28
- //
29
- // if (!response.ok) {
30
- // throw new Error(
31
- // `Failed to create actor: ${response.status} ${response.statusText}\n${await response.text()}`,
32
- // );
33
- // }
34
- //
35
- // return response.json();
36
- // }
37
- //
38
- // export async function destroyActor(
39
- // namespaceName: string,
40
- // actorId: string,
41
- // ): Promise<void> {
42
- // const response = await fetch(
43
- // `${RIVET_ENDPOINT}/actors/${actorId}?namespace=${namespaceName}`,
44
- // {
45
- // method: "DELETE",
46
- // },
47
- // );
48
- //
49
- // if (!response.ok) {
50
- // throw new Error(
51
- // `Failed to delete actor: ${response.status} ${response.statusText}\n${await response.text()}`,
52
- // );
53
- // }
54
- // }
55
- //
56
- // export async function createNamespace(
57
- // name: string,
58
- // displayName: string,
59
- // ): Promise<any> {
60
- // const response = await fetch(`${RIVET_ENDPOINT}/namespaces`, {
61
- // method: "POST",
62
- // headers: {
63
- // "Content-Type": "application/json",
64
- // },
65
- // body: JSON.stringify({
66
- // name,
67
- // display_name: displayName,
68
- // }),
69
- // });
70
- //
71
- // if (!response.ok) {
72
- // console.warn(
73
- // `Failed to create namespace: ${response.status} ${response.statusText}\n${await response.text()}`,
74
- // );
75
- // }
76
- // }
77
- //
78
- // export interface BenchmarkRunnerSetup {
79
- // runner: Runner;
80
- // namespaceName: string;
81
- // runnerName: string;
82
- // }
83
- //
84
- // export async function setupBenchmarkRunner(
85
- // namespaceSuffix: string,
86
- // port: number,
87
- // onActorStart?: (
88
- // actorId: string,
89
- // generation: number,
90
- // config: ActorConfig,
91
- // ) => Promise<void>,
92
- // onActorStop?: (actorId: string, generation: number) => Promise<void>,
93
- // ): Promise<BenchmarkRunnerSetup> {
94
- // const namespaceName = `bench-${crypto.randomUUID().slice(0, 8)}`;
95
- // const runnerName = `bench-runner`;
96
- //
97
- // let runnerStartedResolver: () => void;
98
- // const runnerStarted = new Promise<void>((resolve) => {
99
- // runnerStartedResolver = resolve;
100
- // });
101
- //
102
- // const config: RunnerConfig = {
103
- // version: 1,
104
- // endpoint: RIVET_ENDPOINT,
105
- // namespace: namespaceName,
106
- // addresses: { main: { host: "127.0.0.1", port } },
107
- // totalSlots: 100,
108
- // prepopulateActorNames: [],
109
- // runnerName: runnerName,
110
- // runnerKey: "default",
111
- // onConnected: () => {
112
- // runnerStartedResolver();
113
- // },
114
- // onDisconnected: () => {},
115
- // fetch: async (_actorId: string, request: Request) => {
116
- // return new Response("ok", { status: 200 });
117
- // },
118
- // onActorStart: onActorStart || (async () => {}),
119
- // onActorStop: onActorStop || (async () => {}),
120
- // };
121
- //
122
- // await createNamespace(namespaceName, `Bench ${namespaceSuffix} Namespace`);
123
- // const runner = new Runner(config);
124
- // runner.start();
125
- // await runnerStarted;
126
- //
127
- // return { runner, namespaceName, runnerName };
128
- // }
129
- //
130
- // export function createPromiseResolver<T = void>(): {
131
- // promise: Promise<T>;
132
- // resolve: (value: T) => void;
133
- // reject: (error: any) => void;
134
- // } {
135
- // let resolve: (value: T) => void;
136
- // let reject: (error: any) => void;
137
- // const promise = new Promise<T>((res, rej) => {
138
- // resolve = res;
139
- // reject = rej;
140
- // });
141
- // return { promise, resolve: resolve!, reject: reject! };
142
- // }
143
- //
@@ -1,596 +0,0 @@
1
- // import { describe, it, expect, vi } from "vitest";
2
- // import { Runner } from "@/mod";
3
- // import type { RunnerConfig, ActorConfig } from "@/mod";
4
- // import WebSocket, { type CloseEvent } from "ws";
5
- //
6
- // const RIVET_ENDPOINT = process.env.RIVET_ENDPOINT ?? "http://localhost:6420";
7
- // const RIVET_ENDPOINT_WS = RIVET_ENDPOINT.replace("http://", "ws://").replace(
8
- // "https://",
9
- // "wss://",
10
- // );
11
- //
12
- // async function createActor(
13
- // namespaceName: string,
14
- // runnerNameSelector: string,
15
- // durable: boolean,
16
- // name?: string,
17
- // ): Promise<any> {
18
- // const response = await fetch(
19
- // `${RIVET_ENDPOINT}/actors?namespace=${namespaceName}`,
20
- // {
21
- // method: "POST",
22
- // headers: {
23
- // "Content-Type": "application/json",
24
- // },
25
- // body: JSON.stringify({
26
- // name: name ?? "thingy",
27
- // input: btoa("hello"),
28
- // runner_name_selector: runnerNameSelector,
29
- // durable,
30
- // }),
31
- // },
32
- // );
33
- //
34
- // if (!response.ok) {
35
- // throw new Error(
36
- // `Failed to create actor: ${response.status} ${response.statusText}\n${await response.text()}`,
37
- // );
38
- // }
39
- //
40
- // return response.json();
41
- // }
42
- //
43
- // async function destroyActor(
44
- // namespaceName: string,
45
- // actorId: string,
46
- // ): Promise<void> {
47
- // const response = await fetch(
48
- // `${RIVET_ENDPOINT}/actors/${actorId}?namespace=${namespaceName}`,
49
- // {
50
- // method: "DELETE",
51
- // },
52
- // );
53
- //
54
- // if (!response.ok) {
55
- // throw new Error(
56
- // `Failed to delete actor: ${response.status} ${response.statusText}\n${await response.text()}`,
57
- // );
58
- // }
59
- // }
60
- //
61
- // async function createNamespace(
62
- // name: string,
63
- // displayName: string,
64
- // ): Promise<any> {
65
- // const response = await fetch(`${RIVET_ENDPOINT}/namespaces`, {
66
- // method: "POST",
67
- // headers: {
68
- // "Content-Type": "application/json",
69
- // },
70
- // body: JSON.stringify({
71
- // name,
72
- // display_name: displayName,
73
- // }),
74
- // });
75
- //
76
- // if (!response.ok) {
77
- // console.warn(
78
- // `Failed to create namespace: ${response.status} ${response.statusText}\n${await response.text()}`,
79
- // );
80
- // }
81
- // }
82
- //
83
- // async function getActorNames(namespaceName: string): Promise<any> {
84
- // const response = await fetch(
85
- // `${RIVET_ENDPOINT}/actors/names?namespace=${namespaceName}`,
86
- // {
87
- // method: "GET",
88
- // headers: {
89
- // "Content-Type": "application/json",
90
- // },
91
- // },
92
- // );
93
- //
94
- // if (!response.ok) {
95
- // throw new Error(
96
- // `Failed to get actor names: ${response.status} ${response.statusText}\n${await response.text()}`,
97
- // );
98
- // }
99
- //
100
- // return await response.json();
101
- // }
102
- //
103
- // describe("Runner E2E", () => {
104
- // it("performs end-to-end actor lifecycle", async () => {
105
- // const namespaceName = `test-${Math.floor(Math.random() * 10000)}`;
106
- // const runnerName = "test-runner";
107
- // const prepopulateActorNames: string[] = Array.from(
108
- // { length: 8 },
109
- // () =>
110
- // `actor-${Math.random().toString(36).substring(2, 10)}-${Date.now()}`,
111
- // );
112
- // let runnerStarted = Promise.withResolvers();
113
- // let websocketOpen = Promise.withResolvers();
114
- // let websocketClosed = Promise.withResolvers();
115
- // let runner: Runner | null = null;
116
- // const actorWebSockets = new Map<string, WebSocket>();
117
- //
118
- // // Use objects to hold the current promise resolvers so callbacks always get the latest
119
- // const startedRef = { current: Promise.withResolvers() };
120
- // const stoppedRef = { current: Promise.withResolvers() };
121
- //
122
- // const config: RunnerConfig = {
123
- // version: 1,
124
- // endpoint: RIVET_ENDPOINT,
125
- // namespace: namespaceName,
126
- // addresses: { main: { host: "127.0.0.1", port: 5051 } },
127
- // totalSlots: 100,
128
- // runnerName: runnerName,
129
- // runnerKey: "default",
130
- // prepopulateActorNames,
131
- // onConnected: () => {
132
- // runnerStarted.resolve(undefined);
133
- // },
134
- // onDisconnected: () => { },
135
- // fetch: async (actorId: string, request: Request) => {
136
- // const url = new URL(request.url);
137
- // if (url.pathname === "/ping") {
138
- // // Return the actor ID in response
139
- // return new Response(
140
- // JSON.stringify({
141
- // actorId,
142
- // status: "ok",
143
- // timestamp: Date.now(),
144
- // }),
145
- // {
146
- // status: 200,
147
- // headers: { "Content-Type": "application/json" },
148
- // },
149
- // );
150
- // }
151
- // return new Response("ok", { status: 200 });
152
- // },
153
- // onActorStart: async (
154
- // _actorId: string,
155
- // _generation: number,
156
- // _config: ActorConfig,
157
- // ) => {
158
- // console.log(
159
- // `Actor ${_actorId} started (generation ${_generation})`,
160
- // );
161
- // startedRef.current.resolve(undefined);
162
- // },
163
- // onActorStop: async (_actorId: string, _generation: number) => {
164
- // console.log(
165
- // `Actor ${_actorId} stopped (generation ${_generation})`,
166
- // );
167
- // stoppedRef.current.resolve(undefined);
168
- // },
169
- // websocket: async (
170
- // actorId: string,
171
- // ws: WebSocket,
172
- // request: Request,
173
- // ) => {
174
- // console.log(`WebSocket connected for actor ${actorId}`);
175
- // websocketOpen.resolve(undefined);
176
- // actorWebSockets.set(actorId, ws);
177
- //
178
- // // Echo server - send back any messages received
179
- // ws.on("message", (data) => {
180
- // console.log(
181
- // `WebSocket message from actor ${actorId}:`,
182
- // data.toString(),
183
- // );
184
- // ws.send(`Echo: ${data}`);
185
- // });
186
- //
187
- // ws.on("close", () => {
188
- // console.log(`WebSocket closed for actor ${actorId}`);
189
- // actorWebSockets.delete(actorId);
190
- // websocketClosed.resolve(undefined);
191
- // });
192
- // },
193
- // };
194
- //
195
- // // Create namespace first
196
- // await createNamespace(namespaceName, "Test Namespace");
197
- //
198
- // runner = new Runner(config);
199
- //
200
- // // Check pegboard URL configuration
201
- // expect(runner.pegboardUrl).toBe(
202
- // `${RIVET_ENDPOINT_WS}/v1?namespace=${namespaceName}`,
203
- // );
204
- //
205
- // // Start runner
206
- // runner.start();
207
- //
208
- // // Wait for runner to be ready
209
- // console.log("Waiting runner start...");
210
- // await runnerStarted.promise;
211
- //
212
- // // Check actor names prepopulated
213
- // console.log("Comparing actor names...");
214
- // await vi.waitFor(
215
- // async () => {
216
- // const { names } = await getActorNames(namespaceName);
217
- // expect(names.sort()).toStrictEqual(
218
- // prepopulateActorNames.sort(),
219
- // );
220
- // },
221
- // { interval: 100 },
222
- // );
223
- //
224
- // // Create an actor
225
- // console.log("Creating actor...");
226
- // const actorResponse = await createActor(
227
- // namespaceName,
228
- // runnerName,
229
- // false,
230
- // );
231
- // console.log("Actor created:", actorResponse.actor);
232
- // const actorId = actorResponse.actor.actor_id;
233
- //
234
- // // Wait for actor to start
235
- // console.log("Waiting new actor start...");
236
- // await startedRef.current.promise;
237
- //
238
- // // Ping actor to get actor ID in response (via Guard port)
239
- // console.log("Pinging actor...");
240
- // const actorPingResponse = await fetch(`${RIVET_ENDPOINT}/ping`, {
241
- // method: "GET",
242
- // headers: {
243
- // "x-rivet-target": "actor",
244
- // "x-rivet-actor": actorId,
245
- // },
246
- // });
247
- // expect(actorPingResponse.ok).toBe(true);
248
- // const pingResult = (await actorPingResponse.json()) as any;
249
- // expect(pingResult.actorId).toBe(actorId);
250
- //
251
- // // Test WebSocket connection
252
- // console.log("Testing WebSocket connection...");
253
- // const ws = new WebSocket(`${RIVET_ENDPOINT_WS}/ws`, {
254
- // headers: {
255
- // "x-rivet-target": "actor",
256
- // "x-rivet-actor": actorId,
257
- // },
258
- // });
259
- //
260
- // const testMessage = "Hello, actor!";
261
- // const messagePromise = new Promise<string>((resolve, reject) => {
262
- // ws.once("open", () => {
263
- // console.log("WebSocket connected");
264
- // ws.send(testMessage);
265
- // });
266
- // ws.once("message", (data) => {
267
- // resolve(data.toString());
268
- // });
269
- // ws.once("error", reject);
270
- // });
271
- //
272
- // await websocketOpen.promise;
273
- //
274
- // // Test WebSocket messaging
275
- // console.log("Testing WebSocket messaging...");
276
- // const response = await messagePromise;
277
- // expect(response).toBe(`Echo: ${testMessage}`);
278
- //
279
- // // Close WebSocket for now
280
- // ws.close();
281
- // console.log("Waiting websocket close...");
282
- // await websocketClosed.promise;
283
- //
284
- // await testKv(runner, actorId);
285
- //
286
- // // Sleep and wake actor 3 times in a loop
287
- // for (let i = 1; i <= 3; i++) {
288
- // console.log(`Sleep/wake cycle ${i}/3`);
289
- //
290
- // // Sleep actor
291
- // console.log(`Sleeping actor (cycle ${i})...`);
292
- // stoppedRef.current = Promise.withResolvers();
293
- // runner.sleepActor(actorId);
294
- //
295
- // console.log("Waiting actor sleep...");
296
- // await stoppedRef.current.promise;
297
- //
298
- // // Make network request to wake actor (via Guard)
299
- // console.log(`Waking actor (cycle ${i})...`);
300
- // startedRef.current = Promise.withResolvers();
301
- // const wakeResponse = await fetch(`${RIVET_ENDPOINT}/wake`, {
302
- // method: "GET",
303
- // headers: {
304
- // "x-rivet-target": "actor",
305
- // "x-rivet-actor": actorId,
306
- // },
307
- // });
308
- // console.log(`Wake response status: ${wakeResponse.status}`);
309
- // console.log(`Wake response body: ${await wakeResponse.text()}`);
310
- // expect(wakeResponse.status).toBe(200);
311
- //
312
- // // TODO: Remove this
313
- // // Wait for actor to wake
314
- // console.log("Waiting actor start...");
315
- // await startedRef.current.promise;
316
- // console.log(`Actor started successfully for cycle ${i}`);
317
- //
318
- // await testKvAfterSleep(runner, actorId);
319
- // }
320
- //
321
- // // Sleep and wake actor 3 times in a loop
322
- // for (let i = 1; i <= 3; i++) {
323
- // console.log(`Sleep/wake cycle ${i}/3`);
324
- //
325
- // // Sleep actor
326
- // console.log(`Sleeping actor (cycle ${i})...`);
327
- // stoppedRef.current = Promise.withResolvers();
328
- // runner.sleepActor(actorId);
329
- //
330
- // console.log("Waiting actor sleep...");
331
- // await stoppedRef.current.promise;
332
- //
333
- // // Open websocket to wake actor (via Guard)
334
- // console.log(`Waking actor (cycle ${i})...`);
335
- // startedRef.current = Promise.withResolvers();
336
- // const ws = new WebSocket(`${RIVET_ENDPOINT_WS}/ws`, {
337
- // headers: {
338
- // "x-rivet-target": "actor",
339
- // "x-rivet-actor": actorId,
340
- // },
341
- // });
342
- //
343
- // await new Promise<void>((resolve, reject) => {
344
- // ws.on("open", () => {
345
- // console.log("WebSocket connected for wake test");
346
- // resolve();
347
- // });
348
- // ws.on("error", reject);
349
- // });
350
- //
351
- // // TODO: Remove this
352
- // // Wait for actor to wake
353
- // console.log("Waiting actor start...");
354
- // await startedRef.current.promise;
355
- // console.log(`Actor started successfully for cycle ${i}`);
356
- //
357
- // await testKvAfterSleep(runner, actorId);
358
- // }
359
- //
360
- // // Create a fresh WebSocket connection for destroy testing
361
- // console.log("Creating WebSocket for destroy test...");
362
- // const wsForDestroy = new WebSocket(`${RIVET_ENDPOINT_WS}/ws`, {
363
- // headers: {
364
- // "x-rivet-target": "actor",
365
- // "x-rivet-actor": actorId,
366
- // },
367
- // });
368
- //
369
- // await new Promise<void>((resolve, reject) => {
370
- // wsForDestroy.on("open", () => {
371
- // console.log("WebSocket connected for destroy test");
372
- // resolve();
373
- // });
374
- // wsForDestroy.on("error", reject);
375
- // });
376
- //
377
- // // Test WebSocket closes on actor destroy
378
- // const wsClosePromise = new Promise<void>((resolve) => {
379
- // wsForDestroy.on("close", () => {
380
- // console.log("WebSocket closed after actor destroy");
381
- // resolve();
382
- // });
383
- // });
384
- //
385
- // // Destroy actor
386
- // console.log("Destroying actor...");
387
- // stoppedRef.current = Promise.withResolvers(); // Create new promise for actor destroy
388
- //
389
- // // Start destroy and wait for WebSocket close simultaneously
390
- // const destroyPromise = destroyActor(namespaceName, actorId);
391
- //
392
- // // Wait for WebSocket to close
393
- // console.log("Waiting WS close...");
394
- // await wsClosePromise;
395
- //
396
- // // Ensure destroy API call completed
397
- // await destroyPromise;
398
- // console.log("Destroy API call completed");
399
- //
400
- // // Wait for actor to stop with timeout
401
- // console.log("Waiting actor stopped...");
402
- // await stoppedRef.current.promise;
403
- // console.log("Actor stop callback completed");
404
- //
405
- // // Validate actor is destroyed
406
- // console.log("Validating actor is destroyed...");
407
- // const destroyedPingResponse = await fetch(`${RIVET_ENDPOINT}/ping`, {
408
- // headers: {
409
- // "x-rivet-target": "actor",
410
- // "x-rivet-actor": actorId,
411
- // },
412
- // });
413
- // expect(destroyedPingResponse.status).toBe(404);
414
- //
415
- // // Test WebSocket connection to destroyed actor fails
416
- // console.log("Testing WebSocket to destroyed actor...");
417
- // const wsToDestroyed = new WebSocket(`${RIVET_ENDPOINT_WS}/ws`, {
418
- // headers: {
419
- // "x-rivet-target": "actor",
420
- // "x-rivet-actor": actorId,
421
- // },
422
- // });
423
- //
424
- // console.log(
425
- // "Waiting WS close...",
426
- // );
427
- // const closeCode = await new Promise<number>((resolve, reject) => {
428
- // wsToDestroyed.on("error", (err) => {
429
- // console.log("WebSocket should not have errored");
430
- // reject(err);
431
- // });
432
- // wsToDestroyed.on("close", (code) => {
433
- // console.log("WebSocket closed");
434
- // resolve(code);
435
- // });
436
- // });
437
- // expect(closeCode).toBe(1011);
438
- //
439
- // console.log("E2E test completed successfully!");
440
- //
441
- // // Clean up - stop the runner
442
- // if (runner) {
443
- // await runner.shutdown(false);
444
- // }
445
- // }, 30_000);
446
- // });
447
- //
448
- // async function testKv(runner: Runner, actorId: string) {
449
- // // Test KV operations
450
- // console.log("Testing KV operations...");
451
- //
452
- // // Test kvPut and kvGet
453
- // const testEntries: [Uint8Array, Uint8Array][] = [
454
- // [createTestKey(["user", "123"]), createTestValue("alice")],
455
- // [createTestKey(["user", "456"]), createTestValue("bob")],
456
- // [createTestKey(["config", "theme"]), createTestValue("dark")],
457
- // [createTestKey(["config", "lang"]), createTestValue("en")],
458
- // ];
459
- //
460
- // console.log("Testing kvPut...");
461
- // await runner.kvPut(actorId, testEntries);
462
- //
463
- // console.log("Testing kvGet...");
464
- // const getKeys = testEntries.map(([key, _]) => key);
465
- // const getResult = await runner.kvGet(actorId, getKeys);
466
- //
467
- // expect(getResult.length).toBe(4);
468
- // expect(decodeValue(getResult[0]!)).toBe("alice");
469
- // expect(decodeValue(getResult[1]!)).toBe("bob");
470
- // expect(decodeValue(getResult[2]!)).toBe("dark");
471
- // expect(decodeValue(getResult[3]!)).toBe("en");
472
- //
473
- // // Test getting non-existent key
474
- // const nonExistentResult = await runner.kvGet(actorId, [
475
- // createTestKey(["nonexistent"]),
476
- // ]);
477
- // expect(nonExistentResult[0]).toBe(null);
478
- //
479
- // // Test kvListAll
480
- // console.log("Testing kvListAll...");
481
- // const allEntries = await runner.kvListAll(actorId);
482
- // expect(allEntries.length).toBe(4);
483
- //
484
- // // Verify all entries are present (order may vary)
485
- // const allValues = allEntries.map(([_, value]) => decodeValue(value));
486
- // expect(allValues.sort()).toEqual(["alice", "bob", "dark", "en"]);
487
- //
488
- // // Test kvListAll with limit
489
- // const limitedEntries = await runner.kvListAll(actorId, { limit: 2 });
490
- // expect(limitedEntries.length).toBe(2);
491
- //
492
- // // Test kvListPrefix
493
- // console.log("Testing kvListPrefix...");
494
- // const userEntries = await runner.kvListPrefix(
495
- // actorId,
496
- // createTestKey(["user"]),
497
- // );
498
- // // Note: Prefix queries may not be working as expected on the server side
499
- // // For now, we'll test that the method executes without error
500
- // expect(userEntries.length).toBeGreaterThanOrEqual(0);
501
- //
502
- // const configEntries = await runner.kvListPrefix(
503
- // actorId,
504
- // createTestKey(["config"]),
505
- // );
506
- // expect(configEntries.length).toBeGreaterThanOrEqual(0);
507
- //
508
- // // Test kvListRange
509
- // console.log("Testing kvListRange...");
510
- // const rangeEntries = await runner.kvListRange(
511
- // actorId,
512
- // createTestKey(["config"]),
513
- // createTestKey(["user"]),
514
- // false, // inclusive
515
- // );
516
- // // Range queries may have varying behavior depending on key ordering
517
- // expect(rangeEntries.length).toBeGreaterThanOrEqual(0);
518
- //
519
- // // Test kvDelete
520
- // console.log("Testing kvDelete...");
521
- // const keysToDelete = [createTestKey(["user", "456"])]; // Delete bob
522
- // await runner.kvDelete(actorId, keysToDelete);
523
- //
524
- // // Verify deletion worked
525
- // const afterDeleteResult = await runner.kvGet(actorId, [
526
- // createTestKey(["user", "456"]),
527
- // ]);
528
- // expect(afterDeleteResult[0]).toBe(null);
529
- //
530
- // // Verify other data still exists
531
- // const remainingUserResult = await runner.kvGet(actorId, [
532
- // createTestKey(["user", "123"]),
533
- // ]);
534
- // expect(decodeValue(remainingUserResult[0]!)).toBe("alice");
535
- //
536
- // // Test kvDrop operation before destroy
537
- // console.log("Testing kvDrop...");
538
- // await runner.kvDrop(actorId);
539
- //
540
- // // Verify all data is cleared
541
- // const afterDropData = await runner.kvGet(actorId, [
542
- // createTestKey(["user", "123"]),
543
- // createTestKey(["config", "theme"]),
544
- // createTestKey(["config", "lang"]),
545
- // ]);
546
- // expect(afterDropData[0]).toBe(null);
547
- // expect(afterDropData[1]).toBe(null);
548
- // expect(afterDropData[2]).toBe(null);
549
- //
550
- // // Verify list operations return empty after drop
551
- // const afterDropList = await runner.kvListAll(actorId);
552
- // expect(afterDropList.length).toBe(0);
553
- //
554
- // // Write data to test it exists during a sleep
555
- // console.log("Writing data to live during sleep...");
556
- // await runner.kvPut(actorId, [
557
- // [createTestKey(["user", "789"]), createTestValue("max")],
558
- // ]);
559
- // }
560
- //
561
- // async function testKvAfterSleep(runner: Runner, actorId: string) {
562
- // // Verify data still exists after waking again
563
- // const remainingUserResult = await runner.kvGet(actorId, [
564
- // createTestKey(["user", "789"]),
565
- // ]);
566
- // expect(decodeValue(remainingUserResult[0]!)).toBe("max");
567
- // }
568
- //
569
- // function createTestKey(segments: string[]): Uint8Array {
570
- // return flattenUint8Arrays(segments.map((s) => new TextEncoder().encode(s)));
571
- // }
572
- //
573
- // function createTestValue(value: string): Uint8Array {
574
- // return new TextEncoder().encode(value);
575
- // }
576
- //
577
- // function decodeValue(value: Uint8Array): string {
578
- // return new TextDecoder().decode(value);
579
- // }
580
- //
581
- // function flattenUint8Arrays(arrays: Uint8Array[]): Uint8Array {
582
- // // Calculate total length
583
- // const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
584
- //
585
- // // Create result array
586
- // const result = new Uint8Array(totalLength);
587
- //
588
- // // Copy each array
589
- // let offset = 0;
590
- // for (const arr of arrays) {
591
- // result.set(arr, offset);
592
- // offset += arr.length;
593
- // }
594
- //
595
- // return result;
596
- // }
@@ -1,194 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- wrappingGteU16,
4
- wrappingGtU16,
5
- wrappingLteU16,
6
- wrappingLtU16,
7
- } from "../src/utils";
8
-
9
- describe("wrappingGtU16", () => {
10
- it("should return true when a > b in normal case", () => {
11
- expect(wrappingGtU16(100, 50)).toBe(true);
12
- expect(wrappingGtU16(1000, 999)).toBe(true);
13
- });
14
-
15
- it("should return false when a < b in normal case", () => {
16
- expect(wrappingGtU16(50, 100)).toBe(false);
17
- expect(wrappingGtU16(999, 1000)).toBe(false);
18
- });
19
-
20
- it("should return false when a == b", () => {
21
- expect(wrappingGtU16(100, 100)).toBe(false);
22
- expect(wrappingGtU16(0, 0)).toBe(false);
23
- expect(wrappingGtU16(65535, 65535)).toBe(false);
24
- });
25
-
26
- it("should handle wrapping around u16 max", () => {
27
- // When values wrap around, 1 is "greater than" 65535
28
- expect(wrappingGtU16(1, 65535)).toBe(true);
29
- expect(wrappingGtU16(100, 65500)).toBe(true);
30
- });
31
-
32
- it("should handle edge cases near u16 boundaries", () => {
33
- // 65535 is not greater than 0 (wrapped)
34
- expect(wrappingGtU16(65535, 0)).toBe(false);
35
- // But 0 is greater than 65535 if we consider wrapping
36
- expect(wrappingGtU16(0, 65535)).toBe(true);
37
- });
38
-
39
- it("should handle values at exactly half the range", () => {
40
- // U16_MAX / 2 = 32767.5, so values with distance <= 32767 return true
41
- const lessThanHalf = 32766;
42
- expect(wrappingGtU16(lessThanHalf, 0)).toBe(true);
43
- expect(wrappingGtU16(0, lessThanHalf)).toBe(false);
44
-
45
- // At distance 32767, still less than 32767.5, so comparison returns true
46
- const atHalfDistance = 32767;
47
- expect(wrappingGtU16(atHalfDistance, 0)).toBe(true);
48
- expect(wrappingGtU16(0, atHalfDistance)).toBe(false);
49
-
50
- // At distance 32768, greater than 32767.5, so comparison returns false
51
- const overHalfDistance = 32768;
52
- expect(wrappingGtU16(overHalfDistance, 0)).toBe(false);
53
- expect(wrappingGtU16(0, overHalfDistance)).toBe(false);
54
- });
55
- });
56
-
57
- describe("wrappingLtU16", () => {
58
- it("should return true when a < b in normal case", () => {
59
- expect(wrappingLtU16(50, 100)).toBe(true);
60
- expect(wrappingLtU16(999, 1000)).toBe(true);
61
- });
62
-
63
- it("should return false when a > b in normal case", () => {
64
- expect(wrappingLtU16(100, 50)).toBe(false);
65
- expect(wrappingLtU16(1000, 999)).toBe(false);
66
- });
67
-
68
- it("should return false when a == b", () => {
69
- expect(wrappingLtU16(100, 100)).toBe(false);
70
- expect(wrappingLtU16(0, 0)).toBe(false);
71
- expect(wrappingLtU16(65535, 65535)).toBe(false);
72
- });
73
-
74
- it("should handle wrapping around u16 max", () => {
75
- // When values wrap around, 65535 is "less than" 1
76
- expect(wrappingLtU16(65535, 1)).toBe(true);
77
- expect(wrappingLtU16(65500, 100)).toBe(true);
78
- });
79
-
80
- it("should handle edge cases near u16 boundaries", () => {
81
- // 0 is not less than 65535 (wrapped)
82
- expect(wrappingLtU16(0, 65535)).toBe(false);
83
- // But 65535 is less than 0 if we consider wrapping
84
- expect(wrappingLtU16(65535, 0)).toBe(true);
85
- });
86
-
87
- it("should handle values at exactly half the range", () => {
88
- // U16_MAX / 2 = 32767.5, so values with distance <= 32767 return true
89
- const lessThanHalf = 32766;
90
- expect(wrappingLtU16(0, lessThanHalf)).toBe(true);
91
- expect(wrappingLtU16(lessThanHalf, 0)).toBe(false);
92
-
93
- // At distance 32767, still less than 32767.5, so comparison returns true
94
- const atHalfDistance = 32767;
95
- expect(wrappingLtU16(0, atHalfDistance)).toBe(true);
96
- expect(wrappingLtU16(atHalfDistance, 0)).toBe(false);
97
-
98
- // At distance 32768, greater than 32767.5, so comparison returns false
99
- const overHalfDistance = 32768;
100
- expect(wrappingLtU16(0, overHalfDistance)).toBe(false);
101
- expect(wrappingLtU16(overHalfDistance, 0)).toBe(false);
102
- });
103
- });
104
-
105
- describe("wrappingGtU16 and wrappingLtU16 consistency", () => {
106
- it("should be inverse of each other for different values", () => {
107
- const testCases: [number, number][] = [
108
- [100, 200],
109
- [200, 100],
110
- [0, 65535],
111
- [65535, 0],
112
- [1, 65534],
113
- [32767, 32768],
114
- ];
115
-
116
- for (const [a, b] of testCases) {
117
- const gt = wrappingGtU16(a, b);
118
- const lt = wrappingLtU16(a, b);
119
- const eq = a === b;
120
-
121
- // For any pair, exactly one of gt, lt, or eq should be true
122
- expect(Number(gt) + Number(lt) + Number(eq)).toBe(1);
123
- }
124
- });
125
-
126
- it("should satisfy transitivity for sequential values", () => {
127
- // If we have sequential indices, a < b < c should hold
128
- const a = 100;
129
- const b = 101;
130
- const c = 102;
131
-
132
- expect(wrappingLtU16(a, b)).toBe(true);
133
- expect(wrappingLtU16(b, c)).toBe(true);
134
- expect(wrappingLtU16(a, c)).toBe(true);
135
- });
136
-
137
- it("should handle sequence across wrap boundary", () => {
138
- // Test a sequence that wraps: 65534, 65535, 0, 1
139
- const values = [65534, 65535, 0, 1];
140
-
141
- for (let i = 0; i < values.length - 1; i++) {
142
- expect(wrappingLtU16(values[i], values[i + 1])).toBe(true);
143
- expect(wrappingGtU16(values[i + 1], values[i])).toBe(true);
144
- }
145
- });
146
- });
147
-
148
- describe("wrappingGteU16", () => {
149
- it("should return true when a > b", () => {
150
- expect(wrappingGteU16(100, 50)).toBe(true);
151
- expect(wrappingGteU16(1000, 999)).toBe(true);
152
- });
153
-
154
- it("should return true when a == b", () => {
155
- expect(wrappingGteU16(100, 100)).toBe(true);
156
- expect(wrappingGteU16(0, 0)).toBe(true);
157
- expect(wrappingGteU16(65535, 65535)).toBe(true);
158
- });
159
-
160
- it("should return false when a < b", () => {
161
- expect(wrappingGteU16(50, 100)).toBe(false);
162
- expect(wrappingGteU16(999, 1000)).toBe(false);
163
- });
164
-
165
- it("should handle wrapping around u16 max", () => {
166
- expect(wrappingGteU16(1, 65535)).toBe(true);
167
- expect(wrappingGteU16(100, 65500)).toBe(true);
168
- expect(wrappingGteU16(0, 65535)).toBe(true);
169
- });
170
- });
171
-
172
- describe("wrappingLteU16", () => {
173
- it("should return true when a < b", () => {
174
- expect(wrappingLteU16(50, 100)).toBe(true);
175
- expect(wrappingLteU16(999, 1000)).toBe(true);
176
- });
177
-
178
- it("should return true when a == b", () => {
179
- expect(wrappingLteU16(100, 100)).toBe(true);
180
- expect(wrappingLteU16(0, 0)).toBe(true);
181
- expect(wrappingLteU16(65535, 65535)).toBe(true);
182
- });
183
-
184
- it("should return false when a > b", () => {
185
- expect(wrappingLteU16(100, 50)).toBe(false);
186
- expect(wrappingLteU16(1000, 999)).toBe(false);
187
- });
188
-
189
- it("should handle wrapping around u16 max", () => {
190
- expect(wrappingLteU16(65535, 1)).toBe(true);
191
- expect(wrappingLteU16(65500, 100)).toBe(true);
192
- expect(wrappingLteU16(65535, 0)).toBe(true);
193
- });
194
- });
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "../../../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "types": ["node"],
5
- "paths": {
6
- "@/*": ["./src/*"]
7
- }
8
- },
9
- "include": ["src/**/*", "tests/**/*", "benches/**/*"],
10
- "exclude": ["node_modules"]
11
- }
package/tsup.config.ts DELETED
@@ -1,4 +0,0 @@
1
- import { defineConfig } from "tsup";
2
- import defaultConfig from "../../../../tsup.base.ts";
3
-
4
- export default defineConfig(defaultConfig);
package/turbo.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "$schema": "https://turbo.build/schema.json",
3
- "extends": ["//"]
4
- }
package/vitest.config.ts DELETED
@@ -1,16 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { defineConfig } from "vitest/config";
3
- import defaultConfig from "../../../../vitest.base.ts";
4
-
5
- export default defineConfig({
6
- ...defaultConfig,
7
- resolve: {
8
- alias: {
9
- "@": resolve(__dirname, "./src"),
10
- },
11
- },
12
- test: {
13
- ...defaultConfig.test,
14
- include: ["tests/**/*.test.ts"],
15
- },
16
- });