rivetkit 2.0.23 → 2.0.24

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 (228) hide show
  1. package/dist/schemas/actor-persist/v2.ts +3 -3
  2. package/dist/schemas/actor-persist/v3.ts +274 -0
  3. package/dist/schemas/client-protocol/v2.ts +432 -0
  4. package/dist/schemas/file-system-driver/v2.ts +136 -0
  5. package/dist/tsup/actor/errors.cjs +2 -4
  6. package/dist/tsup/actor/errors.cjs.map +1 -1
  7. package/dist/tsup/actor/errors.d.cts +7 -10
  8. package/dist/tsup/actor/errors.d.ts +7 -10
  9. package/dist/tsup/actor/errors.js +9 -11
  10. package/dist/tsup/{actor-router-consts-B3Lu87yJ.d.cts → actor-router-consts-DzI2szci.d.cts} +5 -9
  11. package/dist/tsup/{actor-router-consts-B3Lu87yJ.d.ts → actor-router-consts-DzI2szci.d.ts} +5 -9
  12. package/dist/tsup/{chunk-3JYSUFET.cjs → chunk-3543NCSN.cjs} +45 -57
  13. package/dist/tsup/chunk-3543NCSN.cjs.map +1 -0
  14. package/dist/tsup/chunk-4SHILYS5.cjs +5694 -0
  15. package/dist/tsup/chunk-4SHILYS5.cjs.map +1 -0
  16. package/dist/tsup/{chunk-NCUALX2Q.cjs → chunk-5BZO5XPS.cjs} +3 -3
  17. package/dist/tsup/{chunk-NCUALX2Q.cjs.map → chunk-5BZO5XPS.cjs.map} +1 -1
  18. package/dist/tsup/{chunk-5PKKNNNS.js → chunk-BAIGSF64.js} +189 -187
  19. package/dist/tsup/chunk-BAIGSF64.js.map +1 -0
  20. package/dist/tsup/{chunk-HNYF4T36.cjs → chunk-CHLZBSI2.cjs} +17 -17
  21. package/dist/tsup/chunk-CHLZBSI2.cjs.map +1 -0
  22. package/dist/tsup/chunk-D3SLADUD.cjs +512 -0
  23. package/dist/tsup/chunk-D3SLADUD.cjs.map +1 -0
  24. package/dist/tsup/{chunk-KSRXX3Z4.cjs → chunk-D6762AOA.cjs} +20 -25
  25. package/dist/tsup/chunk-D6762AOA.cjs.map +1 -0
  26. package/dist/tsup/{chunk-C56XVVV4.cjs → chunk-DLK5YCTN.cjs} +187 -185
  27. package/dist/tsup/chunk-DLK5YCTN.cjs.map +1 -0
  28. package/dist/tsup/{chunk-DLYZKFRY.js → chunk-DUJQWGYD.js} +3 -7
  29. package/dist/tsup/chunk-DUJQWGYD.js.map +1 -0
  30. package/dist/tsup/{chunk-5UJQWWO3.js → chunk-EIPANQMF.js} +2 -2
  31. package/dist/tsup/{chunk-54DVMQPT.cjs → chunk-ESMTDP7G.cjs} +6 -6
  32. package/dist/tsup/chunk-ESMTDP7G.cjs.map +1 -0
  33. package/dist/tsup/{chunk-XYK5PY3B.cjs → chunk-FVAKREFB.cjs} +1900 -1737
  34. package/dist/tsup/chunk-FVAKREFB.cjs.map +1 -0
  35. package/dist/tsup/{chunk-PHNIVSG5.js → chunk-I3XT7WOF.js} +44 -56
  36. package/dist/tsup/chunk-I3XT7WOF.js.map +1 -0
  37. package/dist/tsup/{chunk-3I6ZIJVJ.js → chunk-IMDS5T42.js} +3 -3
  38. package/dist/tsup/chunk-IMDS5T42.js.map +1 -0
  39. package/dist/tsup/{chunk-SN4KWTRA.cjs → chunk-J3HZJF2P.cjs} +10 -14
  40. package/dist/tsup/chunk-J3HZJF2P.cjs.map +1 -0
  41. package/dist/tsup/{chunk-NOZSCUPQ.js → chunk-MBBJUHSP.js} +1844 -1681
  42. package/dist/tsup/chunk-MBBJUHSP.js.map +1 -0
  43. package/dist/tsup/{chunk-RVVUS4X6.js → chunk-MO5CB6MD.js} +9 -9
  44. package/dist/tsup/chunk-MO5CB6MD.js.map +1 -0
  45. package/dist/tsup/chunk-OFOTPKAH.js +512 -0
  46. package/dist/tsup/chunk-OFOTPKAH.js.map +1 -0
  47. package/dist/tsup/{chunk-G64QUEDJ.js → chunk-W6RDS6NW.js} +23 -28
  48. package/dist/tsup/chunk-W6RDS6NW.js.map +1 -0
  49. package/dist/tsup/{chunk-XSDSNHSE.cjs → chunk-YC5DUHPM.cjs} +4 -8
  50. package/dist/tsup/chunk-YC5DUHPM.cjs.map +1 -0
  51. package/dist/tsup/{chunk-YAYNBR37.js → chunk-YC7YPM2T.js} +2 -6
  52. package/dist/tsup/chunk-YC7YPM2T.js.map +1 -0
  53. package/dist/tsup/{chunk-FTQ62XTN.js → chunk-ZSPU5R4C.js} +3322 -2251
  54. package/dist/tsup/chunk-ZSPU5R4C.js.map +1 -0
  55. package/dist/tsup/client/mod.cjs +9 -9
  56. package/dist/tsup/client/mod.d.cts +5 -7
  57. package/dist/tsup/client/mod.d.ts +5 -7
  58. package/dist/tsup/client/mod.js +8 -8
  59. package/dist/tsup/common/log.cjs +3 -3
  60. package/dist/tsup/common/log.js +2 -2
  61. package/dist/tsup/common/websocket.cjs +4 -4
  62. package/dist/tsup/common/websocket.js +3 -3
  63. package/dist/tsup/{conn-B3Vhbgnd.d.ts → config-BRDYDraU.d.cts} +1119 -1047
  64. package/dist/tsup/{conn-DJWL3nGx.d.cts → config-Bo-blHpJ.d.ts} +1119 -1047
  65. package/dist/tsup/driver-helpers/mod.cjs +5 -13
  66. package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
  67. package/dist/tsup/driver-helpers/mod.d.cts +11 -9
  68. package/dist/tsup/driver-helpers/mod.d.ts +11 -9
  69. package/dist/tsup/driver-helpers/mod.js +14 -22
  70. package/dist/tsup/driver-test-suite/mod.cjs +474 -303
  71. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
  72. package/dist/tsup/driver-test-suite/mod.d.cts +6 -9
  73. package/dist/tsup/driver-test-suite/mod.d.ts +6 -9
  74. package/dist/tsup/driver-test-suite/mod.js +1085 -914
  75. package/dist/tsup/driver-test-suite/mod.js.map +1 -1
  76. package/dist/tsup/inspector/mod.cjs +6 -6
  77. package/dist/tsup/inspector/mod.d.cts +5 -7
  78. package/dist/tsup/inspector/mod.d.ts +5 -7
  79. package/dist/tsup/inspector/mod.js +5 -5
  80. package/dist/tsup/mod.cjs +10 -16
  81. package/dist/tsup/mod.cjs.map +1 -1
  82. package/dist/tsup/mod.d.cts +23 -25
  83. package/dist/tsup/mod.d.ts +23 -25
  84. package/dist/tsup/mod.js +17 -23
  85. package/dist/tsup/test/mod.cjs +11 -11
  86. package/dist/tsup/test/mod.d.cts +4 -6
  87. package/dist/tsup/test/mod.d.ts +4 -6
  88. package/dist/tsup/test/mod.js +10 -10
  89. package/dist/tsup/utils.cjs +3 -5
  90. package/dist/tsup/utils.cjs.map +1 -1
  91. package/dist/tsup/utils.d.cts +1 -2
  92. package/dist/tsup/utils.d.ts +1 -2
  93. package/dist/tsup/utils.js +2 -4
  94. package/package.json +13 -6
  95. package/src/actor/config.ts +56 -44
  96. package/src/actor/conn/driver.ts +61 -0
  97. package/src/actor/conn/drivers/http.ts +17 -0
  98. package/src/actor/conn/drivers/raw-request.ts +24 -0
  99. package/src/actor/conn/drivers/raw-websocket.ts +65 -0
  100. package/src/actor/conn/drivers/websocket.ts +129 -0
  101. package/src/actor/conn/mod.ts +232 -0
  102. package/src/actor/conn/persisted.ts +81 -0
  103. package/src/actor/conn/state-manager.ts +196 -0
  104. package/src/actor/contexts/action.ts +23 -0
  105. package/src/actor/{context.ts → contexts/actor.ts} +19 -8
  106. package/src/actor/contexts/conn-init.ts +31 -0
  107. package/src/actor/contexts/conn.ts +48 -0
  108. package/src/actor/contexts/create-conn-state.ts +13 -0
  109. package/src/actor/contexts/on-before-connect.ts +13 -0
  110. package/src/actor/contexts/on-connect.ts +22 -0
  111. package/src/actor/contexts/request.ts +48 -0
  112. package/src/actor/contexts/websocket.ts +48 -0
  113. package/src/actor/definition.ts +3 -3
  114. package/src/actor/driver.ts +36 -5
  115. package/src/actor/errors.ts +19 -24
  116. package/src/actor/instance/connection-manager.ts +465 -0
  117. package/src/actor/instance/event-manager.ts +292 -0
  118. package/src/actor/instance/kv.ts +15 -0
  119. package/src/actor/instance/mod.ts +1107 -0
  120. package/src/actor/instance/persisted.ts +67 -0
  121. package/src/actor/instance/schedule-manager.ts +349 -0
  122. package/src/actor/instance/state-manager.ts +502 -0
  123. package/src/actor/mod.ts +13 -16
  124. package/src/actor/protocol/old.ts +131 -43
  125. package/src/actor/protocol/serde.ts +19 -4
  126. package/src/actor/router-endpoints.ts +61 -586
  127. package/src/actor/router-websocket-endpoints.ts +408 -0
  128. package/src/actor/router.ts +63 -197
  129. package/src/actor/schedule.ts +1 -1
  130. package/src/client/actor-conn.ts +183 -249
  131. package/src/client/actor-handle.ts +29 -6
  132. package/src/client/client.ts +0 -4
  133. package/src/client/config.ts +1 -4
  134. package/src/client/mod.ts +0 -1
  135. package/src/client/raw-utils.ts +3 -3
  136. package/src/client/utils.ts +85 -39
  137. package/src/common/actor-router-consts.ts +5 -12
  138. package/src/common/{inline-websocket-adapter2.ts → inline-websocket-adapter.ts} +26 -48
  139. package/src/common/log.ts +1 -1
  140. package/src/common/router.ts +28 -17
  141. package/src/common/utils.ts +2 -0
  142. package/src/driver-helpers/mod.ts +7 -10
  143. package/src/driver-helpers/utils.ts +18 -9
  144. package/src/driver-test-suite/mod.ts +26 -50
  145. package/src/driver-test-suite/test-inline-client-driver.ts +27 -51
  146. package/src/driver-test-suite/tests/actor-conn-hibernation.ts +150 -0
  147. package/src/driver-test-suite/tests/actor-conn-state.ts +1 -4
  148. package/src/driver-test-suite/tests/actor-conn.ts +5 -9
  149. package/src/driver-test-suite/tests/actor-destroy.ts +294 -0
  150. package/src/driver-test-suite/tests/actor-driver.ts +0 -7
  151. package/src/driver-test-suite/tests/actor-handle.ts +12 -12
  152. package/src/driver-test-suite/tests/actor-metadata.ts +1 -1
  153. package/src/driver-test-suite/tests/manager-driver.ts +1 -1
  154. package/src/driver-test-suite/tests/raw-http-direct-registry.ts +8 -8
  155. package/src/driver-test-suite/tests/raw-http-request-properties.ts +6 -5
  156. package/src/driver-test-suite/tests/raw-http.ts +5 -5
  157. package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +7 -7
  158. package/src/driver-test-suite/tests/request-access.ts +4 -4
  159. package/src/driver-test-suite/utils.ts +6 -10
  160. package/src/drivers/engine/actor-driver.ts +614 -424
  161. package/src/drivers/engine/mod.ts +0 -1
  162. package/src/drivers/file-system/actor.ts +24 -12
  163. package/src/drivers/file-system/global-state.ts +427 -37
  164. package/src/drivers/file-system/manager.ts +71 -83
  165. package/src/drivers/file-system/mod.ts +3 -0
  166. package/src/drivers/file-system/utils.ts +18 -8
  167. package/src/engine-process/mod.ts +38 -38
  168. package/src/inspector/utils.ts +7 -5
  169. package/src/manager/driver.ts +11 -4
  170. package/src/manager/gateway.ts +4 -29
  171. package/src/manager/protocol/mod.ts +0 -2
  172. package/src/manager/protocol/query.ts +0 -4
  173. package/src/manager/router.ts +67 -64
  174. package/src/manager-api/actors.ts +13 -0
  175. package/src/mod.ts +1 -3
  176. package/src/registry/mod.ts +20 -20
  177. package/src/registry/serve.ts +9 -14
  178. package/src/remote-manager-driver/actor-websocket-client.ts +1 -16
  179. package/src/remote-manager-driver/api-endpoints.ts +13 -1
  180. package/src/remote-manager-driver/api-utils.ts +8 -0
  181. package/src/remote-manager-driver/metadata.ts +58 -0
  182. package/src/remote-manager-driver/mod.ts +47 -62
  183. package/src/remote-manager-driver/ws-proxy.ts +1 -1
  184. package/src/schemas/actor-persist/mod.ts +1 -1
  185. package/src/schemas/actor-persist/versioned.ts +56 -31
  186. package/src/schemas/client-protocol/mod.ts +1 -1
  187. package/src/schemas/client-protocol/versioned.ts +41 -21
  188. package/src/schemas/client-protocol-zod/mod.ts +103 -0
  189. package/src/schemas/file-system-driver/mod.ts +1 -1
  190. package/src/schemas/file-system-driver/versioned.ts +42 -19
  191. package/src/serde.ts +33 -11
  192. package/src/test/mod.ts +7 -3
  193. package/src/utils/node.ts +173 -0
  194. package/src/utils.ts +0 -4
  195. package/dist/tsup/chunk-3I6ZIJVJ.js.map +0 -1
  196. package/dist/tsup/chunk-3JYSUFET.cjs.map +0 -1
  197. package/dist/tsup/chunk-54DVMQPT.cjs.map +0 -1
  198. package/dist/tsup/chunk-5PKKNNNS.js.map +0 -1
  199. package/dist/tsup/chunk-C56XVVV4.cjs.map +0 -1
  200. package/dist/tsup/chunk-D6PCH7FR.cjs +0 -4623
  201. package/dist/tsup/chunk-D6PCH7FR.cjs.map +0 -1
  202. package/dist/tsup/chunk-DLYZKFRY.js.map +0 -1
  203. package/dist/tsup/chunk-FTQ62XTN.js.map +0 -1
  204. package/dist/tsup/chunk-G64QUEDJ.js.map +0 -1
  205. package/dist/tsup/chunk-HNYF4T36.cjs.map +0 -1
  206. package/dist/tsup/chunk-JMLTKMJ7.cjs +0 -1119
  207. package/dist/tsup/chunk-JMLTKMJ7.cjs.map +0 -1
  208. package/dist/tsup/chunk-KSRXX3Z4.cjs.map +0 -1
  209. package/dist/tsup/chunk-NOZSCUPQ.js.map +0 -1
  210. package/dist/tsup/chunk-PHNIVSG5.js.map +0 -1
  211. package/dist/tsup/chunk-RUTBXBRR.js +0 -1119
  212. package/dist/tsup/chunk-RUTBXBRR.js.map +0 -1
  213. package/dist/tsup/chunk-RVVUS4X6.js.map +0 -1
  214. package/dist/tsup/chunk-SN4KWTRA.cjs.map +0 -1
  215. package/dist/tsup/chunk-XSDSNHSE.cjs.map +0 -1
  216. package/dist/tsup/chunk-XYK5PY3B.cjs.map +0 -1
  217. package/dist/tsup/chunk-YAYNBR37.js.map +0 -1
  218. package/src/actor/action.ts +0 -178
  219. package/src/actor/conn-drivers.ts +0 -216
  220. package/src/actor/conn-socket.ts +0 -8
  221. package/src/actor/conn.ts +0 -272
  222. package/src/actor/instance.ts +0 -2336
  223. package/src/actor/persisted.ts +0 -49
  224. package/src/actor/unstable-react.ts +0 -110
  225. package/src/driver-test-suite/tests/actor-reconnect.ts +0 -170
  226. package/src/drivers/engine/kv.ts +0 -3
  227. package/src/manager/hono-websocket-adapter.ts +0 -393
  228. /package/dist/tsup/{chunk-5UJQWWO3.js.map → chunk-EIPANQMF.js.map} +0 -0
@@ -0,0 +1,294 @@
1
+ import { describe, expect, test, vi } from "vitest";
2
+ import type { ActorError } from "@/client/mod";
3
+ import type { DriverTestConfig } from "../mod";
4
+ import { setupDriverTest } from "../utils";
5
+
6
+ export function runActorDestroyTests(driverTestConfig: DriverTestConfig) {
7
+ describe("Actor Destroy Tests", () => {
8
+ test("actor destroy clears state (without connect)", async (c) => {
9
+ const { client } = await setupDriverTest(c, driverTestConfig);
10
+
11
+ const actorKey = "test-destroy-without-connect";
12
+
13
+ // Get destroy observer
14
+ const observer = client.destroyObserver.getOrCreate(["observer"]);
15
+ await observer.reset();
16
+
17
+ // Create actor
18
+ const destroyActor = client.destroyActor.getOrCreate([actorKey]);
19
+
20
+ // Update state and save immediately
21
+ await destroyActor.setValue(42);
22
+
23
+ // Verify state was saved
24
+ const value = await destroyActor.getValue();
25
+ expect(value).toBe(42);
26
+
27
+ // Get actor ID before destroying
28
+ const actorId = await destroyActor.resolve();
29
+
30
+ // Destroy the actor
31
+ await destroyActor.destroy();
32
+
33
+ // Wait until the observer confirms the actor was destroyed
34
+ await vi.waitFor(async () => {
35
+ const wasDestroyed = await observer.wasDestroyed(actorKey);
36
+ expect(wasDestroyed, "actor onDestroy not called").toBeTruthy();
37
+ });
38
+
39
+ // Wait until the actor is fully cleaned up (getForId returns error)
40
+ await vi.waitFor(async () => {
41
+ let actorRunning = false;
42
+ try {
43
+ await client.destroyActor.getForId(actorId).getValue();
44
+ actorRunning = true;
45
+ } catch (err) {
46
+ expect((err as ActorError).group).toBe("actor");
47
+ expect((err as ActorError).code).toBe("not_found");
48
+ }
49
+
50
+ expect(actorRunning, "actor still running").toBeFalsy();
51
+ });
52
+
53
+ // Verify actor no longer exists via getForId
54
+ let existsById = false;
55
+ try {
56
+ await client.destroyActor.getForId(actorId).getValue();
57
+ existsById = true;
58
+ } catch (err) {
59
+ expect((err as ActorError).group).toBe("actor");
60
+ expect((err as ActorError).code).toBe("not_found");
61
+ }
62
+ expect(
63
+ existsById,
64
+ "actor should not exist after destroy",
65
+ ).toBeFalsy();
66
+
67
+ // Verify actor no longer exists via get
68
+ let existsByKey = false;
69
+ try {
70
+ await client.destroyActor
71
+ .get(["test-destroy-without-connect"])
72
+ .resolve();
73
+ existsByKey = true;
74
+ } catch (err) {
75
+ expect((err as ActorError).group).toBe("actor");
76
+ expect((err as ActorError).code).toBe("not_found");
77
+ }
78
+ expect(
79
+ existsByKey,
80
+ "actor should not exist after destroy",
81
+ ).toBeFalsy();
82
+
83
+ // Create new actor with same key using getOrCreate
84
+ const newActor = client.destroyActor.getOrCreate([
85
+ "test-destroy-without-connect",
86
+ ]);
87
+
88
+ // Verify state is fresh (default value, not the old value)
89
+ const newValue = await newActor.getValue();
90
+ expect(newValue).toBe(0);
91
+ });
92
+
93
+ test("actor destroy clears state (with connect)", async (c) => {
94
+ const { client } = await setupDriverTest(c, driverTestConfig);
95
+
96
+ const actorKey = "test-destroy-with-connect";
97
+
98
+ // Get destroy observer
99
+ const observer = client.destroyObserver.getOrCreate(["observer"]);
100
+ await observer.reset();
101
+
102
+ // Create actor handle
103
+ const destroyActorHandle = client.destroyActor.getOrCreate([
104
+ actorKey,
105
+ ]);
106
+
107
+ // Get actor ID before destroying
108
+ const actorId = await destroyActorHandle.resolve();
109
+
110
+ // Create persistent connection
111
+ const destroyActor = destroyActorHandle.connect();
112
+
113
+ // Update state and save immediately
114
+ await destroyActor.setValue(99);
115
+
116
+ // Verify state was saved
117
+ const value = await destroyActor.getValue();
118
+ expect(value).toBe(99);
119
+
120
+ // Destroy the actor
121
+ await destroyActor.destroy();
122
+
123
+ // Dispose the connection
124
+ await destroyActor.dispose();
125
+
126
+ // Wait until the observer confirms the actor was destroyed
127
+ await vi.waitFor(async () => {
128
+ const wasDestroyed = await observer.wasDestroyed(actorKey);
129
+ expect(wasDestroyed, "actor onDestroy not called").toBeTruthy();
130
+ });
131
+
132
+ // Wait until the actor is fully cleaned up (getForId returns error)
133
+ await vi.waitFor(async () => {
134
+ let actorRunning = false;
135
+ try {
136
+ await client.destroyActor.getForId(actorId).getValue();
137
+ actorRunning = true;
138
+ } catch (err) {
139
+ expect((err as ActorError).group).toBe("actor");
140
+ expect((err as ActorError).code).toBe("not_found");
141
+ }
142
+
143
+ expect(actorRunning, "actor still running").toBeFalsy();
144
+ });
145
+
146
+ // Verify actor no longer exists via getForId
147
+ let existsById = false;
148
+ try {
149
+ await client.destroyActor.getForId(actorId).getValue();
150
+ existsById = true;
151
+ } catch (err) {
152
+ expect((err as ActorError).group).toBe("actor");
153
+ expect((err as ActorError).code).toBe("not_found");
154
+ }
155
+ expect(
156
+ existsById,
157
+ "actor should not exist after destroy",
158
+ ).toBeFalsy();
159
+
160
+ // Verify actor no longer exists via get
161
+ let existsByKey = false;
162
+ try {
163
+ await client.destroyActor
164
+ .get(["test-destroy-with-connect"])
165
+ .resolve();
166
+ existsByKey = true;
167
+ } catch (err) {
168
+ expect((err as ActorError).group).toBe("actor");
169
+ expect((err as ActorError).code).toBe("not_found");
170
+ }
171
+ expect(
172
+ existsByKey,
173
+ "actor should not exist after destroy",
174
+ ).toBeFalsy();
175
+
176
+ // Create new actor with same key using getOrCreate
177
+ const newActor = client.destroyActor.getOrCreate([
178
+ "test-destroy-with-connect",
179
+ ]);
180
+
181
+ // Verify state is fresh (default value, not the old value)
182
+ const newValue = await newActor.getValue();
183
+ expect(newValue).toBe(0);
184
+ });
185
+
186
+ test("actor destroy allows recreation via getOrCreate with resolve", async (c) => {
187
+ const { client } = await setupDriverTest(c, driverTestConfig);
188
+
189
+ const actorKey = "test-destroy-getorcreate-resolve";
190
+
191
+ // Get destroy observer
192
+ const observer = client.destroyObserver.getOrCreate(["observer"]);
193
+ await observer.reset();
194
+
195
+ // Create actor
196
+ const destroyActor = client.destroyActor.getOrCreate([actorKey]);
197
+
198
+ // Update state and save immediately
199
+ await destroyActor.setValue(123);
200
+
201
+ // Verify state was saved
202
+ const value = await destroyActor.getValue();
203
+ expect(value).toBe(123);
204
+
205
+ // Get actor ID before destroying
206
+ const actorId = await destroyActor.resolve();
207
+
208
+ // Destroy the actor
209
+ await destroyActor.destroy();
210
+
211
+ // Wait until the observer confirms the actor was destroyed
212
+ await vi.waitFor(async () => {
213
+ const wasDestroyed = await observer.wasDestroyed(actorKey);
214
+ expect(wasDestroyed, "actor onDestroy not called").toBeTruthy();
215
+ });
216
+
217
+ // Wait until the actor is fully cleaned up
218
+ await vi.waitFor(async () => {
219
+ let actorRunning = false;
220
+ try {
221
+ await client.destroyActor.getForId(actorId).getValue();
222
+ actorRunning = true;
223
+ } catch (err) {
224
+ expect((err as ActorError).group).toBe("actor");
225
+ expect((err as ActorError).code).toBe("not_found");
226
+ }
227
+
228
+ expect(actorRunning, "actor still running").toBeFalsy();
229
+ });
230
+
231
+ // Recreate using getOrCreate with resolve
232
+ const newHandle = client.destroyActor.getOrCreate([actorKey]);
233
+ const newActorId = await newHandle.resolve();
234
+
235
+ // Verify state is fresh (default value, not the old value)
236
+ const newValue = await newHandle.getValue();
237
+ expect(newValue).toBe(0);
238
+ });
239
+
240
+ test("actor destroy allows recreation via create", async (c) => {
241
+ const { client } = await setupDriverTest(c, driverTestConfig);
242
+
243
+ const actorKey = "test-destroy-create";
244
+
245
+ // Get destroy observer
246
+ const observer = client.destroyObserver.getOrCreate(["observer"]);
247
+ await observer.reset();
248
+
249
+ // Create actor using create()
250
+ const initialHandle = await client.destroyActor.create([actorKey]);
251
+
252
+ // Update state and save immediately
253
+ await initialHandle.setValue(456);
254
+
255
+ // Verify state was saved
256
+ const value = await initialHandle.getValue();
257
+ expect(value).toBe(456);
258
+
259
+ // Get actor ID before destroying
260
+ const actorId = await initialHandle.resolve();
261
+
262
+ // Destroy the actor
263
+ await initialHandle.destroy();
264
+
265
+ // Wait until the observer confirms the actor was destroyed
266
+ await vi.waitFor(async () => {
267
+ const wasDestroyed = await observer.wasDestroyed(actorKey);
268
+ expect(wasDestroyed, "actor onDestroy not called").toBeTruthy();
269
+ });
270
+
271
+ // Wait until the actor is fully cleaned up
272
+ await vi.waitFor(async () => {
273
+ let actorRunning = false;
274
+ try {
275
+ await client.destroyActor.getForId(actorId).getValue();
276
+ actorRunning = true;
277
+ } catch (err) {
278
+ expect((err as ActorError).group).toBe("actor");
279
+ expect((err as ActorError).code).toBe("not_found");
280
+ }
281
+
282
+ expect(actorRunning, "actor still running").toBeFalsy();
283
+ });
284
+
285
+ // Recreate using create()
286
+ const newHandle = await client.destroyActor.create([actorKey]);
287
+ const newActorId = await newHandle.resolve();
288
+
289
+ // Verify state is fresh (default value, not the old value)
290
+ const newValue = await newHandle.getValue();
291
+ expect(newValue).toBe(0);
292
+ });
293
+ });
294
+ }
@@ -11,14 +11,7 @@ export function runActorDriverTests(driverTestConfig: DriverTestConfig) {
11
11
 
12
12
  // Run scheduled alarms tests
13
13
  runActorScheduleTests(driverTestConfig);
14
- });
15
- }
16
14
 
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
15
  // Run actor sleep tests
23
16
  runActorSleepTests(driverTestConfig);
24
17
  });
@@ -94,7 +94,7 @@ export function runActorHandleTests(driverTestConfig: DriverTestConfig) {
94
94
  expect.fail("did not error on duplicate create");
95
95
  } catch (err) {
96
96
  expect((err as ActorError).group).toBe("actor");
97
- expect((err as ActorError).code).toBe("already_exists");
97
+ expect((err as ActorError).code).toBe("duplicate_key");
98
98
  }
99
99
  });
100
100
 
@@ -183,25 +183,25 @@ export function runActorHandleTests(driverTestConfig: DriverTestConfig) {
183
183
  test("should trigger lifecycle hooks on actor creation", async (c) => {
184
184
  const { client } = await setupDriverTest(c, driverTestConfig);
185
185
 
186
- // Get or create a new actor - this should trigger onStart
186
+ // Get or create a new actor - this should trigger onWake
187
187
  const handle = client.counterWithLifecycle.getOrCreate([
188
188
  "test-lifecycle-handle",
189
189
  ]);
190
190
 
191
- // Verify onStart was triggered
191
+ // Verify onWake was triggered
192
192
  const initialEvents = await handle.getEvents();
193
- expect(initialEvents).toContain("onStart");
193
+ expect(initialEvents).toContain("onWake");
194
194
 
195
195
  // Create a separate handle to the same actor
196
196
  const sameHandle = client.counterWithLifecycle.getOrCreate([
197
197
  "test-lifecycle-handle",
198
198
  ]);
199
199
 
200
- // Verify events still include onStart but don't duplicate it
201
- // (onStart should only be called once when the actor is first created)
200
+ // Verify events still include onWake but don't duplicate it
201
+ // (onWake should only be called once when the actor is first created)
202
202
  const events = await sameHandle.getEvents();
203
- expect(events).toContain("onStart");
204
- expect(events.filter((e) => e === "onStart").length).toBe(1);
203
+ expect(events).toContain("onWake");
204
+ expect(events.filter((e) => e === "onWake").length).toBe(1);
205
205
  });
206
206
 
207
207
  test("should trigger lifecycle hooks for each Action call", async (c) => {
@@ -212,9 +212,9 @@ export function runActorHandleTests(driverTestConfig: DriverTestConfig) {
212
212
  "test-lifecycle-action",
213
213
  ]);
214
214
 
215
- // Initial state should only have onStart
215
+ // Initial state should only have onWake
216
216
  const initialEvents = await viewHandle.getEvents();
217
- expect(initialEvents).toContain("onStart");
217
+ expect(initialEvents).toContain("onWake");
218
218
  expect(initialEvents).not.toContain("onBeforeConnect");
219
219
  expect(initialEvents).not.toContain("onConnect");
220
220
  expect(initialEvents).not.toContain("onDisconnect");
@@ -297,8 +297,8 @@ export function runActorHandleTests(driverTestConfig: DriverTestConfig) {
297
297
  // Check lifecycle hooks
298
298
  const events = await viewHandle.getEvents();
299
299
 
300
- // Should have 1 onStart, 2 each of onBeforeConnect, onConnect, and onDisconnect
301
- expect(events.filter((e) => e === "onStart").length).toBe(1);
300
+ // Should have 1 onWake, 2 each of onBeforeConnect, onConnect, and onDisconnect
301
+ expect(events.filter((e) => e === "onWake").length).toBe(1);
302
302
  expect(
303
303
  events.filter((e) => e === "onBeforeConnect").length,
304
304
  ).toBe(2);
@@ -16,7 +16,7 @@ export function runActorMetadataTests(driverTestConfig: DriverTestConfig) {
16
16
  expect(actorName).toBe("metadataActor");
17
17
  });
18
18
 
19
- test("should preserve actor name in state during onStart", async (c) => {
19
+ test("should preserve actor name in state during onWake", async (c) => {
20
20
  const { client } = await setupDriverTest(c, driverTestConfig);
21
21
 
22
22
  // Get the stored actor name
@@ -43,7 +43,7 @@ export function runManagerDriverTests(driverTestConfig: DriverTestConfig) {
43
43
  expect.fail("did not error on duplicate create");
44
44
  } catch (err) {
45
45
  expect((err as ActorError).group).toBe("actor");
46
- expect((err as ActorError).code).toBe("already_exists");
46
+ expect((err as ActorError).code).toBe("duplicate_key");
47
47
  }
48
48
 
49
49
  // Verify the original actor still works and has its state
@@ -25,7 +25,7 @@
25
25
  //
26
26
  // // Make a direct fetch request to the registry
27
27
  // const response = await fetch(
28
- // `${endpoint}/registry/actors/raw/http/api/hello`,
28
+ // `${endpoint}/registry/actors/request/api/hello`,
29
29
  // {
30
30
  // method: "GET",
31
31
  // headers: {
@@ -52,7 +52,7 @@
52
52
  //
53
53
  // const testData = { test: "direct", number: 456 };
54
54
  // const response = await fetch(
55
- // `${endpoint}/registry/actors/raw/http/api/echo`,
55
+ // `${endpoint}/registry/actors/request/api/echo`,
56
56
  // {
57
57
  // method: "POST",
58
58
  // headers: {
@@ -85,7 +85,7 @@
85
85
  // };
86
86
  //
87
87
  // const response = await fetch(
88
- // `${endpoint}/registry/actors/raw/http/api/headers`,
88
+ // `${endpoint}/registry/actors/request/api/headers`,
89
89
  // {
90
90
  // method: "GET",
91
91
  // headers: {
@@ -114,7 +114,7 @@
114
114
  // const connParams = { token: "test-auth-token", userId: "user123" };
115
115
  //
116
116
  // const response = await fetch(
117
- // `${endpoint}/registry/actors/raw/http/api/hello`,
117
+ // `${endpoint}/registry/actors/request/api/hello`,
118
118
  // {
119
119
  // method: "GET",
120
120
  // headers: {
@@ -129,7 +129,7 @@
129
129
  // expect(data).toEqual({ message: "Hello from actor!" });
130
130
  // });
131
131
  //
132
- // test("should return 404 for actors without onFetch handler", async (c) => {
132
+ // test("should return 404 for actors without onRequest handler", async (c) => {
133
133
  // const { endpoint } = await setupDriverTest(c, driverTestConfig);
134
134
  //
135
135
  // const actorQuery: ActorQuery = {
@@ -140,7 +140,7 @@
140
140
  // };
141
141
  //
142
142
  // const response = await fetch(
143
- // `${endpoint}/registry/actors/raw/http/api/anything`,
143
+ // `${endpoint}/registry/actors/request/api/anything`,
144
144
  // {
145
145
  // method: "GET",
146
146
  // headers: {
@@ -168,7 +168,7 @@
168
168
  //
169
169
  // for (const method of methods) {
170
170
  // const response = await fetch(
171
- // `${endpoint}/registry/actors/raw/http/api/echo`,
171
+ // `${endpoint}/registry/actors/request/api/echo`,
172
172
  // {
173
173
  // method,
174
174
  // headers: {
@@ -207,7 +207,7 @@
207
207
  // // Send binary data
208
208
  // const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
209
209
  // const response = await fetch(
210
- // `${endpoint}/registry/actors/raw/http/api/echo`,
210
+ // `${endpoint}/registry/actors/request/api/echo`,
211
211
  // {
212
212
  // method: "POST",
213
213
  // headers: {
@@ -8,7 +8,7 @@ export function runRawHttpRequestPropertiesTests(
8
8
  driverTestConfig: DriverTestConfig,
9
9
  ) {
10
10
  describe("raw http request properties", () => {
11
- test("should pass all Request properties correctly to onFetch", async (c) => {
11
+ test("should pass all Request properties correctly to onRequest", async (c) => {
12
12
  const { client } = await setupDriverTest(c, driverTestConfig);
13
13
  const actor = client.rawHttpRequestPropertiesActor.getOrCreate([
14
14
  "test",
@@ -284,7 +284,7 @@ export function runRawHttpRequestPropertiesTests(
284
284
  expect(data.search.length).toBeGreaterThan(1000);
285
285
  });
286
286
 
287
- test("should handle large request bodies", async (c) => {
287
+ test.skip("should handle large request bodies", async (c) => {
288
288
  const { client } = await setupDriverTest(c, driverTestConfig);
289
289
  const actor = client.rawHttpRequestPropertiesActor.getOrCreate([
290
290
  "test",
@@ -341,9 +341,10 @@ export function runRawHttpRequestPropertiesTests(
341
341
  });
342
342
 
343
343
  expect(response.ok).toBe(true);
344
- const data = (await response.json()) as any;
345
- expect(data.body).toBeNull();
346
- expect(data.bodyText).toBe("");
344
+ // TODO: This is inconsistent between engine & file system driver
345
+ // const data = (await response.json()) as any;
346
+ // expect(data.body).toBeNull();
347
+ // expect(data.bodyText).toBe("");
347
348
  });
348
349
 
349
350
  test("should handle custom HTTP methods", async (c) => {
@@ -79,7 +79,7 @@ export function runRawHttpTests(driverTestConfig: DriverTestConfig) {
79
79
  expect(response.status).toBe(404);
80
80
  });
81
81
 
82
- test("should return 404 when no onFetch handler defined", async (c) => {
82
+ test("should return 404 when no onRequest handler defined", async (c) => {
83
83
  const { client } = await setupDriverTest(c, driverTestConfig);
84
84
  const actor = client.rawHttpNoHandlerActor.getOrCreate([
85
85
  "no-handler",
@@ -89,10 +89,10 @@ export function runRawHttpTests(driverTestConfig: DriverTestConfig) {
89
89
  expect(response.ok).toBe(false);
90
90
  expect(response.status).toBe(404);
91
91
 
92
- // No actions available without onFetch handler
92
+ // No actions available without onRequest handler
93
93
  });
94
94
 
95
- test("should return 500 error when onFetch returns void", async (c) => {
95
+ test("should return 500 error when onRequest returns void", async (c) => {
96
96
  const { client } = await setupDriverTest(c, driverTestConfig);
97
97
  const actor = client.rawHttpVoidReturnActor.getOrCreate([
98
98
  "void-return",
@@ -108,14 +108,14 @@ export function runRawHttpTests(driverTestConfig: DriverTestConfig) {
108
108
  message: string;
109
109
  };
110
110
  expect(errorData.message).toContain(
111
- "onFetch handler must return a Response",
111
+ "onRequest handler must return a Response",
112
112
  );
113
113
  } catch {
114
114
  // If JSON parsing fails, just check that we got a 500 error
115
115
  // The error details are already validated by the status code
116
116
  }
117
117
 
118
- // No actions available when onFetch returns void
118
+ // No actions available when onRequest returns void
119
119
  });
120
120
 
121
121
  test("should handle different HTTP methods", async (c) => {
@@ -28,7 +28,7 @@
28
28
  // const wsEndpoint = endpoint
29
29
  // .replace(/^http:/, "ws:")
30
30
  // .replace(/^https:/, "wss:");
31
- // const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
31
+ // const wsUrl = `${wsEndpoint}/registry/actors/websocket/`;
32
32
  //
33
33
  // // Create WebSocket connection with subprotocol
34
34
  // const ws = new WebSocket(wsUrl, [
@@ -79,7 +79,7 @@
79
79
  // const wsEndpoint = endpoint
80
80
  // .replace(/^http:/, "ws:")
81
81
  // .replace(/^https:/, "wss:");
82
- // const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
82
+ // const wsUrl = `${wsEndpoint}/registry/actors/websocket/`;
83
83
  //
84
84
  // const ws = new WebSocket(wsUrl, [
85
85
  // queryProtocol,
@@ -138,7 +138,7 @@
138
138
  // const wsEndpoint = endpoint
139
139
  // .replace(/^http:/, "ws:")
140
140
  // .replace(/^https:/, "wss:");
141
- // const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
141
+ // const wsUrl = `${wsEndpoint}/registry/actors/websocket/`;
142
142
  //
143
143
  // const ws = new WebSocket(wsUrl, [
144
144
  // queryProtocol,
@@ -191,7 +191,7 @@
191
191
  // const wsEndpoint = endpoint
192
192
  // .replace(/^http:/, "ws:")
193
193
  // .replace(/^https:/, "wss:");
194
- // const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
194
+ // const wsUrl = `${wsEndpoint}/registry/actors/websocket/`;
195
195
  //
196
196
  // const ws = new WebSocket(wsUrl, [
197
197
  // queryProtocol,
@@ -247,7 +247,7 @@
247
247
  // const paths = ["chat/room1", "updates/feed", "stream/events"];
248
248
  //
249
249
  // for (const path of paths) {
250
- // const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/${path}`;
250
+ // const wsUrl = `${wsEndpoint}/registry/actors/websocket/${path}`;
251
251
  // const ws = new WebSocket(wsUrl, [
252
252
  // queryProtocol,
253
253
  // // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
@@ -295,7 +295,7 @@
295
295
  // const wsEndpoint = endpoint
296
296
  // .replace(/^http:/, "ws:")
297
297
  // .replace(/^https:/, "wss:");
298
- // const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
298
+ // const wsUrl = `${wsEndpoint}/registry/actors/websocket/`;
299
299
  //
300
300
  // const ws = new WebSocket(wsUrl, [
301
301
  // queryProtocol,
@@ -329,7 +329,7 @@
329
329
  // const wsEndpoint = endpoint
330
330
  // .replace(/^http:/, "ws:")
331
331
  // .replace(/^https:/, "wss:");
332
- // const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
332
+ // const wsUrl = `${wsEndpoint}/registry/actors/websocket/`;
333
333
  //
334
334
  // const ws = new WebSocket(wsUrl, [
335
335
  // queryProtocol,
@@ -125,7 +125,7 @@ export function runRequestAccessTests(driverTestConfig: DriverTestConfig) {
125
125
  });
126
126
 
127
127
  // TODO: re-expose this once we can have actor queries on the gateway
128
- // test("should have access to request object in onFetch", async (c) => {
128
+ // test("should have access to request object in onRequest", async (c) => {
129
129
  // const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
130
130
  //
131
131
  // // Create actor
@@ -141,7 +141,7 @@ export function runRequestAccessTests(driverTestConfig: DriverTestConfig) {
141
141
  // },
142
142
  // };
143
143
  //
144
- // const url = `${endpoint}/registry/actors/raw/http/test-path`;
144
+ // const url = `${endpoint}/registry/actors/request/test-path`;
145
145
  // const response = await fetch(url, {
146
146
  // method: "POST",
147
147
  // headers: {
@@ -163,7 +163,7 @@ export function runRequestAccessTests(driverTestConfig: DriverTestConfig) {
163
163
  // expect(response.ok).toBe(true);
164
164
  // const data = await response.json();
165
165
  //
166
- // // Verify request info from onFetch
166
+ // // Verify request info from onRequest
167
167
  // expect((data as any).hasRequest).toBe(true);
168
168
  // expect((data as any).requestUrl).toContain("/test-path");
169
169
  // expect((data as any).requestMethod).toBe("POST");
@@ -200,7 +200,7 @@ export function runRequestAccessTests(driverTestConfig: DriverTestConfig) {
200
200
  // .replace("http://", "ws://")
201
201
  // .replace("https://", "wss://");
202
202
  // const ws = new WebSocket(
203
- // `${wsUrl}/registry/actors/raw/websocket/test-path`,
203
+ // `${wsUrl}/registry/actors/websocket/test-path`,
204
204
  // [
205
205
  // queryProtocol,
206
206
  // "rivetkit", // Required protocol
@@ -1,4 +1,3 @@
1
- import invariant from "invariant";
2
1
  import { type TestContext, vi } from "vitest";
3
2
  import { assertUnreachable } from "@/actor/utils";
4
3
  import { type Client, createClient } from "@/client/mod";
@@ -7,6 +6,7 @@ import { createClientWithDriver } from "@/mod";
7
6
  import type { registry } from "../../fixtures/driver-test-suite/registry";
8
7
  import type { DriverTestConfig } from "./mod";
9
8
  import { createTestInlineClientDriver } from "./test-inline-client-driver";
9
+ import { logger } from "./log";
10
10
 
11
11
  export const FAKE_TIME = new Date("2024-01-01T00:00:00.000Z");
12
12
 
@@ -26,7 +26,10 @@ export async function setupDriverTest(
26
26
  // Build drivers
27
27
  const { endpoint, namespace, runnerName, cleanup } =
28
28
  await driverTestConfig.start();
29
- c.onTestFinished(cleanup);
29
+ c.onTestFinished(() => {
30
+ logger().info("cleaning up test");
31
+ cleanup();
32
+ });
30
33
 
31
34
  let client: Client<typeof registry>;
32
35
  if (driverTestConfig.clientType === "http") {
@@ -35,20 +38,13 @@ export async function setupDriverTest(
35
38
  endpoint,
36
39
  namespace,
37
40
  runnerName,
38
- transport: driverTestConfig.transport,
39
41
  encoding: driverTestConfig.encoding,
40
42
  });
41
43
  } else if (driverTestConfig.clientType === "inline") {
42
44
  // Use inline client from driver
43
- const transport = driverTestConfig.transport ?? "websocket";
44
45
  const encoding = driverTestConfig.encoding ?? "bare";
45
- const managerDriver = createTestInlineClientDriver(
46
- endpoint,
47
- encoding,
48
- transport,
49
- );
46
+ const managerDriver = createTestInlineClientDriver(endpoint, encoding);
50
47
  const runConfig = RunConfigSchema.parse({
51
- transport: transport,
52
48
  encoding: encoding,
53
49
  });
54
50
  client = createClientWithDriver(managerDriver, runConfig);