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,239 @@
|
|
|
1
|
+
import { serve as honoServe } from "@hono/node-server";
|
|
2
|
+
import { createNodeWebSocket, type NodeWebSocket } from "@hono/node-ws";
|
|
3
|
+
import { bundleRequire } from "bundle-require";
|
|
4
|
+
import invariant from "invariant";
|
|
5
|
+
import { describe } from "vitest";
|
|
6
|
+
import type { Transport } from "@/client/mod";
|
|
7
|
+
import { createManagerRouter } from "@/manager/router";
|
|
8
|
+
import type { DriverConfig, Registry, RunConfig } from "@/mod";
|
|
9
|
+
import { RunConfigSchema } from "@/registry/run-config";
|
|
10
|
+
import { getPort } from "@/test/mod";
|
|
11
|
+
import { logger } from "./log";
|
|
12
|
+
import { runActionFeaturesTests } from "./tests/action-features";
|
|
13
|
+
import { runActorConnTests } from "./tests/actor-conn";
|
|
14
|
+
import { runActorConnStateTests } from "./tests/actor-conn-state";
|
|
15
|
+
import {
|
|
16
|
+
runActorDriverTests,
|
|
17
|
+
runActorDriverTestsWithTransport,
|
|
18
|
+
} from "./tests/actor-driver";
|
|
19
|
+
import { runActorErrorHandlingTests } from "./tests/actor-error-handling";
|
|
20
|
+
import { runActorHandleTests } from "./tests/actor-handle";
|
|
21
|
+
import { runActorInlineClientTests } from "./tests/actor-inline-client";
|
|
22
|
+
import { runActorInspectorTests } from "./tests/actor-inspector";
|
|
23
|
+
import { runActorMetadataTests } from "./tests/actor-metadata";
|
|
24
|
+
import { runActorOnStateChangeTests } from "./tests/actor-onstatechange";
|
|
25
|
+
import { runActorVarsTests } from "./tests/actor-vars";
|
|
26
|
+
import { runManagerDriverTests } from "./tests/manager-driver";
|
|
27
|
+
import { runRawHttpTests } from "./tests/raw-http";
|
|
28
|
+
import { runRawHttpRequestPropertiesTests } from "./tests/raw-http-request-properties";
|
|
29
|
+
import { runRawWebSocketTests } from "./tests/raw-websocket";
|
|
30
|
+
import { runRequestAccessTests } from "./tests/request-access";
|
|
31
|
+
|
|
32
|
+
export interface SkipTests {
|
|
33
|
+
schedule?: boolean;
|
|
34
|
+
sleep?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface DriverTestConfig {
|
|
38
|
+
/** Deploys an registry and returns the connection endpoint. */
|
|
39
|
+
start(projectDir: string): Promise<DriverDeployOutput>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* If we're testing with an external system, we should use real timers
|
|
43
|
+
* instead of Vitest's mocked timers.
|
|
44
|
+
**/
|
|
45
|
+
useRealTimers?: boolean;
|
|
46
|
+
|
|
47
|
+
/** Cloudflare Workers has some bugs with cleanup. */
|
|
48
|
+
HACK_skipCleanupNet?: boolean;
|
|
49
|
+
|
|
50
|
+
skip?: SkipTests;
|
|
51
|
+
|
|
52
|
+
transport?: Transport;
|
|
53
|
+
|
|
54
|
+
clientType: ClientType;
|
|
55
|
+
|
|
56
|
+
cleanup?: () => Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The type of client to run the test with.
|
|
61
|
+
*
|
|
62
|
+
* The logic for HTTP vs inline is very different, so this helps validate all behavior matches.
|
|
63
|
+
**/
|
|
64
|
+
type ClientType = "http" | "inline";
|
|
65
|
+
|
|
66
|
+
export interface DriverDeployOutput {
|
|
67
|
+
endpoint: string;
|
|
68
|
+
namespace: string;
|
|
69
|
+
runnerName: string;
|
|
70
|
+
|
|
71
|
+
/** Cleans up the test. */
|
|
72
|
+
cleanup(): Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Runs all Vitest tests against the provided drivers. */
|
|
76
|
+
export function runDriverTests(
|
|
77
|
+
driverTestConfigPartial: Omit<DriverTestConfig, "clientType" | "transport">,
|
|
78
|
+
) {
|
|
79
|
+
for (const clientType of ["http", "inline"] as ClientType[]) {
|
|
80
|
+
const driverTestConfig: DriverTestConfig = {
|
|
81
|
+
...driverTestConfigPartial,
|
|
82
|
+
clientType,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
describe(`client type (${clientType})`, () => {
|
|
86
|
+
runActorDriverTests(driverTestConfig);
|
|
87
|
+
runManagerDriverTests(driverTestConfig);
|
|
88
|
+
|
|
89
|
+
for (const transport of ["websocket", "sse"] as Transport[]) {
|
|
90
|
+
describe(`transport (${transport})`, () => {
|
|
91
|
+
runActorConnTests({
|
|
92
|
+
...driverTestConfig,
|
|
93
|
+
transport,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
runActorConnStateTests({ ...driverTestConfig, transport });
|
|
97
|
+
|
|
98
|
+
runRequestAccessTests({ ...driverTestConfig, transport });
|
|
99
|
+
|
|
100
|
+
runActorDriverTestsWithTransport({ ...driverTestConfig, transport });
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
runActorHandleTests(driverTestConfig);
|
|
105
|
+
|
|
106
|
+
runActionFeaturesTests(driverTestConfig);
|
|
107
|
+
|
|
108
|
+
runActorVarsTests(driverTestConfig);
|
|
109
|
+
|
|
110
|
+
runActorMetadataTests(driverTestConfig);
|
|
111
|
+
|
|
112
|
+
runActorOnStateChangeTests(driverTestConfig);
|
|
113
|
+
|
|
114
|
+
runActorErrorHandlingTests(driverTestConfig);
|
|
115
|
+
|
|
116
|
+
runActorInlineClientTests(driverTestConfig);
|
|
117
|
+
|
|
118
|
+
runRawHttpTests(driverTestConfig);
|
|
119
|
+
|
|
120
|
+
runRawHttpRequestPropertiesTests(driverTestConfig);
|
|
121
|
+
|
|
122
|
+
runRawWebSocketTests(driverTestConfig);
|
|
123
|
+
|
|
124
|
+
// TODO: re-expose this once we can have actor queries on the gateway
|
|
125
|
+
// runRawHttpDirectRegistryTests(driverTestConfig);
|
|
126
|
+
|
|
127
|
+
// TODO: re-expose this once we can have actor queries on the gateway
|
|
128
|
+
// runRawWebSocketDirectRegistryTests(driverTestConfig);
|
|
129
|
+
|
|
130
|
+
runActorInspectorTests(driverTestConfig);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Helper function to adapt the drivers to the Node.js runtime for tests.
|
|
137
|
+
*
|
|
138
|
+
* This is helpful for drivers that run in-process as opposed to drivers that rely on external tools.
|
|
139
|
+
*/
|
|
140
|
+
export async function createTestRuntime(
|
|
141
|
+
registryPath: string,
|
|
142
|
+
driverFactory: (registry: Registry<any>) => Promise<{
|
|
143
|
+
rivetEngine?: { endpoint: string; namespace: string; runnerName: string };
|
|
144
|
+
driver: DriverConfig;
|
|
145
|
+
cleanup?: () => Promise<void>;
|
|
146
|
+
}>,
|
|
147
|
+
): Promise<DriverDeployOutput> {
|
|
148
|
+
const {
|
|
149
|
+
mod: { registry },
|
|
150
|
+
} = await bundleRequire<{ registry: Registry<any> }>({
|
|
151
|
+
filepath: registryPath,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// TODO: Find a cleaner way of flagging an registry as test mode (ideally not in the config itself)
|
|
155
|
+
// Force enable test
|
|
156
|
+
registry.config.test.enabled = true;
|
|
157
|
+
|
|
158
|
+
// Build drivers
|
|
159
|
+
const {
|
|
160
|
+
driver,
|
|
161
|
+
cleanup: driverCleanup,
|
|
162
|
+
rivetEngine,
|
|
163
|
+
} = await driverFactory(registry);
|
|
164
|
+
|
|
165
|
+
if (rivetEngine) {
|
|
166
|
+
// TODO: We don't need createTestRuntime fort his
|
|
167
|
+
// Using external Rivet engine
|
|
168
|
+
|
|
169
|
+
const cleanup = async () => {
|
|
170
|
+
await driverCleanup?.();
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
endpoint: rivetEngine.endpoint,
|
|
175
|
+
namespace: rivetEngine.namespace,
|
|
176
|
+
runnerName: rivetEngine.runnerName,
|
|
177
|
+
cleanup,
|
|
178
|
+
};
|
|
179
|
+
} else {
|
|
180
|
+
// Start server for Rivet engine
|
|
181
|
+
|
|
182
|
+
// Build driver config
|
|
183
|
+
// biome-ignore lint/style/useConst: Assigned later
|
|
184
|
+
let upgradeWebSocket: any;
|
|
185
|
+
const config: RunConfig = RunConfigSchema.parse({
|
|
186
|
+
driver,
|
|
187
|
+
getUpgradeWebSocket: () => upgradeWebSocket!,
|
|
188
|
+
inspector: {
|
|
189
|
+
enabled: true,
|
|
190
|
+
token: () => "token",
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Create router
|
|
195
|
+
const managerDriver = driver.manager(registry.config, config);
|
|
196
|
+
const { router } = createManagerRouter(
|
|
197
|
+
registry.config,
|
|
198
|
+
config,
|
|
199
|
+
managerDriver,
|
|
200
|
+
false,
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// Inject WebSocket
|
|
204
|
+
const nodeWebSocket = createNodeWebSocket({ app: router });
|
|
205
|
+
upgradeWebSocket = nodeWebSocket.upgradeWebSocket;
|
|
206
|
+
|
|
207
|
+
// Start server
|
|
208
|
+
const port = await getPort();
|
|
209
|
+
const server = honoServe({
|
|
210
|
+
fetch: router.fetch,
|
|
211
|
+
hostname: "127.0.0.1",
|
|
212
|
+
port,
|
|
213
|
+
});
|
|
214
|
+
invariant(
|
|
215
|
+
nodeWebSocket.injectWebSocket !== undefined,
|
|
216
|
+
"should have injectWebSocket",
|
|
217
|
+
);
|
|
218
|
+
nodeWebSocket.injectWebSocket(server);
|
|
219
|
+
const serverEndpoint = `http://127.0.0.1:${port}`;
|
|
220
|
+
|
|
221
|
+
logger().info({ msg: "test serer listening", port });
|
|
222
|
+
|
|
223
|
+
// Cleanup
|
|
224
|
+
const cleanup = async () => {
|
|
225
|
+
// Stop server
|
|
226
|
+
await new Promise((resolve) => server.close(() => resolve(undefined)));
|
|
227
|
+
|
|
228
|
+
// Extra cleanup
|
|
229
|
+
await driverCleanup?.();
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
endpoint: serverEndpoint,
|
|
234
|
+
namespace: "default",
|
|
235
|
+
runnerName: "rivetkit",
|
|
236
|
+
cleanup,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import type { ActorError } from "@/client/errors";
|
|
3
|
+
import type { DriverTestConfig } from "../mod";
|
|
4
|
+
import { setupDriverTest } from "../utils";
|
|
5
|
+
|
|
6
|
+
export function runActionFeaturesTests(driverTestConfig: DriverTestConfig) {
|
|
7
|
+
describe("Action Features", () => {
|
|
8
|
+
// TODO: These do not work with fake timers
|
|
9
|
+
describe("Action Timeouts", () => {
|
|
10
|
+
const usesFakeTimers = !driverTestConfig.useRealTimers;
|
|
11
|
+
|
|
12
|
+
test("should timeout actions that exceed the configured timeout", async (c) => {
|
|
13
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
14
|
+
|
|
15
|
+
// The quick action should complete successfully
|
|
16
|
+
const quickResult = await client.shortTimeoutActor
|
|
17
|
+
.getOrCreate()
|
|
18
|
+
.quickAction();
|
|
19
|
+
expect(quickResult).toBe("quick response");
|
|
20
|
+
|
|
21
|
+
// The slow action should throw a timeout error
|
|
22
|
+
await expect(
|
|
23
|
+
client.shortTimeoutActor.getOrCreate().slowAction(),
|
|
24
|
+
).rejects.toThrow("Action timed out");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("should respect the default timeout", async (c) => {
|
|
28
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
29
|
+
|
|
30
|
+
// This action should complete within the default timeout
|
|
31
|
+
const result = await client.defaultTimeoutActor
|
|
32
|
+
.getOrCreate()
|
|
33
|
+
.normalAction();
|
|
34
|
+
expect(result).toBe("normal response");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("non-promise action results should not be affected by timeout", async (c) => {
|
|
38
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
39
|
+
|
|
40
|
+
// Synchronous action should not be affected by timeout
|
|
41
|
+
const result = await client.syncTimeoutActor.getOrCreate().syncAction();
|
|
42
|
+
expect(result).toBe("sync response");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("should allow configuring different timeouts for different actors", async (c) => {
|
|
46
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
47
|
+
|
|
48
|
+
// The short timeout actor should fail
|
|
49
|
+
await expect(
|
|
50
|
+
client.shortTimeoutActor.getOrCreate().slowAction(),
|
|
51
|
+
).rejects.toThrow("Action timed out");
|
|
52
|
+
|
|
53
|
+
// The longer timeout actor should succeed
|
|
54
|
+
const result = await client.longTimeoutActor
|
|
55
|
+
.getOrCreate()
|
|
56
|
+
.delayedAction();
|
|
57
|
+
expect(result).toBe("delayed response");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("Action Sync & Async", () => {
|
|
62
|
+
test("should support synchronous actions", async (c) => {
|
|
63
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
64
|
+
|
|
65
|
+
const instance = client.syncActionActor.getOrCreate();
|
|
66
|
+
|
|
67
|
+
// Test increment action
|
|
68
|
+
let result = await instance.increment(5);
|
|
69
|
+
expect(result).toBe(5);
|
|
70
|
+
|
|
71
|
+
result = await instance.increment(3);
|
|
72
|
+
expect(result).toBe(8);
|
|
73
|
+
|
|
74
|
+
// Test getInfo action
|
|
75
|
+
const info = await instance.getInfo();
|
|
76
|
+
expect(info.currentValue).toBe(8);
|
|
77
|
+
expect(typeof info.timestamp).toBe("number");
|
|
78
|
+
|
|
79
|
+
// Test reset action (void return)
|
|
80
|
+
await instance.reset();
|
|
81
|
+
result = await instance.increment(0);
|
|
82
|
+
expect(result).toBe(0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("should support asynchronous actions", async (c) => {
|
|
86
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
87
|
+
|
|
88
|
+
const instance = client.asyncActionActor.getOrCreate();
|
|
89
|
+
|
|
90
|
+
// Test delayed increment
|
|
91
|
+
const result = await instance.delayedIncrement(5);
|
|
92
|
+
expect(result).toBe(5);
|
|
93
|
+
|
|
94
|
+
// Test fetch data
|
|
95
|
+
const data = await instance.fetchData("test-123");
|
|
96
|
+
expect(data.id).toBe("test-123");
|
|
97
|
+
expect(typeof data.timestamp).toBe("number");
|
|
98
|
+
|
|
99
|
+
// Test successful async operation
|
|
100
|
+
const success = await instance.asyncWithError(false);
|
|
101
|
+
expect(success).toBe("Success");
|
|
102
|
+
|
|
103
|
+
// Test error in async operation
|
|
104
|
+
try {
|
|
105
|
+
await instance.asyncWithError(true);
|
|
106
|
+
expect.fail("did not error");
|
|
107
|
+
} catch (error) {
|
|
108
|
+
expect((error as ActorError).message).toBe("Intentional error");
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("should handle promises returned from actions correctly", async (c) => {
|
|
113
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
114
|
+
|
|
115
|
+
const instance = client.promiseActor.getOrCreate();
|
|
116
|
+
|
|
117
|
+
// Test resolved promise
|
|
118
|
+
const resolvedValue = await instance.resolvedPromise();
|
|
119
|
+
expect(resolvedValue).toBe("resolved value");
|
|
120
|
+
|
|
121
|
+
// Test delayed promise
|
|
122
|
+
const delayedValue = await instance.delayedPromise();
|
|
123
|
+
expect(delayedValue).toBe("delayed value");
|
|
124
|
+
|
|
125
|
+
// Test rejected promise
|
|
126
|
+
await expect(instance.rejectedPromise()).rejects.toThrow(
|
|
127
|
+
"promised rejection",
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// Check state was updated by the delayed promise
|
|
131
|
+
const results = await instance.getResults();
|
|
132
|
+
expect(results).toContain("delayed");
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from "vitest";
|
|
2
|
+
import type { DriverTestConfig } from "../mod";
|
|
3
|
+
import { setupDriverTest } from "../utils";
|
|
4
|
+
|
|
5
|
+
export function runActorConnStateTests(driverTestConfig: DriverTestConfig) {
|
|
6
|
+
describe("Actor Connection State Tests", () => {
|
|
7
|
+
describe("Connection State Initialization", () => {
|
|
8
|
+
test("should retrieve connection state", async (c) => {
|
|
9
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
10
|
+
|
|
11
|
+
// Connect to the actor
|
|
12
|
+
const connection = client.connStateActor.getOrCreate().connect();
|
|
13
|
+
|
|
14
|
+
// Get the connection state
|
|
15
|
+
const connState = await connection.getConnectionState();
|
|
16
|
+
|
|
17
|
+
// Verify the connection state structure
|
|
18
|
+
expect(connState.id).toBeDefined();
|
|
19
|
+
expect(connState.username).toBeDefined();
|
|
20
|
+
expect(connState.role).toBeDefined();
|
|
21
|
+
expect(connState.counter).toBeDefined();
|
|
22
|
+
expect(connState.createdAt).toBeDefined();
|
|
23
|
+
|
|
24
|
+
// Clean up
|
|
25
|
+
await connection.dispose();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("should initialize connection state with custom parameters", async (c) => {
|
|
29
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
30
|
+
|
|
31
|
+
// Connect with custom parameters
|
|
32
|
+
const connection = client.connStateActor
|
|
33
|
+
.getOrCreate([], {
|
|
34
|
+
params: {
|
|
35
|
+
username: "testuser",
|
|
36
|
+
role: "admin",
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
.connect();
|
|
40
|
+
|
|
41
|
+
// Get the connection state
|
|
42
|
+
const connState = await connection.getConnectionState();
|
|
43
|
+
|
|
44
|
+
// Verify the connection state was initialized with custom values
|
|
45
|
+
expect(connState.username).toBe("testuser");
|
|
46
|
+
expect(connState.role).toBe("admin");
|
|
47
|
+
|
|
48
|
+
// Clean up
|
|
49
|
+
await connection.dispose();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("Connection State Management", () => {
|
|
54
|
+
test("should maintain unique state for each connection", async (c) => {
|
|
55
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
56
|
+
|
|
57
|
+
// Create multiple connections
|
|
58
|
+
const conn1 = client.connStateActor
|
|
59
|
+
.getOrCreate([], {
|
|
60
|
+
params: { username: "user1" },
|
|
61
|
+
})
|
|
62
|
+
.connect();
|
|
63
|
+
|
|
64
|
+
const conn2 = client.connStateActor
|
|
65
|
+
.getOrCreate([], {
|
|
66
|
+
params: { username: "user2" },
|
|
67
|
+
})
|
|
68
|
+
.connect();
|
|
69
|
+
|
|
70
|
+
// Update connection state for each connection
|
|
71
|
+
await conn1.incrementConnCounter(5);
|
|
72
|
+
await conn2.incrementConnCounter(10);
|
|
73
|
+
|
|
74
|
+
// Get state for each connection
|
|
75
|
+
const state1 = await conn1.getConnectionState();
|
|
76
|
+
const state2 = await conn2.getConnectionState();
|
|
77
|
+
|
|
78
|
+
// Verify states are separate
|
|
79
|
+
expect(state1.counter).toBe(5);
|
|
80
|
+
expect(state2.counter).toBe(10);
|
|
81
|
+
expect(state1.username).toBe("user1");
|
|
82
|
+
expect(state2.username).toBe("user2");
|
|
83
|
+
|
|
84
|
+
// Clean up
|
|
85
|
+
await conn1.dispose();
|
|
86
|
+
await conn2.dispose();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("should track connections in shared state", async (c) => {
|
|
90
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
91
|
+
|
|
92
|
+
// Create two connections
|
|
93
|
+
const handle = client.connStateActor.getOrCreate();
|
|
94
|
+
const conn1 = handle.connect();
|
|
95
|
+
const conn2 = handle.connect();
|
|
96
|
+
|
|
97
|
+
// HACK: Wait for both connections to successfully connect by waiting for a round trip RPC
|
|
98
|
+
await conn1.getConnectionState();
|
|
99
|
+
await conn2.getConnectionState();
|
|
100
|
+
|
|
101
|
+
// Get state1 for reference
|
|
102
|
+
const state1 = await conn1.getConnectionState();
|
|
103
|
+
|
|
104
|
+
// Get connection IDs tracked by the actor
|
|
105
|
+
const connectionIds = await conn1.getConnectionIds();
|
|
106
|
+
|
|
107
|
+
// There should be at least 2 connections tracked
|
|
108
|
+
expect(connectionIds.length).toBeGreaterThanOrEqual(2);
|
|
109
|
+
|
|
110
|
+
// Should include the ID of the first connection
|
|
111
|
+
expect(connectionIds).toContain(state1.id);
|
|
112
|
+
|
|
113
|
+
// Clean up
|
|
114
|
+
await conn1.dispose();
|
|
115
|
+
await conn2.dispose();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("should identify different connections in the same actor", async (c) => {
|
|
119
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
120
|
+
|
|
121
|
+
// Create two connections to the same actor
|
|
122
|
+
const handle = client.connStateActor.getOrCreate();
|
|
123
|
+
const conn1 = handle.connect();
|
|
124
|
+
const conn2 = handle.connect();
|
|
125
|
+
|
|
126
|
+
// HACK: Wait for both connections to successfully connect by waiting for a round trip RPC
|
|
127
|
+
await conn1.getConnectionState();
|
|
128
|
+
await conn2.getConnectionState();
|
|
129
|
+
|
|
130
|
+
// Get all connection states
|
|
131
|
+
const allStates = await conn1.getAllConnectionStates();
|
|
132
|
+
|
|
133
|
+
// Should have at least 2 states
|
|
134
|
+
expect(allStates.length).toBeGreaterThanOrEqual(2);
|
|
135
|
+
|
|
136
|
+
// IDs should be unique
|
|
137
|
+
const ids = allStates.map((state) => state.id);
|
|
138
|
+
const uniqueIds = [...new Set(ids)];
|
|
139
|
+
expect(uniqueIds.length).toBe(ids.length);
|
|
140
|
+
|
|
141
|
+
// Clean up
|
|
142
|
+
await conn1.dispose();
|
|
143
|
+
await conn2.dispose();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe("Connection Lifecycle", () => {
|
|
148
|
+
test("should track connection and disconnection events", async (c) => {
|
|
149
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
150
|
+
|
|
151
|
+
// Create a connection
|
|
152
|
+
const handle = client.connStateActor.getOrCreate();
|
|
153
|
+
const conn = handle.connect();
|
|
154
|
+
|
|
155
|
+
// Get the connection state
|
|
156
|
+
const connState = await conn.getConnectionState();
|
|
157
|
+
|
|
158
|
+
// Verify the connection is tracked
|
|
159
|
+
const connectionIds = await conn.getConnectionIds();
|
|
160
|
+
expect(connectionIds).toContain(connState.id);
|
|
161
|
+
|
|
162
|
+
// Initial disconnection count
|
|
163
|
+
const initialDisconnections = await conn.getDisconnectionCount();
|
|
164
|
+
|
|
165
|
+
// Dispose the connection
|
|
166
|
+
await conn.dispose();
|
|
167
|
+
|
|
168
|
+
// Create a new connection to check the disconnection count
|
|
169
|
+
const newConn = handle.connect();
|
|
170
|
+
|
|
171
|
+
// Verify disconnection was tracked
|
|
172
|
+
await vi.waitFor(async () => {
|
|
173
|
+
const newDisconnections = await newConn.getDisconnectionCount();
|
|
174
|
+
|
|
175
|
+
expect(newDisconnections).toBeGreaterThan(initialDisconnections);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Clean up
|
|
179
|
+
await newConn.dispose();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("should update connection state", async (c) => {
|
|
183
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
184
|
+
|
|
185
|
+
// Create a connection
|
|
186
|
+
const conn = client.connStateActor.getOrCreate().connect();
|
|
187
|
+
|
|
188
|
+
// Get the initial state
|
|
189
|
+
const initialState = await conn.getConnectionState();
|
|
190
|
+
expect(initialState.username).toBe("anonymous");
|
|
191
|
+
|
|
192
|
+
// Update the connection state
|
|
193
|
+
const updatedState = await conn.updateConnection({
|
|
194
|
+
username: "newname",
|
|
195
|
+
role: "moderator",
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Verify the state was updated
|
|
199
|
+
expect(updatedState.username).toBe("newname");
|
|
200
|
+
expect(updatedState.role).toBe("moderator");
|
|
201
|
+
|
|
202
|
+
// Get the state again to verify persistence
|
|
203
|
+
const latestState = await conn.getConnectionState();
|
|
204
|
+
expect(latestState.username).toBe("newname");
|
|
205
|
+
expect(latestState.role).toBe("moderator");
|
|
206
|
+
|
|
207
|
+
// Clean up
|
|
208
|
+
await conn.dispose();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
describe("Connection Communication", () => {
|
|
213
|
+
test("should send messages to specific connections", async (c) => {
|
|
214
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
215
|
+
|
|
216
|
+
// Create two connections
|
|
217
|
+
const handle = client.connStateActor.getOrCreate();
|
|
218
|
+
const conn1 = handle.connect();
|
|
219
|
+
const conn2 = handle.connect();
|
|
220
|
+
|
|
221
|
+
// Get connection states
|
|
222
|
+
const state1 = await conn1.getConnectionState();
|
|
223
|
+
const state2 = await conn2.getConnectionState();
|
|
224
|
+
|
|
225
|
+
// Set up event listener on second connection
|
|
226
|
+
const receivedMessages: any[] = [];
|
|
227
|
+
conn2.on("directMessage", (data) => {
|
|
228
|
+
receivedMessages.push(data);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Send message from first connection to second
|
|
232
|
+
const success = await conn1.sendToConnection(
|
|
233
|
+
state2.id,
|
|
234
|
+
"Hello from conn1",
|
|
235
|
+
);
|
|
236
|
+
expect(success).toBe(true);
|
|
237
|
+
|
|
238
|
+
// Verify message was received
|
|
239
|
+
expect(receivedMessages.length).toBe(1);
|
|
240
|
+
expect(receivedMessages[0].from).toBe(state1.id);
|
|
241
|
+
expect(receivedMessages[0].message).toBe("Hello from conn1");
|
|
242
|
+
|
|
243
|
+
// Clean up
|
|
244
|
+
await conn1.dispose();
|
|
245
|
+
await conn2.dispose();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
}
|