rivetkit 2.0.2 → 2.0.4
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/README.md +3 -5
- package/dist/schemas/actor-persist/v1.ts +225 -0
- package/dist/schemas/client-protocol/v1.ts +435 -0
- package/dist/schemas/file-system-driver/v1.ts +102 -0
- package/dist/tsup/actor/errors.cjs +77 -0
- package/dist/tsup/actor/errors.cjs.map +1 -0
- package/dist/tsup/actor/errors.d.cts +156 -0
- package/dist/tsup/actor/errors.d.ts +156 -0
- package/dist/tsup/actor/errors.js +77 -0
- package/dist/tsup/actor/errors.js.map +1 -0
- package/dist/tsup/chunk-3F2YSRJL.js +117 -0
- package/dist/tsup/chunk-3F2YSRJL.js.map +1 -0
- package/dist/tsup/chunk-4CXBCT26.cjs +250 -0
- package/dist/tsup/chunk-4CXBCT26.cjs.map +1 -0
- package/dist/tsup/chunk-4R73YDN3.cjs +20 -0
- package/dist/tsup/chunk-4R73YDN3.cjs.map +1 -0
- package/dist/tsup/chunk-6LJT3QRL.cjs +539 -0
- package/dist/tsup/chunk-6LJT3QRL.cjs.map +1 -0
- package/dist/tsup/chunk-GICQ3YCU.cjs +1792 -0
- package/dist/tsup/chunk-GICQ3YCU.cjs.map +1 -0
- package/dist/tsup/chunk-H26RP6GD.js +251 -0
- package/dist/tsup/chunk-H26RP6GD.js.map +1 -0
- package/dist/tsup/chunk-HI3HWJRC.js +20 -0
- package/dist/tsup/chunk-HI3HWJRC.js.map +1 -0
- package/dist/tsup/chunk-HLLF4B4Q.js +1792 -0
- package/dist/tsup/chunk-HLLF4B4Q.js.map +1 -0
- package/dist/tsup/chunk-IH6CKNDW.cjs +117 -0
- package/dist/tsup/chunk-IH6CKNDW.cjs.map +1 -0
- package/dist/tsup/chunk-LV2S3OU3.js +250 -0
- package/dist/tsup/chunk-LV2S3OU3.js.map +1 -0
- package/dist/tsup/chunk-LWNKVZG5.cjs +251 -0
- package/dist/tsup/chunk-LWNKVZG5.cjs.map +1 -0
- package/dist/tsup/chunk-NFU2BBT5.js +374 -0
- package/dist/tsup/chunk-NFU2BBT5.js.map +1 -0
- package/dist/tsup/chunk-PQY7KKTL.js +539 -0
- package/dist/tsup/chunk-PQY7KKTL.js.map +1 -0
- package/dist/tsup/chunk-QK72M5JB.js +45 -0
- package/dist/tsup/chunk-QK72M5JB.js.map +1 -0
- package/dist/tsup/chunk-QNNXFOQV.cjs +45 -0
- package/dist/tsup/chunk-QNNXFOQV.cjs.map +1 -0
- package/dist/tsup/chunk-SBHHJ6QS.cjs +374 -0
- package/dist/tsup/chunk-SBHHJ6QS.cjs.map +1 -0
- package/dist/tsup/chunk-TQ62L3X7.js +325 -0
- package/dist/tsup/chunk-TQ62L3X7.js.map +1 -0
- package/dist/tsup/chunk-VO7ZRVVD.cjs +6293 -0
- package/dist/tsup/chunk-VO7ZRVVD.cjs.map +1 -0
- package/dist/tsup/chunk-WHBPJNGW.cjs +325 -0
- package/dist/tsup/chunk-WHBPJNGW.cjs.map +1 -0
- package/dist/tsup/chunk-XJQHKJ4P.js +6293 -0
- package/dist/tsup/chunk-XJQHKJ4P.js.map +1 -0
- package/dist/tsup/client/mod.cjs +32 -0
- package/dist/tsup/client/mod.cjs.map +1 -0
- package/dist/tsup/client/mod.d.cts +20 -0
- package/dist/tsup/client/mod.d.ts +20 -0
- package/dist/tsup/client/mod.js +32 -0
- package/dist/tsup/client/mod.js.map +1 -0
- package/dist/tsup/common/log.cjs +21 -0
- package/dist/tsup/common/log.cjs.map +1 -0
- package/dist/tsup/common/log.d.cts +26 -0
- package/dist/tsup/common/log.d.ts +26 -0
- package/dist/tsup/common/log.js +21 -0
- package/dist/tsup/common/log.js.map +1 -0
- package/dist/tsup/common/websocket.cjs +10 -0
- package/dist/tsup/common/websocket.cjs.map +1 -0
- package/dist/tsup/common/websocket.d.cts +3 -0
- package/dist/tsup/common/websocket.d.ts +3 -0
- package/dist/tsup/common/websocket.js +10 -0
- package/dist/tsup/common/websocket.js.map +1 -0
- package/dist/tsup/common-CXCe7s6i.d.cts +218 -0
- package/dist/tsup/common-CXCe7s6i.d.ts +218 -0
- package/dist/tsup/connection-BI-6UIBJ.d.ts +2087 -0
- package/dist/tsup/connection-Dyd4NLGW.d.cts +2087 -0
- package/dist/tsup/driver-helpers/mod.cjs +30 -0
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
- package/dist/tsup/driver-helpers/mod.d.cts +17 -0
- package/dist/tsup/driver-helpers/mod.d.ts +17 -0
- package/dist/tsup/driver-helpers/mod.js +30 -0
- package/dist/tsup/driver-helpers/mod.js.map +1 -0
- package/dist/tsup/driver-test-suite/mod.cjs +3411 -0
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
- package/dist/tsup/driver-test-suite/mod.d.cts +63 -0
- package/dist/tsup/driver-test-suite/mod.d.ts +63 -0
- package/dist/tsup/driver-test-suite/mod.js +3411 -0
- package/dist/tsup/driver-test-suite/mod.js.map +1 -0
- package/dist/tsup/inspector/mod.cjs +51 -0
- package/dist/tsup/inspector/mod.cjs.map +1 -0
- package/dist/tsup/inspector/mod.d.cts +408 -0
- package/dist/tsup/inspector/mod.d.ts +408 -0
- package/dist/tsup/inspector/mod.js +51 -0
- package/dist/tsup/inspector/mod.js.map +1 -0
- package/dist/tsup/mod.cjs +67 -0
- package/dist/tsup/mod.cjs.map +1 -0
- package/dist/tsup/mod.d.cts +105 -0
- package/dist/tsup/mod.d.ts +105 -0
- package/dist/tsup/mod.js +67 -0
- package/dist/tsup/mod.js.map +1 -0
- package/dist/tsup/router-endpoints-BTe_Rsdn.d.cts +65 -0
- package/dist/tsup/router-endpoints-CBSrKHmo.d.ts +65 -0
- package/dist/tsup/test/mod.cjs +17 -0
- package/dist/tsup/test/mod.cjs.map +1 -0
- package/dist/tsup/test/mod.d.cts +26 -0
- package/dist/tsup/test/mod.d.ts +26 -0
- package/dist/tsup/test/mod.js +17 -0
- package/dist/tsup/test/mod.js.map +1 -0
- package/dist/tsup/utils-fwx3o3K9.d.cts +18 -0
- package/dist/tsup/utils-fwx3o3K9.d.ts +18 -0
- package/dist/tsup/utils.cjs +26 -0
- package/dist/tsup/utils.cjs.map +1 -0
- package/dist/tsup/utils.d.cts +36 -0
- package/dist/tsup/utils.d.ts +36 -0
- package/dist/tsup/utils.js +26 -0
- package/dist/tsup/utils.js.map +1 -0
- package/package.json +208 -5
- package/src/actor/action.ts +178 -0
- package/src/actor/config.ts +497 -0
- package/src/actor/connection.ts +257 -0
- package/src/actor/context.ts +168 -0
- package/src/actor/database.ts +23 -0
- package/src/actor/definition.ts +82 -0
- package/src/actor/driver.ts +84 -0
- package/src/actor/errors.ts +422 -0
- package/src/actor/generic-conn-driver.ts +246 -0
- package/src/actor/instance.ts +1844 -0
- package/src/actor/keys.test.ts +266 -0
- package/src/actor/keys.ts +89 -0
- package/src/actor/log.ts +6 -0
- package/src/actor/mod.ts +108 -0
- package/src/actor/persisted.ts +42 -0
- package/src/actor/protocol/old.ts +297 -0
- package/src/actor/protocol/serde.ts +131 -0
- package/src/actor/router-endpoints.ts +688 -0
- package/src/actor/router.ts +265 -0
- package/src/actor/schedule.ts +17 -0
- package/src/actor/unstable-react.ts +110 -0
- package/src/actor/utils.ts +102 -0
- package/src/client/actor-common.ts +30 -0
- package/src/client/actor-conn.ts +865 -0
- package/src/client/actor-handle.ts +268 -0
- package/src/client/actor-query.ts +65 -0
- package/src/client/client.ts +554 -0
- package/src/client/config.ts +44 -0
- package/src/client/errors.ts +42 -0
- package/src/client/log.ts +5 -0
- package/src/client/mod.ts +60 -0
- package/src/client/raw-utils.ts +149 -0
- package/src/client/test.ts +44 -0
- package/src/client/utils.ts +152 -0
- package/src/common/eventsource-interface.ts +47 -0
- package/src/common/eventsource.ts +80 -0
- package/src/common/fake-event-source.ts +267 -0
- package/src/common/inline-websocket-adapter2.ts +454 -0
- package/src/common/log-levels.ts +27 -0
- package/src/common/log.ts +214 -0
- package/src/common/logfmt.ts +219 -0
- package/src/common/network.ts +2 -0
- package/src/common/router.ts +80 -0
- package/src/common/utils.ts +336 -0
- package/src/common/versioned-data.ts +95 -0
- package/src/common/websocket-interface.ts +49 -0
- package/src/common/websocket.ts +42 -0
- package/src/driver-helpers/mod.ts +22 -0
- package/src/driver-helpers/utils.ts +17 -0
- package/src/driver-test-suite/log.ts +5 -0
- package/src/driver-test-suite/mod.ts +239 -0
- package/src/driver-test-suite/tests/action-features.ts +136 -0
- package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
- package/src/driver-test-suite/tests/actor-conn.ts +349 -0
- package/src/driver-test-suite/tests/actor-driver.ts +25 -0
- package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
- package/src/driver-test-suite/tests/actor-handle.ts +292 -0
- package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
- package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
- package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
- package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
- package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
- package/src/driver-test-suite/tests/actor-state.ts +54 -0
- package/src/driver-test-suite/tests/actor-vars.ts +93 -0
- package/src/driver-test-suite/tests/manager-driver.ts +367 -0
- package/src/driver-test-suite/tests/raw-http-direct-registry.ts +227 -0
- package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
- package/src/driver-test-suite/tests/raw-http.ts +347 -0
- package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +393 -0
- package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
- package/src/driver-test-suite/tests/request-access.ts +230 -0
- package/src/driver-test-suite/utils.ts +71 -0
- package/src/drivers/default.ts +34 -0
- package/src/drivers/engine/actor-driver.ts +369 -0
- package/src/drivers/engine/config.ts +31 -0
- package/src/drivers/engine/kv.ts +3 -0
- package/src/drivers/engine/log.ts +5 -0
- package/src/drivers/engine/mod.ts +35 -0
- package/src/drivers/file-system/actor.ts +91 -0
- package/src/drivers/file-system/global-state.ts +686 -0
- package/src/drivers/file-system/log.ts +5 -0
- package/src/drivers/file-system/manager.ts +329 -0
- package/src/drivers/file-system/mod.ts +48 -0
- package/src/drivers/file-system/utils.ts +109 -0
- package/src/globals.d.ts +6 -0
- package/src/inspector/actor.ts +298 -0
- package/src/inspector/config.ts +88 -0
- package/src/inspector/log.ts +5 -0
- package/src/inspector/manager.ts +86 -0
- package/src/inspector/mod.ts +2 -0
- package/src/inspector/protocol/actor.ts +10 -0
- package/src/inspector/protocol/common.ts +196 -0
- package/src/inspector/protocol/manager.ts +10 -0
- package/src/inspector/protocol/mod.ts +2 -0
- package/src/inspector/utils.ts +76 -0
- package/src/manager/driver.ts +88 -0
- package/src/manager/hono-websocket-adapter.ts +342 -0
- package/src/manager/log.ts +5 -0
- package/src/manager/mod.ts +2 -0
- package/src/manager/protocol/mod.ts +24 -0
- package/src/manager/protocol/query.ts +89 -0
- package/src/manager/router.ts +412 -0
- package/src/manager-api/routes/actors-create.ts +16 -0
- package/src/manager-api/routes/actors-delete.ts +4 -0
- package/src/manager-api/routes/actors-get-by-id.ts +7 -0
- package/src/manager-api/routes/actors-get-or-create-by-id.ts +29 -0
- package/src/manager-api/routes/actors-get.ts +7 -0
- package/src/manager-api/routes/common.ts +18 -0
- package/src/mod.ts +18 -0
- package/src/registry/config.ts +32 -0
- package/src/registry/log.ts +5 -0
- package/src/registry/mod.ts +157 -0
- package/src/registry/run-config.ts +52 -0
- package/src/registry/serve.ts +52 -0
- package/src/remote-manager-driver/actor-http-client.ts +72 -0
- package/src/remote-manager-driver/actor-websocket-client.ts +63 -0
- package/src/remote-manager-driver/api-endpoints.ts +79 -0
- package/src/remote-manager-driver/api-utils.ts +43 -0
- package/src/remote-manager-driver/log.ts +5 -0
- package/src/remote-manager-driver/mod.ts +274 -0
- package/src/remote-manager-driver/ws-proxy.ts +180 -0
- package/src/schemas/actor-persist/mod.ts +1 -0
- package/src/schemas/actor-persist/versioned.ts +25 -0
- package/src/schemas/client-protocol/mod.ts +1 -0
- package/src/schemas/client-protocol/versioned.ts +63 -0
- package/src/schemas/file-system-driver/mod.ts +1 -0
- package/src/schemas/file-system-driver/versioned.ts +28 -0
- package/src/serde.ts +90 -0
- package/src/test/config.ts +16 -0
- package/src/test/log.ts +5 -0
- package/src/test/mod.ts +154 -0
- package/src/utils.ts +172 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import type { DriverTestConfig } from "../mod";
|
|
3
|
+
import { FAKE_TIME, setupDriverTest, waitFor } from "../utils";
|
|
4
|
+
|
|
5
|
+
export function runActorConnTests(driverTestConfig: DriverTestConfig) {
|
|
6
|
+
describe("Actor Connection Tests", () => {
|
|
7
|
+
describe("Connection Methods", () => {
|
|
8
|
+
test("should connect using .get().connect()", async (c) => {
|
|
9
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
10
|
+
|
|
11
|
+
// Create actor
|
|
12
|
+
await client.counter.create(["test-get"]);
|
|
13
|
+
|
|
14
|
+
// Get a handle and connect
|
|
15
|
+
const handle = client.counter.get(["test-get"]);
|
|
16
|
+
const connection = handle.connect();
|
|
17
|
+
|
|
18
|
+
// Verify connection by performing an action
|
|
19
|
+
const count = await connection.increment(5);
|
|
20
|
+
expect(count).toBe(5);
|
|
21
|
+
|
|
22
|
+
// Clean up
|
|
23
|
+
await connection.dispose();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("should connect using .getForId().connect()", async (c) => {
|
|
27
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
28
|
+
|
|
29
|
+
// Create a actor first to get its ID
|
|
30
|
+
const handle = client.counter.getOrCreate(["test-get-for-id"]);
|
|
31
|
+
await handle.increment(3);
|
|
32
|
+
const actorId = await handle.resolve();
|
|
33
|
+
|
|
34
|
+
// Get a new handle using the actor ID and connect
|
|
35
|
+
const idHandle = client.counter.getForId(actorId);
|
|
36
|
+
const connection = idHandle.connect();
|
|
37
|
+
|
|
38
|
+
// Verify connection works and state is preserved
|
|
39
|
+
const count = await connection.getCount();
|
|
40
|
+
expect(count).toBe(3);
|
|
41
|
+
|
|
42
|
+
// Clean up
|
|
43
|
+
await connection.dispose();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("should connect using .getOrCreate().connect()", async (c) => {
|
|
47
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
48
|
+
|
|
49
|
+
// Get or create actor and connect
|
|
50
|
+
const handle = client.counter.getOrCreate(["test-get-or-create"]);
|
|
51
|
+
const connection = handle.connect();
|
|
52
|
+
|
|
53
|
+
// Verify connection works
|
|
54
|
+
const count = await connection.increment(7);
|
|
55
|
+
expect(count).toBe(7);
|
|
56
|
+
|
|
57
|
+
// Clean up
|
|
58
|
+
await connection.dispose();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("should connect using (await create()).connect()", async (c) => {
|
|
62
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
63
|
+
|
|
64
|
+
// Create actor and connect
|
|
65
|
+
const handle = await client.counter.create(["test-create"]);
|
|
66
|
+
const connection = handle.connect();
|
|
67
|
+
|
|
68
|
+
// Verify connection works
|
|
69
|
+
const count = await connection.increment(9);
|
|
70
|
+
expect(count).toBe(9);
|
|
71
|
+
|
|
72
|
+
// Clean up
|
|
73
|
+
await connection.dispose();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe("Event Communication", () => {
|
|
78
|
+
test("should mix RPC calls and WebSocket events", async (c) => {
|
|
79
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
80
|
+
|
|
81
|
+
// Create actor
|
|
82
|
+
const handle = client.counter.getOrCreate(["test-mixed-rpc-ws"]);
|
|
83
|
+
const connection = handle.connect();
|
|
84
|
+
|
|
85
|
+
// Set up event listener
|
|
86
|
+
const receivedEvents: number[] = [];
|
|
87
|
+
const receivedEventsPromise = new Promise((resolve) => {
|
|
88
|
+
connection.on("newCount", (count: number) => {
|
|
89
|
+
receivedEvents.push(count);
|
|
90
|
+
if (
|
|
91
|
+
receivedEvents.includes(1) &&
|
|
92
|
+
receivedEvents.includes(6) &&
|
|
93
|
+
receivedEvents.includes(9)
|
|
94
|
+
)
|
|
95
|
+
resolve(undefined);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Send one RPC call over the connection to ensure it's open
|
|
100
|
+
await connection.increment(1);
|
|
101
|
+
|
|
102
|
+
// Now use stateless RPC calls through the handle (no connection)
|
|
103
|
+
// These should still trigger events that the connection receives
|
|
104
|
+
await handle.increment(5);
|
|
105
|
+
await handle.increment(3);
|
|
106
|
+
|
|
107
|
+
// Wait for all events to be received
|
|
108
|
+
await receivedEventsPromise;
|
|
109
|
+
|
|
110
|
+
// Clean up
|
|
111
|
+
await connection.dispose();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("should receive events via broadcast", async (c) => {
|
|
115
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
116
|
+
|
|
117
|
+
// Create actor and connect
|
|
118
|
+
const handle = client.counter.getOrCreate(["test-broadcast"]);
|
|
119
|
+
const connection = handle.connect();
|
|
120
|
+
|
|
121
|
+
// Set up event listener
|
|
122
|
+
const receivedEvents: number[] = [];
|
|
123
|
+
connection.on("newCount", (count: number) => {
|
|
124
|
+
receivedEvents.push(count);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Trigger broadcast events
|
|
128
|
+
await connection.increment(5);
|
|
129
|
+
await connection.increment(3);
|
|
130
|
+
|
|
131
|
+
// Verify events were received
|
|
132
|
+
expect(receivedEvents).toContain(5);
|
|
133
|
+
expect(receivedEvents).toContain(8);
|
|
134
|
+
|
|
135
|
+
// Clean up
|
|
136
|
+
await connection.dispose();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("should handle one-time events with once()", async (c) => {
|
|
140
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
141
|
+
|
|
142
|
+
// Create actor and connect
|
|
143
|
+
const handle = client.counter.getOrCreate(["test-once"]);
|
|
144
|
+
const connection = handle.connect();
|
|
145
|
+
|
|
146
|
+
// Set up one-time event listener
|
|
147
|
+
const receivedEvents: number[] = [];
|
|
148
|
+
connection.once("newCount", (count: number) => {
|
|
149
|
+
receivedEvents.push(count);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Trigger multiple events, but should only receive the first one
|
|
153
|
+
await connection.increment(5);
|
|
154
|
+
await connection.increment(3);
|
|
155
|
+
|
|
156
|
+
// Verify only the first event was received
|
|
157
|
+
expect(receivedEvents).toEqual([5]);
|
|
158
|
+
expect(receivedEvents).not.toContain(8);
|
|
159
|
+
|
|
160
|
+
// Clean up
|
|
161
|
+
await connection.dispose();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("should unsubscribe from events", async (c) => {
|
|
165
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
166
|
+
|
|
167
|
+
// Create actor and connect
|
|
168
|
+
const handle = client.counter.getOrCreate(["test-unsubscribe"]);
|
|
169
|
+
const connection = handle.connect();
|
|
170
|
+
|
|
171
|
+
// Set up event listener with unsubscribe
|
|
172
|
+
const receivedEvents: number[] = [];
|
|
173
|
+
const unsubscribe = connection.on("newCount", (count: number) => {
|
|
174
|
+
receivedEvents.push(count);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Trigger first event
|
|
178
|
+
await connection.increment(5);
|
|
179
|
+
|
|
180
|
+
// Unsubscribe
|
|
181
|
+
unsubscribe();
|
|
182
|
+
|
|
183
|
+
// Trigger second event, should not be received
|
|
184
|
+
await connection.increment(3);
|
|
185
|
+
|
|
186
|
+
// Verify only the first event was received
|
|
187
|
+
expect(receivedEvents).toEqual([5]);
|
|
188
|
+
expect(receivedEvents).not.toContain(8);
|
|
189
|
+
|
|
190
|
+
// Clean up
|
|
191
|
+
await connection.dispose();
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe("Connection Parameters", () => {
|
|
196
|
+
test("should pass connection parameters", async (c) => {
|
|
197
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
198
|
+
|
|
199
|
+
// Create two connections with different params
|
|
200
|
+
const handle1 = client.counterWithParams.getOrCreate(["test-params"], {
|
|
201
|
+
params: { name: "user1" },
|
|
202
|
+
});
|
|
203
|
+
const handle2 = client.counterWithParams.getOrCreate(["test-params"], {
|
|
204
|
+
params: { name: "user2" },
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const conn1 = handle1.connect();
|
|
208
|
+
const conn2 = handle2.connect();
|
|
209
|
+
|
|
210
|
+
// HACK: Call an action to wait for the connections to be established
|
|
211
|
+
await conn1.getInitializers();
|
|
212
|
+
await conn2.getInitializers();
|
|
213
|
+
|
|
214
|
+
// Get initializers to verify connection params were used
|
|
215
|
+
const initializers = await conn1.getInitializers();
|
|
216
|
+
|
|
217
|
+
// Verify both connection names were recorded
|
|
218
|
+
expect(initializers).toContain("user1");
|
|
219
|
+
expect(initializers).toContain("user2");
|
|
220
|
+
|
|
221
|
+
// Clean up
|
|
222
|
+
await conn1.dispose();
|
|
223
|
+
await conn2.dispose();
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
describe("Lifecycle Hooks", () => {
|
|
228
|
+
test("should trigger lifecycle hooks", async (c) => {
|
|
229
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
230
|
+
|
|
231
|
+
// Create and connect
|
|
232
|
+
const connHandle = client.counterWithLifecycle.getOrCreate(
|
|
233
|
+
["test-lifecycle"],
|
|
234
|
+
{
|
|
235
|
+
params: { trackLifecycle: true },
|
|
236
|
+
},
|
|
237
|
+
);
|
|
238
|
+
const connection = connHandle.connect();
|
|
239
|
+
|
|
240
|
+
// Verify lifecycle events were triggered
|
|
241
|
+
const events = await connection.getEvents();
|
|
242
|
+
expect(events).toEqual(["onStart", "onBeforeConnect", "onConnect"]);
|
|
243
|
+
|
|
244
|
+
// Disconnect should trigger onDisconnect
|
|
245
|
+
await connection.dispose();
|
|
246
|
+
|
|
247
|
+
// Reconnect to check if onDisconnect was called
|
|
248
|
+
const handle = client.counterWithLifecycle.getOrCreate([
|
|
249
|
+
"test-lifecycle",
|
|
250
|
+
]);
|
|
251
|
+
const finalEvents = await handle.getEvents();
|
|
252
|
+
expect(finalEvents).toBeOneOf([
|
|
253
|
+
// Still active
|
|
254
|
+
["onStart", "onBeforeConnect", "onConnect", "onDisconnect"],
|
|
255
|
+
// Went to sleep and woke back up
|
|
256
|
+
[
|
|
257
|
+
"onStart",
|
|
258
|
+
"onBeforeConnect",
|
|
259
|
+
"onConnect",
|
|
260
|
+
"onDisconnect",
|
|
261
|
+
"onStart",
|
|
262
|
+
],
|
|
263
|
+
]);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe("Connection Liveness", () => {
|
|
268
|
+
// TODO: KIT-242
|
|
269
|
+
test.skip("should return correct liveness status for connections", async (c) => {
|
|
270
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
271
|
+
|
|
272
|
+
// Create actor and connection
|
|
273
|
+
const handle = client.connLivenessActor.getOrCreate([
|
|
274
|
+
"test-liveness-status",
|
|
275
|
+
]);
|
|
276
|
+
const connA = handle.connect();
|
|
277
|
+
const connB = handle.connect();
|
|
278
|
+
|
|
279
|
+
const connAId = await connA.getConnectionId();
|
|
280
|
+
const connBId = await connB.getConnectionId();
|
|
281
|
+
|
|
282
|
+
// Verify connection works initially
|
|
283
|
+
await connA.increment(5);
|
|
284
|
+
await connB.increment(5);
|
|
285
|
+
|
|
286
|
+
const counter = await handle.getCounter();
|
|
287
|
+
expect(counter).toBe(10);
|
|
288
|
+
|
|
289
|
+
const connectionsStatusBeforeKill =
|
|
290
|
+
await handle.getWsConnectionsLiveness();
|
|
291
|
+
expect(connectionsStatusBeforeKill).toHaveLength(2);
|
|
292
|
+
expect(connectionsStatusBeforeKill).toContainEqual(
|
|
293
|
+
expect.objectContaining({
|
|
294
|
+
id: connAId,
|
|
295
|
+
status: "connected",
|
|
296
|
+
lastSeen: FAKE_TIME.getTime(),
|
|
297
|
+
}),
|
|
298
|
+
);
|
|
299
|
+
expect(connectionsStatusBeforeKill).toContainEqual(
|
|
300
|
+
expect.objectContaining({
|
|
301
|
+
id: connBId,
|
|
302
|
+
status: "connected",
|
|
303
|
+
lastSeen: FAKE_TIME.getTime(),
|
|
304
|
+
}),
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
// Kill one connection
|
|
308
|
+
await handle.kill(connAId); // instead of dispose, we use kill to simulate a disconnection (e.g. network failure)
|
|
309
|
+
// connA.dispose();
|
|
310
|
+
// we killed the connection, but the actor instance does not know about it yet
|
|
311
|
+
// it should still be in the list of connections, but with a status of "reconnecting"
|
|
312
|
+
const connectionsStatusAfterKill =
|
|
313
|
+
await handle.getWsConnectionsLiveness();
|
|
314
|
+
expect(connectionsStatusAfterKill).toEqual(
|
|
315
|
+
expect.arrayContaining([
|
|
316
|
+
expect.objectContaining({
|
|
317
|
+
id: connAId,
|
|
318
|
+
status: "reconnecting",
|
|
319
|
+
lastSeen: FAKE_TIME.getTime(),
|
|
320
|
+
}),
|
|
321
|
+
expect.objectContaining({
|
|
322
|
+
id: connBId,
|
|
323
|
+
status: "connected",
|
|
324
|
+
lastSeen: FAKE_TIME.getTime(),
|
|
325
|
+
}),
|
|
326
|
+
]),
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
// default time to wait for cleanup is 5 seconds
|
|
330
|
+
// check actor options
|
|
331
|
+
await waitFor(driverTestConfig, 5_000);
|
|
332
|
+
|
|
333
|
+
// After timeout, the killed connection should be unavailable, since the manager has cleaned it up
|
|
334
|
+
const connectionsStatusAfterCleanup =
|
|
335
|
+
await handle.getWsConnectionsLiveness();
|
|
336
|
+
expect(connectionsStatusAfterCleanup).not.toContainEqual(
|
|
337
|
+
expect.objectContaining({
|
|
338
|
+
id: connAId,
|
|
339
|
+
}),
|
|
340
|
+
);
|
|
341
|
+
expect(connectionsStatusAfterCleanup).toContainEqual(
|
|
342
|
+
expect.objectContaining({
|
|
343
|
+
id: connBId,
|
|
344
|
+
}),
|
|
345
|
+
);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe } from "vitest";
|
|
2
|
+
import type { DriverTestConfig } from "../mod";
|
|
3
|
+
import { runActorScheduleTests } from "./actor-schedule";
|
|
4
|
+
import { runActorSleepTests } from "./actor-sleep";
|
|
5
|
+
import { runActorStateTests } from "./actor-state";
|
|
6
|
+
|
|
7
|
+
export function runActorDriverTests(driverTestConfig: DriverTestConfig) {
|
|
8
|
+
describe("Actor Driver Tests", () => {
|
|
9
|
+
// Run state persistence tests
|
|
10
|
+
runActorStateTests(driverTestConfig);
|
|
11
|
+
|
|
12
|
+
// Run scheduled alarms tests
|
|
13
|
+
runActorScheduleTests(driverTestConfig);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Actor driver tests that need to be tested for all transport mechanisms. */
|
|
18
|
+
export function runActorDriverTestsWithTransport(
|
|
19
|
+
driverTestConfig: DriverTestConfig,
|
|
20
|
+
) {
|
|
21
|
+
describe("Actor Driver Tests", () => {
|
|
22
|
+
// Run actor sleep tests
|
|
23
|
+
runActorSleepTests(driverTestConfig);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
INTERNAL_ERROR_CODE,
|
|
4
|
+
INTERNAL_ERROR_DESCRIPTION,
|
|
5
|
+
} from "@/actor/errors";
|
|
6
|
+
import { assertUnreachable } from "@/actor/utils";
|
|
7
|
+
import type { DriverTestConfig } from "../mod";
|
|
8
|
+
import { setupDriverTest } from "../utils";
|
|
9
|
+
|
|
10
|
+
export function runActorErrorHandlingTests(driverTestConfig: DriverTestConfig) {
|
|
11
|
+
describe("Actor Error Handling Tests", () => {
|
|
12
|
+
describe("UserError Handling", () => {
|
|
13
|
+
test("should handle simple UserError with message", async (c) => {
|
|
14
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
15
|
+
|
|
16
|
+
// Try to call an action that throws a simple UserError
|
|
17
|
+
const handle = client.errorHandlingActor.getOrCreate();
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await handle.throwSimpleError();
|
|
21
|
+
// If we get here, the test should fail
|
|
22
|
+
expect(true).toBe(false); // This should not be reached
|
|
23
|
+
} catch (error: any) {
|
|
24
|
+
// Verify the error properties
|
|
25
|
+
expect(error.message).toBe("Simple error message");
|
|
26
|
+
// Default code is "user_error" when not specified
|
|
27
|
+
expect(error.code).toBe("user_error");
|
|
28
|
+
// No metadata by default
|
|
29
|
+
expect(error.metadata).toBeUndefined();
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("should handle detailed UserError with code and metadata", async (c) => {
|
|
34
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
35
|
+
|
|
36
|
+
// Try to call an action that throws a detailed UserError
|
|
37
|
+
const handle = client.errorHandlingActor.getOrCreate();
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await handle.throwDetailedError();
|
|
41
|
+
// If we get here, the test should fail
|
|
42
|
+
expect(true).toBe(false); // This should not be reached
|
|
43
|
+
} catch (error: any) {
|
|
44
|
+
// Verify the error properties
|
|
45
|
+
expect(error.message).toBe("Detailed error message");
|
|
46
|
+
expect(error.code).toBe("detailed_error");
|
|
47
|
+
expect(error.metadata).toBeDefined();
|
|
48
|
+
expect(error.metadata.reason).toBe("test");
|
|
49
|
+
expect(error.metadata.timestamp).toBeDefined();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe("Internal Error Handling", () => {
|
|
55
|
+
test("should convert internal errors to safe format", async (c) => {
|
|
56
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
57
|
+
|
|
58
|
+
// Try to call an action that throws an internal error
|
|
59
|
+
const handle = client.errorHandlingActor.getOrCreate();
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
await handle.throwInternalError();
|
|
63
|
+
// If we get here, the test should fail
|
|
64
|
+
expect(true).toBe(false); // This should not be reached
|
|
65
|
+
} catch (error: any) {
|
|
66
|
+
if (driverTestConfig.clientType === "http") {
|
|
67
|
+
// Verify the error is converted to a safe format
|
|
68
|
+
expect(error.code).toBe(INTERNAL_ERROR_CODE);
|
|
69
|
+
// Original error details should not be exposed
|
|
70
|
+
expect(error.message).toBe(INTERNAL_ERROR_DESCRIPTION);
|
|
71
|
+
} else if (driverTestConfig.clientType === "inline") {
|
|
72
|
+
// Verify that original error is preserved
|
|
73
|
+
expect(error.code).toBe(INTERNAL_ERROR_CODE);
|
|
74
|
+
expect(error.message).toBe("This is an internal error");
|
|
75
|
+
} else {
|
|
76
|
+
assertUnreachable(driverTestConfig.clientType);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// TODO: Does not work with fake timers
|
|
83
|
+
describe.skip("Action Timeout", () => {
|
|
84
|
+
test("should handle action timeouts with custom duration", async (c) => {
|
|
85
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
86
|
+
|
|
87
|
+
// Call an action that should time out
|
|
88
|
+
const handle = client.errorHandlingActor.getOrCreate();
|
|
89
|
+
|
|
90
|
+
// This should throw a timeout error because errorHandlingActor has
|
|
91
|
+
// a 500ms timeout and this action tries to run for much longer
|
|
92
|
+
const timeoutPromise = handle.timeoutAction();
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
await timeoutPromise;
|
|
96
|
+
// If we get here, the test failed - timeout didn't occur
|
|
97
|
+
expect(true).toBe(false); // This should not be reached
|
|
98
|
+
} catch (error: any) {
|
|
99
|
+
// Verify it's a timeout error
|
|
100
|
+
expect(error.message).toMatch(/timed out/i);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("should successfully run actions within timeout", async (c) => {
|
|
105
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
106
|
+
|
|
107
|
+
// Call an action with a delay shorter than the timeout
|
|
108
|
+
const handle = client.errorHandlingActor.getOrCreate();
|
|
109
|
+
|
|
110
|
+
// This should succeed because 200ms < 500ms timeout
|
|
111
|
+
const result = await handle.delayedAction(200);
|
|
112
|
+
expect(result).toBe("Completed after 200ms");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("should respect different timeouts for different actors", async (c) => {
|
|
116
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
117
|
+
|
|
118
|
+
// The following actors have different timeout settings:
|
|
119
|
+
// customTimeoutActor: 200ms timeout
|
|
120
|
+
// standardTimeoutActor: default timeout (much longer)
|
|
121
|
+
|
|
122
|
+
// This should fail - 300ms delay with 200ms timeout
|
|
123
|
+
try {
|
|
124
|
+
await client.customTimeoutActor.getOrCreate().slowAction();
|
|
125
|
+
// Should not reach here
|
|
126
|
+
expect(true).toBe(false);
|
|
127
|
+
} catch (error: any) {
|
|
128
|
+
expect(error.message).toMatch(/timed out/i);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// This should succeed - 50ms delay with 200ms timeout
|
|
132
|
+
const quickResult = await client.customTimeoutActor
|
|
133
|
+
.getOrCreate()
|
|
134
|
+
.quickAction();
|
|
135
|
+
expect(quickResult).toBe("Quick action completed");
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe("Error Recovery", () => {
|
|
140
|
+
test("should continue working after errors", async (c) => {
|
|
141
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
142
|
+
|
|
143
|
+
const handle = client.errorHandlingActor.getOrCreate();
|
|
144
|
+
|
|
145
|
+
// Trigger an error
|
|
146
|
+
try {
|
|
147
|
+
await handle.throwSimpleError();
|
|
148
|
+
} catch (error) {
|
|
149
|
+
// Ignore error
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Actor should still work after error
|
|
153
|
+
const result = await handle.successfulAction();
|
|
154
|
+
expect(result).toBe("success");
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|