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.
Files changed (246) hide show
  1. package/README.md +3 -5
  2. package/dist/schemas/actor-persist/v1.ts +225 -0
  3. package/dist/schemas/client-protocol/v1.ts +435 -0
  4. package/dist/schemas/file-system-driver/v1.ts +102 -0
  5. package/dist/tsup/actor/errors.cjs +77 -0
  6. package/dist/tsup/actor/errors.cjs.map +1 -0
  7. package/dist/tsup/actor/errors.d.cts +156 -0
  8. package/dist/tsup/actor/errors.d.ts +156 -0
  9. package/dist/tsup/actor/errors.js +77 -0
  10. package/dist/tsup/actor/errors.js.map +1 -0
  11. package/dist/tsup/chunk-3F2YSRJL.js +117 -0
  12. package/dist/tsup/chunk-3F2YSRJL.js.map +1 -0
  13. package/dist/tsup/chunk-4CXBCT26.cjs +250 -0
  14. package/dist/tsup/chunk-4CXBCT26.cjs.map +1 -0
  15. package/dist/tsup/chunk-4R73YDN3.cjs +20 -0
  16. package/dist/tsup/chunk-4R73YDN3.cjs.map +1 -0
  17. package/dist/tsup/chunk-6LJT3QRL.cjs +539 -0
  18. package/dist/tsup/chunk-6LJT3QRL.cjs.map +1 -0
  19. package/dist/tsup/chunk-GICQ3YCU.cjs +1792 -0
  20. package/dist/tsup/chunk-GICQ3YCU.cjs.map +1 -0
  21. package/dist/tsup/chunk-H26RP6GD.js +251 -0
  22. package/dist/tsup/chunk-H26RP6GD.js.map +1 -0
  23. package/dist/tsup/chunk-HI3HWJRC.js +20 -0
  24. package/dist/tsup/chunk-HI3HWJRC.js.map +1 -0
  25. package/dist/tsup/chunk-HLLF4B4Q.js +1792 -0
  26. package/dist/tsup/chunk-HLLF4B4Q.js.map +1 -0
  27. package/dist/tsup/chunk-IH6CKNDW.cjs +117 -0
  28. package/dist/tsup/chunk-IH6CKNDW.cjs.map +1 -0
  29. package/dist/tsup/chunk-LV2S3OU3.js +250 -0
  30. package/dist/tsup/chunk-LV2S3OU3.js.map +1 -0
  31. package/dist/tsup/chunk-LWNKVZG5.cjs +251 -0
  32. package/dist/tsup/chunk-LWNKVZG5.cjs.map +1 -0
  33. package/dist/tsup/chunk-NFU2BBT5.js +374 -0
  34. package/dist/tsup/chunk-NFU2BBT5.js.map +1 -0
  35. package/dist/tsup/chunk-PQY7KKTL.js +539 -0
  36. package/dist/tsup/chunk-PQY7KKTL.js.map +1 -0
  37. package/dist/tsup/chunk-QK72M5JB.js +45 -0
  38. package/dist/tsup/chunk-QK72M5JB.js.map +1 -0
  39. package/dist/tsup/chunk-QNNXFOQV.cjs +45 -0
  40. package/dist/tsup/chunk-QNNXFOQV.cjs.map +1 -0
  41. package/dist/tsup/chunk-SBHHJ6QS.cjs +374 -0
  42. package/dist/tsup/chunk-SBHHJ6QS.cjs.map +1 -0
  43. package/dist/tsup/chunk-TQ62L3X7.js +325 -0
  44. package/dist/tsup/chunk-TQ62L3X7.js.map +1 -0
  45. package/dist/tsup/chunk-VO7ZRVVD.cjs +6293 -0
  46. package/dist/tsup/chunk-VO7ZRVVD.cjs.map +1 -0
  47. package/dist/tsup/chunk-WHBPJNGW.cjs +325 -0
  48. package/dist/tsup/chunk-WHBPJNGW.cjs.map +1 -0
  49. package/dist/tsup/chunk-XJQHKJ4P.js +6293 -0
  50. package/dist/tsup/chunk-XJQHKJ4P.js.map +1 -0
  51. package/dist/tsup/client/mod.cjs +32 -0
  52. package/dist/tsup/client/mod.cjs.map +1 -0
  53. package/dist/tsup/client/mod.d.cts +20 -0
  54. package/dist/tsup/client/mod.d.ts +20 -0
  55. package/dist/tsup/client/mod.js +32 -0
  56. package/dist/tsup/client/mod.js.map +1 -0
  57. package/dist/tsup/common/log.cjs +21 -0
  58. package/dist/tsup/common/log.cjs.map +1 -0
  59. package/dist/tsup/common/log.d.cts +26 -0
  60. package/dist/tsup/common/log.d.ts +26 -0
  61. package/dist/tsup/common/log.js +21 -0
  62. package/dist/tsup/common/log.js.map +1 -0
  63. package/dist/tsup/common/websocket.cjs +10 -0
  64. package/dist/tsup/common/websocket.cjs.map +1 -0
  65. package/dist/tsup/common/websocket.d.cts +3 -0
  66. package/dist/tsup/common/websocket.d.ts +3 -0
  67. package/dist/tsup/common/websocket.js +10 -0
  68. package/dist/tsup/common/websocket.js.map +1 -0
  69. package/dist/tsup/common-CXCe7s6i.d.cts +218 -0
  70. package/dist/tsup/common-CXCe7s6i.d.ts +218 -0
  71. package/dist/tsup/connection-BI-6UIBJ.d.ts +2087 -0
  72. package/dist/tsup/connection-Dyd4NLGW.d.cts +2087 -0
  73. package/dist/tsup/driver-helpers/mod.cjs +30 -0
  74. package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
  75. package/dist/tsup/driver-helpers/mod.d.cts +17 -0
  76. package/dist/tsup/driver-helpers/mod.d.ts +17 -0
  77. package/dist/tsup/driver-helpers/mod.js +30 -0
  78. package/dist/tsup/driver-helpers/mod.js.map +1 -0
  79. package/dist/tsup/driver-test-suite/mod.cjs +3411 -0
  80. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
  81. package/dist/tsup/driver-test-suite/mod.d.cts +63 -0
  82. package/dist/tsup/driver-test-suite/mod.d.ts +63 -0
  83. package/dist/tsup/driver-test-suite/mod.js +3411 -0
  84. package/dist/tsup/driver-test-suite/mod.js.map +1 -0
  85. package/dist/tsup/inspector/mod.cjs +51 -0
  86. package/dist/tsup/inspector/mod.cjs.map +1 -0
  87. package/dist/tsup/inspector/mod.d.cts +408 -0
  88. package/dist/tsup/inspector/mod.d.ts +408 -0
  89. package/dist/tsup/inspector/mod.js +51 -0
  90. package/dist/tsup/inspector/mod.js.map +1 -0
  91. package/dist/tsup/mod.cjs +67 -0
  92. package/dist/tsup/mod.cjs.map +1 -0
  93. package/dist/tsup/mod.d.cts +105 -0
  94. package/dist/tsup/mod.d.ts +105 -0
  95. package/dist/tsup/mod.js +67 -0
  96. package/dist/tsup/mod.js.map +1 -0
  97. package/dist/tsup/router-endpoints-BTe_Rsdn.d.cts +65 -0
  98. package/dist/tsup/router-endpoints-CBSrKHmo.d.ts +65 -0
  99. package/dist/tsup/test/mod.cjs +17 -0
  100. package/dist/tsup/test/mod.cjs.map +1 -0
  101. package/dist/tsup/test/mod.d.cts +26 -0
  102. package/dist/tsup/test/mod.d.ts +26 -0
  103. package/dist/tsup/test/mod.js +17 -0
  104. package/dist/tsup/test/mod.js.map +1 -0
  105. package/dist/tsup/utils-fwx3o3K9.d.cts +18 -0
  106. package/dist/tsup/utils-fwx3o3K9.d.ts +18 -0
  107. package/dist/tsup/utils.cjs +26 -0
  108. package/dist/tsup/utils.cjs.map +1 -0
  109. package/dist/tsup/utils.d.cts +36 -0
  110. package/dist/tsup/utils.d.ts +36 -0
  111. package/dist/tsup/utils.js +26 -0
  112. package/dist/tsup/utils.js.map +1 -0
  113. package/package.json +208 -5
  114. package/src/actor/action.ts +178 -0
  115. package/src/actor/config.ts +497 -0
  116. package/src/actor/connection.ts +257 -0
  117. package/src/actor/context.ts +168 -0
  118. package/src/actor/database.ts +23 -0
  119. package/src/actor/definition.ts +82 -0
  120. package/src/actor/driver.ts +84 -0
  121. package/src/actor/errors.ts +422 -0
  122. package/src/actor/generic-conn-driver.ts +246 -0
  123. package/src/actor/instance.ts +1844 -0
  124. package/src/actor/keys.test.ts +266 -0
  125. package/src/actor/keys.ts +89 -0
  126. package/src/actor/log.ts +6 -0
  127. package/src/actor/mod.ts +108 -0
  128. package/src/actor/persisted.ts +42 -0
  129. package/src/actor/protocol/old.ts +297 -0
  130. package/src/actor/protocol/serde.ts +131 -0
  131. package/src/actor/router-endpoints.ts +688 -0
  132. package/src/actor/router.ts +265 -0
  133. package/src/actor/schedule.ts +17 -0
  134. package/src/actor/unstable-react.ts +110 -0
  135. package/src/actor/utils.ts +102 -0
  136. package/src/client/actor-common.ts +30 -0
  137. package/src/client/actor-conn.ts +865 -0
  138. package/src/client/actor-handle.ts +268 -0
  139. package/src/client/actor-query.ts +65 -0
  140. package/src/client/client.ts +554 -0
  141. package/src/client/config.ts +44 -0
  142. package/src/client/errors.ts +42 -0
  143. package/src/client/log.ts +5 -0
  144. package/src/client/mod.ts +60 -0
  145. package/src/client/raw-utils.ts +149 -0
  146. package/src/client/test.ts +44 -0
  147. package/src/client/utils.ts +152 -0
  148. package/src/common/eventsource-interface.ts +47 -0
  149. package/src/common/eventsource.ts +80 -0
  150. package/src/common/fake-event-source.ts +267 -0
  151. package/src/common/inline-websocket-adapter2.ts +454 -0
  152. package/src/common/log-levels.ts +27 -0
  153. package/src/common/log.ts +214 -0
  154. package/src/common/logfmt.ts +219 -0
  155. package/src/common/network.ts +2 -0
  156. package/src/common/router.ts +80 -0
  157. package/src/common/utils.ts +336 -0
  158. package/src/common/versioned-data.ts +95 -0
  159. package/src/common/websocket-interface.ts +49 -0
  160. package/src/common/websocket.ts +42 -0
  161. package/src/driver-helpers/mod.ts +22 -0
  162. package/src/driver-helpers/utils.ts +17 -0
  163. package/src/driver-test-suite/log.ts +5 -0
  164. package/src/driver-test-suite/mod.ts +239 -0
  165. package/src/driver-test-suite/tests/action-features.ts +136 -0
  166. package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
  167. package/src/driver-test-suite/tests/actor-conn.ts +349 -0
  168. package/src/driver-test-suite/tests/actor-driver.ts +25 -0
  169. package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
  170. package/src/driver-test-suite/tests/actor-handle.ts +292 -0
  171. package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
  172. package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
  173. package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
  174. package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
  175. package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
  176. package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
  177. package/src/driver-test-suite/tests/actor-state.ts +54 -0
  178. package/src/driver-test-suite/tests/actor-vars.ts +93 -0
  179. package/src/driver-test-suite/tests/manager-driver.ts +367 -0
  180. package/src/driver-test-suite/tests/raw-http-direct-registry.ts +227 -0
  181. package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
  182. package/src/driver-test-suite/tests/raw-http.ts +347 -0
  183. package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +393 -0
  184. package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
  185. package/src/driver-test-suite/tests/request-access.ts +230 -0
  186. package/src/driver-test-suite/utils.ts +71 -0
  187. package/src/drivers/default.ts +34 -0
  188. package/src/drivers/engine/actor-driver.ts +369 -0
  189. package/src/drivers/engine/config.ts +31 -0
  190. package/src/drivers/engine/kv.ts +3 -0
  191. package/src/drivers/engine/log.ts +5 -0
  192. package/src/drivers/engine/mod.ts +35 -0
  193. package/src/drivers/file-system/actor.ts +91 -0
  194. package/src/drivers/file-system/global-state.ts +686 -0
  195. package/src/drivers/file-system/log.ts +5 -0
  196. package/src/drivers/file-system/manager.ts +329 -0
  197. package/src/drivers/file-system/mod.ts +48 -0
  198. package/src/drivers/file-system/utils.ts +109 -0
  199. package/src/globals.d.ts +6 -0
  200. package/src/inspector/actor.ts +298 -0
  201. package/src/inspector/config.ts +88 -0
  202. package/src/inspector/log.ts +5 -0
  203. package/src/inspector/manager.ts +86 -0
  204. package/src/inspector/mod.ts +2 -0
  205. package/src/inspector/protocol/actor.ts +10 -0
  206. package/src/inspector/protocol/common.ts +196 -0
  207. package/src/inspector/protocol/manager.ts +10 -0
  208. package/src/inspector/protocol/mod.ts +2 -0
  209. package/src/inspector/utils.ts +76 -0
  210. package/src/manager/driver.ts +88 -0
  211. package/src/manager/hono-websocket-adapter.ts +342 -0
  212. package/src/manager/log.ts +5 -0
  213. package/src/manager/mod.ts +2 -0
  214. package/src/manager/protocol/mod.ts +24 -0
  215. package/src/manager/protocol/query.ts +89 -0
  216. package/src/manager/router.ts +412 -0
  217. package/src/manager-api/routes/actors-create.ts +16 -0
  218. package/src/manager-api/routes/actors-delete.ts +4 -0
  219. package/src/manager-api/routes/actors-get-by-id.ts +7 -0
  220. package/src/manager-api/routes/actors-get-or-create-by-id.ts +29 -0
  221. package/src/manager-api/routes/actors-get.ts +7 -0
  222. package/src/manager-api/routes/common.ts +18 -0
  223. package/src/mod.ts +18 -0
  224. package/src/registry/config.ts +32 -0
  225. package/src/registry/log.ts +5 -0
  226. package/src/registry/mod.ts +157 -0
  227. package/src/registry/run-config.ts +52 -0
  228. package/src/registry/serve.ts +52 -0
  229. package/src/remote-manager-driver/actor-http-client.ts +72 -0
  230. package/src/remote-manager-driver/actor-websocket-client.ts +63 -0
  231. package/src/remote-manager-driver/api-endpoints.ts +79 -0
  232. package/src/remote-manager-driver/api-utils.ts +43 -0
  233. package/src/remote-manager-driver/log.ts +5 -0
  234. package/src/remote-manager-driver/mod.ts +274 -0
  235. package/src/remote-manager-driver/ws-proxy.ts +180 -0
  236. package/src/schemas/actor-persist/mod.ts +1 -0
  237. package/src/schemas/actor-persist/versioned.ts +25 -0
  238. package/src/schemas/client-protocol/mod.ts +1 -0
  239. package/src/schemas/client-protocol/versioned.ts +63 -0
  240. package/src/schemas/file-system-driver/mod.ts +1 -0
  241. package/src/schemas/file-system-driver/versioned.ts +28 -0
  242. package/src/serde.ts +90 -0
  243. package/src/test/config.ts +16 -0
  244. package/src/test/log.ts +5 -0
  245. package/src/test/mod.ts +154 -0
  246. package/src/utils.ts +172 -0
@@ -0,0 +1,95 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import type { DriverTestConfig } from "@/driver-test-suite/mod";
3
+ import { setupDriverTest } from "@/driver-test-suite/utils";
4
+
5
+ export function runActorOnStateChangeTests(driverTestConfig: DriverTestConfig) {
6
+ describe("Actor onStateChange Tests", () => {
7
+ test("triggers onStateChange when state is modified", async (c) => {
8
+ const { client } = await setupDriverTest(c, driverTestConfig);
9
+
10
+ const actor = client.onStateChangeActor.getOrCreate();
11
+
12
+ // Modify state - should trigger onChange
13
+ await actor.setValue(10);
14
+
15
+ // Check that onChange was called
16
+ const changeCount = await actor.getChangeCount();
17
+ expect(changeCount).toBe(1);
18
+ });
19
+
20
+ test("triggers onChange multiple times for multiple state changes", async (c) => {
21
+ const { client } = await setupDriverTest(c, driverTestConfig);
22
+
23
+ const actor = client.onStateChangeActor.getOrCreate();
24
+
25
+ // Modify state multiple times
26
+ await actor.incrementMultiple(3);
27
+
28
+ // Check that onChange was called for each modification
29
+ const changeCount = await actor.getChangeCount();
30
+ expect(changeCount).toBe(3);
31
+ });
32
+
33
+ test("does NOT trigger onChange for read-only actions", async (c) => {
34
+ const { client } = await setupDriverTest(c, driverTestConfig);
35
+
36
+ const actor = client.onStateChangeActor.getOrCreate();
37
+
38
+ // Set initial value
39
+ await actor.setValue(5);
40
+
41
+ // Read value without modifying - should NOT trigger onChange
42
+ const value = await actor.getValue();
43
+ expect(value).toBe(5);
44
+
45
+ // Check that onChange was NOT called
46
+ const changeCount = await actor.getChangeCount();
47
+ expect(changeCount).toBe(1);
48
+ });
49
+
50
+ test("does NOT trigger onChange for computed values", async (c) => {
51
+ const { client } = await setupDriverTest(c, driverTestConfig);
52
+
53
+ const actor = client.onStateChangeActor.getOrCreate();
54
+
55
+ // Set initial value
56
+ await actor.setValue(3);
57
+
58
+ // Check that onChange was called
59
+ {
60
+ const changeCount = await actor.getChangeCount();
61
+ expect(changeCount).toBe(1);
62
+ }
63
+
64
+ // Compute value without modifying state - should NOT trigger onChange
65
+ const doubled = await actor.getDoubled();
66
+ expect(doubled).toBe(6);
67
+
68
+ // Check that onChange was NOT called
69
+ {
70
+ const changeCount = await actor.getChangeCount();
71
+ expect(changeCount).toBe(1);
72
+ }
73
+ });
74
+
75
+ test("simple: connect, call action, dispose does NOT trigger onChange", async (c) => {
76
+ const { client } = await setupDriverTest(c, driverTestConfig);
77
+
78
+ const actor = client.onStateChangeActor.getOrCreate();
79
+
80
+ // Connect to the actor
81
+ const connection = await actor.connect();
82
+
83
+ // Call an action that doesn't modify state
84
+ const value = await connection.getValue();
85
+ expect(value).toBe(0);
86
+
87
+ // Dispose the connection
88
+ await connection.dispose();
89
+
90
+ // Verify that onChange was NOT triggered
91
+ const changeCount = await actor.getChangeCount();
92
+ expect(changeCount).toBe(0);
93
+ });
94
+ });
95
+ }
@@ -0,0 +1,108 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import type { DriverTestConfig } from "../mod";
3
+ import { setupDriverTest, waitFor } from "../utils";
4
+
5
+ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) {
6
+ describe.skipIf(driverTestConfig.skip?.schedule)(
7
+ "Actor Schedule Tests",
8
+ () => {
9
+ describe("Scheduled Alarms", () => {
10
+ test("executes c.schedule.at() with specific timestamp", async (c) => {
11
+ const { client } = await setupDriverTest(c, driverTestConfig);
12
+
13
+ // Create instance
14
+ const scheduled = client.scheduled.getOrCreate();
15
+
16
+ // Schedule a task to run in 100ms using timestamp
17
+ const timestamp = Date.now() + 100;
18
+ await scheduled.scheduleTaskAt(timestamp);
19
+
20
+ // Wait for longer than the scheduled time
21
+ await waitFor(driverTestConfig, 200);
22
+
23
+ // Verify the scheduled task ran
24
+ const lastRun = await scheduled.getLastRun();
25
+ const scheduledCount = await scheduled.getScheduledCount();
26
+
27
+ expect(lastRun).toBeGreaterThan(0);
28
+ expect(scheduledCount).toBe(1);
29
+ });
30
+
31
+ test("executes c.schedule.after() with delay", async (c) => {
32
+ const { client } = await setupDriverTest(c, driverTestConfig);
33
+
34
+ // Create instance
35
+ const scheduled = client.scheduled.getOrCreate();
36
+
37
+ // Schedule a task to run in 100ms using delay
38
+ await scheduled.scheduleTaskAfter(100);
39
+
40
+ // Wait for longer than the scheduled time
41
+ await waitFor(driverTestConfig, 200);
42
+
43
+ // Verify the scheduled task ran
44
+ const lastRun = await scheduled.getLastRun();
45
+ const scheduledCount = await scheduled.getScheduledCount();
46
+
47
+ expect(lastRun).toBeGreaterThan(0);
48
+ expect(scheduledCount).toBe(1);
49
+ });
50
+
51
+ test("scheduled tasks persist across actor restarts", async (c) => {
52
+ const { client } = await setupDriverTest(c, driverTestConfig);
53
+
54
+ // Create instance and schedule
55
+ const scheduled = client.scheduled.getOrCreate();
56
+ await scheduled.scheduleTaskAfter(200);
57
+
58
+ // Wait a little so the schedule is stored but hasn't triggered yet
59
+ await waitFor(driverTestConfig, 100);
60
+
61
+ // Get a new reference to simulate actor restart
62
+ const newInstance = client.scheduled.getOrCreate();
63
+
64
+ // Verify the schedule still exists but hasn't run yet
65
+ const initialCount = await newInstance.getScheduledCount();
66
+ expect(initialCount).toBe(0);
67
+
68
+ // Wait for the scheduled task to execute
69
+ await waitFor(driverTestConfig, 200);
70
+
71
+ // Verify the scheduled task ran after "restart"
72
+ const scheduledCount = await newInstance.getScheduledCount();
73
+ expect(scheduledCount).toBe(1);
74
+ });
75
+
76
+ test("multiple scheduled tasks execute in order", async (c) => {
77
+ const { client } = await setupDriverTest(c, driverTestConfig);
78
+
79
+ // Create instance
80
+ const scheduled = client.scheduled.getOrCreate();
81
+
82
+ // Reset history to start fresh
83
+ await scheduled.clearHistory();
84
+
85
+ // Schedule multiple tasks with different delays
86
+ await scheduled.scheduleTaskAfterWithId("first", 100);
87
+ await scheduled.scheduleTaskAfterWithId("second", 300);
88
+ await scheduled.scheduleTaskAfterWithId("third", 500);
89
+
90
+ // Wait for first task only
91
+ await waitFor(driverTestConfig, 200);
92
+ const history1 = await scheduled.getTaskHistory();
93
+ expect(history1).toEqual(["first"]);
94
+
95
+ // Wait for second task
96
+ await waitFor(driverTestConfig, 200);
97
+ const history2 = await scheduled.getTaskHistory();
98
+ expect(history2).toEqual(["first", "second"]);
99
+
100
+ // Wait for third task
101
+ await waitFor(driverTestConfig, 200);
102
+ const history3 = await scheduled.getTaskHistory();
103
+ expect(history3).toEqual(["first", "second", "third"]);
104
+ });
105
+ });
106
+ },
107
+ );
108
+ }
@@ -0,0 +1,413 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { SLEEP_TIMEOUT } from "../../../fixtures/driver-test-suite/sleep";
3
+ import type { DriverTestConfig } from "../mod";
4
+ import { setupDriverTest, waitFor } from "../utils";
5
+
6
+ // TODO: These tests are broken with fake timers because `_sleep` requires
7
+ // background async promises that have a race condition with calling
8
+ // `getCounts`
9
+ //
10
+ // To fix this, we need to imeplment some event system to be able to check for
11
+ // when an actor has slept. OR we can expose an HTTP endpoint on the manager
12
+ // for `.test` that checks if na actor is sleeping that we can poll.
13
+ export function runActorSleepTests(driverTestConfig: DriverTestConfig) {
14
+ describe.skipIf(driverTestConfig.skip?.sleep)("Actor Sleep Tests", () => {
15
+ test("actor sleep persists state", async (c) => {
16
+ const { client } = await setupDriverTest(c, driverTestConfig);
17
+
18
+ // Create actor
19
+ const sleepActor = client.sleep.getOrCreate();
20
+
21
+ // Verify initial sleep count
22
+ {
23
+ const { startCount, sleepCount } = await sleepActor.getCounts();
24
+ expect(sleepCount).toBe(0);
25
+ expect(startCount).toBe(1);
26
+ }
27
+
28
+ // Trigger sleep
29
+ await sleepActor.triggerSleep();
30
+
31
+ // HACK: Wait for sleep to finish in background
32
+ await waitFor(driverTestConfig, 100);
33
+
34
+ // Get sleep count after restore
35
+ {
36
+ const { startCount, sleepCount } = await sleepActor.getCounts();
37
+ expect(sleepCount).toBe(1);
38
+ expect(startCount).toBe(2);
39
+ }
40
+ });
41
+
42
+ test("actor sleep persists state with connect", async (c) => {
43
+ const { client } = await setupDriverTest(c, driverTestConfig);
44
+
45
+ // Create actor with persistent connection
46
+ const sleepActor = client.sleep.getOrCreate().connect();
47
+
48
+ // Verify initial sleep count
49
+ {
50
+ const { startCount, sleepCount } = await sleepActor.getCounts();
51
+ expect(sleepCount).toBe(0);
52
+ expect(startCount).toBe(1);
53
+ }
54
+
55
+ // Trigger sleep
56
+ await sleepActor.triggerSleep();
57
+
58
+ // Disconnect to allow reconnection
59
+ await sleepActor.dispose();
60
+
61
+ // HACK: Wait for sleep to finish in background
62
+ await waitFor(driverTestConfig, 100);
63
+
64
+ // Reconnect to get sleep count after restore
65
+ const sleepActor2 = client.sleep.getOrCreate();
66
+ {
67
+ const { startCount, sleepCount } = await sleepActor2.getCounts();
68
+ expect(sleepCount).toBe(1);
69
+ expect(startCount).toBe(2);
70
+ }
71
+ });
72
+
73
+ test("actor automatically sleeps after timeout", async (c) => {
74
+ const { client } = await setupDriverTest(c, driverTestConfig);
75
+
76
+ // Create actor
77
+ const sleepActor = client.sleep.getOrCreate();
78
+
79
+ // Verify initial sleep count
80
+ {
81
+ const { startCount, sleepCount } = await sleepActor.getCounts();
82
+ expect(sleepCount).toBe(0);
83
+ expect(startCount).toBe(1);
84
+ }
85
+
86
+ // Wait for sleep
87
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
88
+
89
+ // Get sleep count after restore
90
+ {
91
+ const { startCount, sleepCount } = await sleepActor.getCounts();
92
+ expect(sleepCount).toBe(1);
93
+ expect(startCount).toBe(2);
94
+ }
95
+ });
96
+
97
+ test("actor automatically sleeps after timeout with connect", async (c) => {
98
+ const { client } = await setupDriverTest(c, driverTestConfig);
99
+
100
+ // Create actor with persistent connection
101
+ const sleepActor = client.sleep.getOrCreate().connect();
102
+
103
+ // Verify initial sleep count
104
+ {
105
+ const { startCount, sleepCount } = await sleepActor.getCounts();
106
+ expect(sleepCount).toBe(0);
107
+ expect(startCount).toBe(1);
108
+ }
109
+
110
+ // Disconnect to allow actor to sleep
111
+ await sleepActor.dispose();
112
+
113
+ // Wait for sleep
114
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
115
+
116
+ // Reconnect to get sleep count after restore
117
+ const sleepActor2 = client.sleep.getOrCreate();
118
+ {
119
+ const { startCount, sleepCount } = await sleepActor2.getCounts();
120
+ expect(sleepCount).toBe(1);
121
+ expect(startCount).toBe(2);
122
+ }
123
+ });
124
+
125
+ test("rpc calls keep actor awake", async (c) => {
126
+ const { client } = await setupDriverTest(c, driverTestConfig);
127
+
128
+ // Create actor
129
+ const sleepActor = client.sleep.getOrCreate();
130
+
131
+ // Verify initial state
132
+ {
133
+ const { startCount, sleepCount } = await sleepActor.getCounts();
134
+ expect(sleepCount).toBe(0);
135
+ expect(startCount).toBe(1);
136
+ }
137
+
138
+ // Wait almost until sleep timeout, then make RPC call
139
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT - 100);
140
+
141
+ // RPC call should reset the sleep timer
142
+ {
143
+ const { startCount, sleepCount } = await sleepActor.getCounts();
144
+ expect(sleepCount).toBe(0); // Haven't slept yet
145
+ expect(startCount).toBe(1); // Still the same instance
146
+ }
147
+
148
+ // Wait another partial timeout period - actor should still be awake
149
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT - 100);
150
+
151
+ // Actor should still be awake
152
+ {
153
+ const { startCount, sleepCount } = await sleepActor.getCounts();
154
+ expect(sleepCount).toBe(0); // Still haven't slept
155
+ expect(startCount).toBe(1); // Still the same instance
156
+ }
157
+
158
+ // Now wait for full timeout without any RPC calls
159
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
160
+
161
+ // Actor should have slept and restarted
162
+ {
163
+ const { startCount, sleepCount } = await sleepActor.getCounts();
164
+ expect(sleepCount).toBe(1); // Slept once
165
+ expect(startCount).toBe(2); // New instance after sleep
166
+ }
167
+ });
168
+
169
+ test("alarms keep actor awake", async (c) => {
170
+ const { client } = await setupDriverTest(c, driverTestConfig);
171
+
172
+ // Create actor
173
+ const sleepActor = client.sleep.getOrCreate();
174
+
175
+ // Verify initial state
176
+ {
177
+ const { startCount, sleepCount } = await sleepActor.getCounts();
178
+ expect(sleepCount).toBe(0);
179
+ expect(startCount).toBe(1);
180
+ }
181
+
182
+ // Set an alarm to keep the actor awake
183
+ await sleepActor.setAlarm(SLEEP_TIMEOUT - 100);
184
+
185
+ // Wait until after SLEEPT_IMEOUT to validate the actor did not sleep
186
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
187
+
188
+ // Actor should not have slept
189
+ {
190
+ const { startCount, sleepCount } = await sleepActor.getCounts();
191
+ expect(sleepCount).toBe(0);
192
+ expect(startCount).toBe(1);
193
+ }
194
+ });
195
+
196
+ test("alarms wake actors", async (c) => {
197
+ const { client } = await setupDriverTest(c, driverTestConfig);
198
+
199
+ // Create actor
200
+ const sleepActor = client.sleep.getOrCreate();
201
+
202
+ // Verify initial state
203
+ {
204
+ const { startCount, sleepCount } = await sleepActor.getCounts();
205
+ expect(sleepCount).toBe(0);
206
+ expect(startCount).toBe(1);
207
+ }
208
+
209
+ // Set an alarm to keep the actor awake
210
+ await sleepActor.setAlarm(SLEEP_TIMEOUT + 100);
211
+
212
+ // Wait until after SLEEPT_IMEOUT to validate the actor did not sleep
213
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 200);
214
+
215
+ // Actor should not have slept
216
+ {
217
+ const { startCount, sleepCount } = await sleepActor.getCounts();
218
+ expect(sleepCount).toBe(1);
219
+ expect(startCount).toBe(2);
220
+ }
221
+ });
222
+
223
+ test("long running rpcs keep actor awake", async (c) => {
224
+ const { client } = await setupDriverTest(c, driverTestConfig);
225
+
226
+ // Create actor
227
+ const sleepActor = client.sleepWithLongRpc.getOrCreate().connect();
228
+
229
+ // Verify initial state
230
+ {
231
+ const { startCount, sleepCount } = await sleepActor.getCounts();
232
+ expect(sleepCount).toBe(0);
233
+ expect(startCount).toBe(1);
234
+ }
235
+
236
+ // Start a long-running RPC that takes longer than the sleep timeout
237
+ const waitPromise = new Promise((resolve) =>
238
+ sleepActor.once("waiting", resolve),
239
+ );
240
+ const longRunningPromise = sleepActor.longRunningRpc();
241
+ await waitPromise;
242
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
243
+ await sleepActor.finishLongRunningRpc();
244
+ await longRunningPromise;
245
+
246
+ // Actor should still be the same instance (didn't sleep during RPC)
247
+ {
248
+ const { startCount, sleepCount } = await sleepActor.getCounts();
249
+ expect(sleepCount).toBe(0); // Hasn't slept
250
+ expect(startCount).toBe(1); // Same instance
251
+ }
252
+ await sleepActor.dispose();
253
+
254
+ // Now wait for the sleep timeout
255
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
256
+
257
+ // Actor should have slept after the timeout
258
+ const sleepActor2 = client.sleepWithLongRpc.getOrCreate();
259
+ {
260
+ const { startCount, sleepCount } = await sleepActor2.getCounts();
261
+ expect(sleepCount).toBe(1); // Slept once
262
+ expect(startCount).toBe(2); // New instance after sleep
263
+ }
264
+ });
265
+
266
+ test("active raw websockets keep actor awake", async (c) => {
267
+ const { client, endpoint: baseUrl } = await setupDriverTest(
268
+ c,
269
+ driverTestConfig,
270
+ );
271
+
272
+ // Create actor
273
+ const sleepActor = client.sleepWithRawWebSocket.getOrCreate();
274
+
275
+ // Verify initial state
276
+ {
277
+ const { startCount, sleepCount } = await sleepActor.getCounts();
278
+ expect(sleepCount).toBe(0);
279
+ expect(startCount).toBe(1);
280
+ }
281
+
282
+ // Connect WebSocket
283
+ const ws = await sleepActor.websocket();
284
+
285
+ await new Promise<void>((resolve, reject) => {
286
+ ws.onopen = () => resolve();
287
+ ws.onerror = reject;
288
+ });
289
+
290
+ // Wait for connection message
291
+ await new Promise<void>((resolve) => {
292
+ ws.onmessage = (event) => {
293
+ const data = JSON.parse(event.data);
294
+ if (data.type === "connected") {
295
+ resolve();
296
+ }
297
+ };
298
+ });
299
+
300
+ // Wait longer than sleep timeout while keeping WebSocket connected
301
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
302
+
303
+ // Send a message to check if actor is still alive
304
+ ws.send(JSON.stringify({ type: "getCounts" }));
305
+
306
+ const counts = await new Promise<any>((resolve) => {
307
+ ws.onmessage = (event) => {
308
+ const data = JSON.parse(event.data);
309
+ if (data.type === "counts") {
310
+ resolve(data);
311
+ }
312
+ };
313
+ });
314
+
315
+ // Actor should still be the same instance (didn't sleep while WebSocket connected)
316
+ expect(counts.sleepCount).toBe(0);
317
+ expect(counts.startCount).toBe(1);
318
+
319
+ // Close WebSocket
320
+ ws.close();
321
+ await new Promise((resolve) => setTimeout(resolve, 100));
322
+
323
+ // Wait for sleep timeout after WebSocket closed
324
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
325
+
326
+ // Actor should have slept after WebSocket closed
327
+ {
328
+ const { startCount, sleepCount } = await sleepActor.getCounts();
329
+ expect(sleepCount).toBe(1); // Slept once
330
+ expect(startCount).toBe(2); // New instance after sleep
331
+ }
332
+ });
333
+
334
+ test("active raw fetch requests keep actor awake", async (c) => {
335
+ const { client, endpoint: baseUrl } = await setupDriverTest(
336
+ c,
337
+ driverTestConfig,
338
+ );
339
+
340
+ // Create actor
341
+ const sleepActor = client.sleepWithRawHttp.getOrCreate();
342
+
343
+ // Verify initial state
344
+ {
345
+ const { startCount, sleepCount } = await sleepActor.getCounts();
346
+ expect(sleepCount).toBe(0);
347
+ expect(startCount).toBe(1);
348
+ }
349
+
350
+ // Start a long-running fetch request
351
+ const fetchDuration = SLEEP_TIMEOUT + 100;
352
+ const fetchPromise = sleepActor.fetch(
353
+ `long-request?duration=${fetchDuration}`,
354
+ );
355
+
356
+ // Wait for the fetch to complete
357
+ const response = await fetchPromise;
358
+ const result = (await response.json()) as { completed: boolean };
359
+ expect(result.completed).toBe(true);
360
+ {
361
+ const { startCount, sleepCount, requestCount } =
362
+ await sleepActor.getCounts();
363
+ expect(sleepCount).toBe(0);
364
+ expect(startCount).toBe(1);
365
+ expect(requestCount).toBe(1);
366
+ }
367
+
368
+ // Wait for sleep timeout
369
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
370
+
371
+ // Actor should have slept after timeout
372
+ {
373
+ const { startCount, sleepCount } = await sleepActor.getCounts();
374
+ expect(sleepCount).toBe(1); // Slept once
375
+ expect(startCount).toBe(2); // New instance after sleep
376
+ }
377
+ });
378
+
379
+ test("noSleep option disables sleeping", async (c) => {
380
+ const { client } = await setupDriverTest(c, driverTestConfig);
381
+
382
+ // Create actor with noSleep option
383
+ const sleepActor = client.sleepWithNoSleepOption.getOrCreate();
384
+
385
+ // Verify initial state
386
+ {
387
+ const { startCount, sleepCount } = await sleepActor.getCounts();
388
+ expect(sleepCount).toBe(0);
389
+ expect(startCount).toBe(1);
390
+ }
391
+
392
+ // Wait longer than sleep timeout
393
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
394
+
395
+ // Actor should NOT have slept due to noSleep option
396
+ {
397
+ const { startCount, sleepCount } = await sleepActor.getCounts();
398
+ expect(sleepCount).toBe(0); // Never slept
399
+ expect(startCount).toBe(1); // Still the same instance
400
+ }
401
+
402
+ // Wait even longer to be sure
403
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
404
+
405
+ // Actor should still not have slept
406
+ {
407
+ const { startCount, sleepCount } = await sleepActor.getCounts();
408
+ expect(sleepCount).toBe(0); // Never slept
409
+ expect(startCount).toBe(1); // Still the same instance
410
+ }
411
+ });
412
+ });
413
+ }
@@ -0,0 +1,54 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import type { DriverTestConfig } from "../mod";
3
+ import { setupDriverTest } from "../utils";
4
+
5
+ export function runActorStateTests(driverTestConfig: DriverTestConfig) {
6
+ describe("Actor State Tests", () => {
7
+ describe("State Persistence", () => {
8
+ test("persists state between actor instances", async (c) => {
9
+ const { client } = await setupDriverTest(c, driverTestConfig);
10
+
11
+ // Create instance and increment
12
+ const counterInstance = client.counter.getOrCreate();
13
+ const initialCount = await counterInstance.increment(5);
14
+ expect(initialCount).toBe(5);
15
+
16
+ // Get a fresh reference to the same actor and verify state persisted
17
+ const sameInstance = client.counter.getOrCreate();
18
+ const persistedCount = await sameInstance.increment(3);
19
+ expect(persistedCount).toBe(8);
20
+ });
21
+
22
+ test("restores state after actor disconnect/reconnect", async (c) => {
23
+ const { client } = await setupDriverTest(c, driverTestConfig);
24
+
25
+ // Create actor and set initial state
26
+ const counterInstance = client.counter.getOrCreate();
27
+ await counterInstance.increment(5);
28
+
29
+ // Reconnect to the same actor
30
+ const reconnectedInstance = client.counter.getOrCreate();
31
+ const persistedCount = await reconnectedInstance.increment(0);
32
+ expect(persistedCount).toBe(5);
33
+ });
34
+
35
+ test("maintains separate state for different actors", async (c) => {
36
+ const { client } = await setupDriverTest(c, driverTestConfig);
37
+
38
+ // Create first counter with specific key
39
+ const counterA = client.counter.getOrCreate(["counter-a"]);
40
+ await counterA.increment(5);
41
+
42
+ // Create second counter with different key
43
+ const counterB = client.counter.getOrCreate(["counter-b"]);
44
+ await counterB.increment(10);
45
+
46
+ // Verify state is separate
47
+ const countA = await counterA.increment(0);
48
+ const countB = await counterB.increment(0);
49
+ expect(countA).toBe(5);
50
+ expect(countB).toBe(10);
51
+ });
52
+ });
53
+ });
54
+ }