@rikalabs/akter 0.1.0-alpha.0 → 0.1.0-alpha.3

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 (308) hide show
  1. package/CHANGELOG.md +46 -3
  2. package/README.md +2 -2
  3. package/dist/actor/definition.d.ts +13 -9
  4. package/dist/actor/descriptor.d.ts +2 -2
  5. package/dist/actor/descriptor.js +4 -4
  6. package/dist/client/calls.js +1 -1
  7. package/dist/client/index.d.ts +1 -1
  8. package/dist/client/index.js +1 -1
  9. package/dist/errors/actor.d.ts +12 -42
  10. package/dist/errors/actor.js +13 -42
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.js +1 -1
  13. package/dist/members/payload.d.ts +1 -1
  14. package/dist/protocol/inspection.d.ts +221 -1
  15. package/dist/protocol/inspection.js +151 -2
  16. package/dist/protocol/wire.d.ts +6 -49
  17. package/dist/protocol/wire.js +1 -10
  18. package/dist/runtime/actors.d.ts +3 -0
  19. package/dist/runtime/adoption/backfill.js +1 -1
  20. package/dist/runtime/adoption/enforce.js +2 -2
  21. package/dist/runtime/adoption/observe.js +1 -1
  22. package/dist/runtime/adoption/plan.d.ts +1 -1
  23. package/dist/runtime/adoption/startup.js +1 -1
  24. package/dist/runtime/adoption/status.d.ts +1 -1
  25. package/dist/runtime/app.d.ts +65 -0
  26. package/dist/runtime/app.js +38 -0
  27. package/dist/runtime/connections/holder.d.ts +11 -1
  28. package/dist/runtime/connections/holder.js +8 -4
  29. package/dist/runtime/connections/streams.d.ts +4 -4
  30. package/dist/runtime/content/store.js +15 -11
  31. package/dist/runtime/database/bounded.d.ts +4 -18
  32. package/dist/runtime/database/bounded.js +36 -22
  33. package/dist/runtime/database/coordination.d.ts +12 -3
  34. package/dist/runtime/database/coordination.js +29 -36
  35. package/dist/runtime/database/migrations.d.ts +61 -29
  36. package/dist/runtime/database/migrations.js +375 -139
  37. package/dist/runtime/database/replica.d.ts +4 -1
  38. package/dist/runtime/database/replica.js +4 -1
  39. package/dist/runtime/database/schema.d.ts +13 -0
  40. package/dist/runtime/database/schema.js +13 -0
  41. package/dist/runtime/database/shards.d.ts +31 -13
  42. package/dist/runtime/database/shards.js +38 -26
  43. package/dist/runtime/entity/register.d.ts +8 -1
  44. package/dist/runtime/entity/register.js +58 -7
  45. package/dist/runtime/fleet/checks.js +4 -4
  46. package/dist/runtime/fleet/maintainer.d.ts +1 -1
  47. package/dist/runtime/fleet/maintainer.js +1 -1
  48. package/dist/runtime/index.d.ts +2 -0
  49. package/dist/runtime/index.js +1 -0
  50. package/dist/runtime/inspector/layer.d.ts +20 -0
  51. package/dist/runtime/inspector/layer.js +224 -5
  52. package/dist/runtime/inspector/queries.d.ts +54 -8
  53. package/dist/runtime/inspector/queries.js +84 -15
  54. package/dist/runtime/layer.d.ts +48 -39
  55. package/dist/runtime/layer.js +124 -56
  56. package/dist/runtime/operators/audit.d.ts +3 -0
  57. package/dist/runtime/operators/audit.js +6 -2
  58. package/dist/runtime/operators/repair.js +30 -10
  59. package/dist/runtime/operators/seed.js +4 -2
  60. package/dist/runtime/payloads/versions.d.ts +4 -4
  61. package/dist/runtime/payloads/versions.js +24 -15
  62. package/dist/runtime/queries.js +4 -2
  63. package/dist/runtime/registration.d.ts +5 -2
  64. package/dist/runtime/registration.js +3 -3
  65. package/dist/runtime/runner.d.ts +12 -0
  66. package/dist/runtime/runner.js +12 -0
  67. package/dist/runtime/storage/codec.d.ts +19 -7
  68. package/dist/runtime/storage/codec.js +23 -7
  69. package/dist/runtime/storage/placements.d.ts +6 -1
  70. package/dist/runtime/storage/placements.js +98 -6
  71. package/dist/runtime/storage/retention.d.ts +6 -0
  72. package/dist/runtime/storage/retention.js +25 -13
  73. package/dist/runtime/subscriptions/relay.js +47 -44
  74. package/dist/runtime/subscriptions/storage.d.ts +3 -2
  75. package/dist/runtime/subscriptions/storage.js +9 -6
  76. package/dist/runtime/telemetry/live.d.ts +255 -0
  77. package/dist/runtime/telemetry/live.js +540 -0
  78. package/dist/runtime/telemetry/metrics.d.ts +2 -0
  79. package/dist/runtime/telemetry/metrics.js +4 -1
  80. package/dist/runtime/telemetry/sampler.js +33 -13
  81. package/dist/runtime/telemetry/spans.d.ts +1 -1
  82. package/dist/runtime/telemetry/spans.js +1 -1
  83. package/dist/runtime/topology/locks.d.ts +6 -3
  84. package/dist/runtime/topology/locks.js +27 -4
  85. package/dist/runtime/turn/execute.d.ts +2 -0
  86. package/dist/runtime/turn/execute.js +5 -2
  87. package/dist/runtime/turn/pipeline.d.ts +5 -12
  88. package/dist/runtime/turn/pipeline.js +11 -11
  89. package/dist/runtime/turn/relay.d.ts +13 -3
  90. package/dist/runtime/turn/relay.js +27 -14
  91. package/dist/runtime/turn/rows.js +4 -4
  92. package/dist/runtime/workflows/compatibility.d.ts +1 -1
  93. package/dist/runtime/workflows/compatibility.js +85 -31
  94. package/dist/runtime/workflows/engine.js +20 -17
  95. package/dist/serve/layer.js +3 -2
  96. package/dist/tables/owned.d.ts +1 -1
  97. package/dist/tables/owned.js +1 -1
  98. package/dist/testing/actor-test.d.ts +2 -24
  99. package/dist/testing/actor-test.js +1 -27
  100. package/dist/testing/index.d.ts +0 -12
  101. package/dist/testing/index.js +0 -6
  102. package/package.json +1 -1
  103. package/dist/runtime/database/neki/migrations.d.ts +0 -31
  104. package/dist/runtime/database/neki/migrations.js +0 -276
  105. package/dist/runtime/database/neki/session.d.ts +0 -23
  106. package/dist/runtime/database/neki/session.js +0 -31
  107. package/dist/testing/cluster.d.ts +0 -93
  108. package/dist/testing/cluster.js +0 -296
  109. package/dist/testing/conformance/access.d.ts +0 -5
  110. package/dist/testing/conformance/access.js +0 -531
  111. package/dist/testing/conformance/admission.d.ts +0 -11
  112. package/dist/testing/conformance/admission.js +0 -182
  113. package/dist/testing/conformance/adoption.d.ts +0 -2
  114. package/dist/testing/conformance/adoption.js +0 -1019
  115. package/dist/testing/conformance/assertions.d.ts +0 -202
  116. package/dist/testing/conformance/assertions.js +0 -849
  117. package/dist/testing/conformance/batches.d.ts +0 -41
  118. package/dist/testing/conformance/batches.js +0 -388
  119. package/dist/testing/conformance/blobs.d.ts +0 -14
  120. package/dist/testing/conformance/blobs.js +0 -405
  121. package/dist/testing/conformance/capacity.d.ts +0 -8
  122. package/dist/testing/conformance/capacity.js +0 -433
  123. package/dist/testing/conformance/client.d.ts +0 -5
  124. package/dist/testing/conformance/client.js +0 -719
  125. package/dist/testing/conformance/cold-serve.d.ts +0 -16
  126. package/dist/testing/conformance/cold-serve.js +0 -254
  127. package/dist/testing/conformance/connections/actors.d.ts +0 -1143
  128. package/dist/testing/conformance/connections/actors.js +0 -180
  129. package/dist/testing/conformance/connections/harness.d.ts +0 -1754
  130. package/dist/testing/conformance/connections/harness.js +0 -142
  131. package/dist/testing/conformance/connections/holders.d.ts +0 -4
  132. package/dist/testing/conformance/connections/holders.js +0 -165
  133. package/dist/testing/conformance/connections/lifecycle.d.ts +0 -4
  134. package/dist/testing/conformance/connections/lifecycle.js +0 -113
  135. package/dist/testing/conformance/connections/limits.d.ts +0 -4
  136. package/dist/testing/conformance/connections/limits.js +0 -127
  137. package/dist/testing/conformance/connections/reauthorization.d.ts +0 -4
  138. package/dist/testing/conformance/connections/reauthorization.js +0 -170
  139. package/dist/testing/conformance/connections/resync.d.ts +0 -4
  140. package/dist/testing/conformance/connections/resync.js +0 -360
  141. package/dist/testing/conformance/connections/takeover.d.ts +0 -4
  142. package/dist/testing/conformance/connections/takeover.js +0 -287
  143. package/dist/testing/conformance/connections.d.ts +0 -4
  144. package/dist/testing/conformance/connections.js +0 -15
  145. package/dist/testing/conformance/content-blobs.d.ts +0 -16
  146. package/dist/testing/conformance/content-blobs.js +0 -534
  147. package/dist/testing/conformance/counter.d.ts +0 -16
  148. package/dist/testing/conformance/counter.js +0 -813
  149. package/dist/testing/conformance/cron.d.ts +0 -5
  150. package/dist/testing/conformance/cron.js +0 -665
  151. package/dist/testing/conformance/drain.d.ts +0 -26
  152. package/dist/testing/conformance/drain.js +0 -540
  153. package/dist/testing/conformance/effect-control.d.ts +0 -38
  154. package/dist/testing/conformance/effect-control.js +0 -1059
  155. package/dist/testing/conformance/effects.d.ts +0 -23
  156. package/dist/testing/conformance/effects.js +0 -432
  157. package/dist/testing/conformance/events.d.ts +0 -28
  158. package/dist/testing/conformance/events.js +0 -335
  159. package/dist/testing/conformance/export.d.ts +0 -2
  160. package/dist/testing/conformance/export.js +0 -368
  161. package/dist/testing/conformance/fleet.d.ts +0 -444
  162. package/dist/testing/conformance/fleet.js +0 -1009
  163. package/dist/testing/conformance/groups.d.ts +0 -7
  164. package/dist/testing/conformance/groups.js +0 -353
  165. package/dist/testing/conformance/heap.d.ts +0 -3
  166. package/dist/testing/conformance/heap.js +0 -149
  167. package/dist/testing/conformance/http.d.ts +0 -2809
  168. package/dist/testing/conformance/http.js +0 -1234
  169. package/dist/testing/conformance/inspection-views.d.ts +0 -8
  170. package/dist/testing/conformance/inspection-views.js +0 -272
  171. package/dist/testing/conformance/inspector.d.ts +0 -7
  172. package/dist/testing/conformance/inspector.js +0 -650
  173. package/dist/testing/conformance/mint.d.ts +0 -58
  174. package/dist/testing/conformance/mint.js +0 -692
  175. package/dist/testing/conformance/multi-runner.d.ts +0 -8
  176. package/dist/testing/conformance/multi-runner.js +0 -403
  177. package/dist/testing/conformance/neki/plan.d.ts +0 -19
  178. package/dist/testing/conformance/neki/plan.js +0 -30
  179. package/dist/testing/conformance/observability.d.ts +0 -3
  180. package/dist/testing/conformance/observability.js +0 -343
  181. package/dist/testing/conformance/offline.d.ts +0 -4
  182. package/dist/testing/conformance/offline.js +0 -474
  183. package/dist/testing/conformance/operator-harness.d.ts +0 -57
  184. package/dist/testing/conformance/operator-harness.js +0 -78
  185. package/dist/testing/conformance/operator.d.ts +0 -3
  186. package/dist/testing/conformance/operator.js +0 -379
  187. package/dist/testing/conformance/outbox-cross-shard.d.ts +0 -14
  188. package/dist/testing/conformance/outbox-cross-shard.js +0 -160
  189. package/dist/testing/conformance/outbox.d.ts +0 -36
  190. package/dist/testing/conformance/outbox.js +0 -437
  191. package/dist/testing/conformance/payload-migrations.d.ts +0 -3
  192. package/dist/testing/conformance/payload-migrations.js +0 -612
  193. package/dist/testing/conformance/pipeline.d.ts +0 -3
  194. package/dist/testing/conformance/pipeline.js +0 -1040
  195. package/dist/testing/conformance/placement.d.ts +0 -22
  196. package/dist/testing/conformance/placement.js +0 -539
  197. package/dist/testing/conformance/platform.d.ts +0 -40
  198. package/dist/testing/conformance/platform.js +0 -101
  199. package/dist/testing/conformance/progress.d.ts +0 -39
  200. package/dist/testing/conformance/progress.js +0 -666
  201. package/dist/testing/conformance/properties.d.ts +0 -6
  202. package/dist/testing/conformance/properties.js +0 -295
  203. package/dist/testing/conformance/protocols.d.ts +0 -4
  204. package/dist/testing/conformance/protocols.js +0 -618
  205. package/dist/testing/conformance/provider/advertise.d.ts +0 -21
  206. package/dist/testing/conformance/provider/advertise.js +0 -44
  207. package/dist/testing/conformance/read-your-writes.d.ts +0 -20
  208. package/dist/testing/conformance/read-your-writes.js +0 -192
  209. package/dist/testing/conformance/reducers.d.ts +0 -8
  210. package/dist/testing/conformance/reducers.js +0 -258
  211. package/dist/testing/conformance/relay.d.ts +0 -42
  212. package/dist/testing/conformance/relay.js +0 -1115
  213. package/dist/testing/conformance/restore.d.ts +0 -43
  214. package/dist/testing/conformance/restore.js +0 -341
  215. package/dist/testing/conformance/retention.d.ts +0 -14
  216. package/dist/testing/conformance/retention.js +0 -463
  217. package/dist/testing/conformance/rls.d.ts +0 -24
  218. package/dist/testing/conformance/rls.js +0 -576
  219. package/dist/testing/conformance/simulation.d.ts +0 -31
  220. package/dist/testing/conformance/simulation.js +0 -167
  221. package/dist/testing/conformance/single-shard.d.ts +0 -2
  222. package/dist/testing/conformance/single-shard.js +0 -125
  223. package/dist/testing/conformance/singleton.d.ts +0 -3
  224. package/dist/testing/conformance/singleton.js +0 -293
  225. package/dist/testing/conformance/statements.d.ts +0 -60
  226. package/dist/testing/conformance/statements.js +0 -108
  227. package/dist/testing/conformance/streams.d.ts +0 -7
  228. package/dist/testing/conformance/streams.js +0 -280
  229. package/dist/testing/conformance/subscriptions/access.d.ts +0 -4
  230. package/dist/testing/conformance/subscriptions/access.js +0 -98
  231. package/dist/testing/conformance/subscriptions/actors.d.ts +0 -4910
  232. package/dist/testing/conformance/subscriptions/actors.js +0 -372
  233. package/dist/testing/conformance/subscriptions/cluster.d.ts +0 -4
  234. package/dist/testing/conformance/subscriptions/cluster.js +0 -89
  235. package/dist/testing/conformance/subscriptions/delivery.d.ts +0 -4
  236. package/dist/testing/conformance/subscriptions/delivery.js +0 -253
  237. package/dist/testing/conformance/subscriptions/deploys.d.ts +0 -4
  238. package/dist/testing/conformance/subscriptions/deploys.js +0 -162
  239. package/dist/testing/conformance/subscriptions/epochs.d.ts +0 -4
  240. package/dist/testing/conformance/subscriptions/epochs.js +0 -169
  241. package/dist/testing/conformance/subscriptions/failures.d.ts +0 -4
  242. package/dist/testing/conformance/subscriptions/failures.js +0 -108
  243. package/dist/testing/conformance/subscriptions/feeds.d.ts +0 -4
  244. package/dist/testing/conformance/subscriptions/feeds.js +0 -218
  245. package/dist/testing/conformance/subscriptions/harness.d.ts +0 -124
  246. package/dist/testing/conformance/subscriptions/harness.js +0 -143
  247. package/dist/testing/conformance/subscriptions/operator.d.ts +0 -4
  248. package/dist/testing/conformance/subscriptions/operator.js +0 -128
  249. package/dist/testing/conformance/subscriptions/retention.d.ts +0 -4
  250. package/dist/testing/conformance/subscriptions/retention.js +0 -288
  251. package/dist/testing/conformance/subscriptions/routing.d.ts +0 -4
  252. package/dist/testing/conformance/subscriptions/routing.js +0 -179
  253. package/dist/testing/conformance/subscriptions.d.ts +0 -4
  254. package/dist/testing/conformance/subscriptions.js +0 -19
  255. package/dist/testing/conformance/tables.d.ts +0 -125
  256. package/dist/testing/conformance/tables.js +0 -664
  257. package/dist/testing/conformance/transports/actors.d.ts +0 -1907
  258. package/dist/testing/conformance/transports/actors.js +0 -163
  259. package/dist/testing/conformance/transports/client.d.ts +0 -3
  260. package/dist/testing/conformance/transports/client.js +0 -237
  261. package/dist/testing/conformance/transports/feeds.d.ts +0 -3
  262. package/dist/testing/conformance/transports/feeds.js +0 -232
  263. package/dist/testing/conformance/transports/harness.d.ts +0 -93
  264. package/dist/testing/conformance/transports/harness.js +0 -84
  265. package/dist/testing/conformance/transports/streams.d.ts +0 -3
  266. package/dist/testing/conformance/transports/streams.js +0 -96
  267. package/dist/testing/conformance/transports/websocket.d.ts +0 -3
  268. package/dist/testing/conformance/transports/websocket.js +0 -384
  269. package/dist/testing/conformance/transports/wire.d.ts +0 -141
  270. package/dist/testing/conformance/transports/wire.js +0 -204
  271. package/dist/testing/conformance/transports.d.ts +0 -3
  272. package/dist/testing/conformance/transports.js +0 -11
  273. package/dist/testing/conformance/watch.d.ts +0 -59
  274. package/dist/testing/conformance/watch.js +0 -879
  275. package/dist/testing/conformance/workflow-engine.d.ts +0 -97
  276. package/dist/testing/conformance/workflow-engine.js +0 -253
  277. package/dist/testing/conformance/workflow-versions.d.ts +0 -3
  278. package/dist/testing/conformance/workflow-versions.js +0 -545
  279. package/dist/testing/conformance/workflows/access.d.ts +0 -4
  280. package/dist/testing/conformance/workflows/access.js +0 -147
  281. package/dist/testing/conformance/workflows/actors.d.ts +0 -2317
  282. package/dist/testing/conformance/workflows/actors.js +0 -305
  283. package/dist/testing/conformance/workflows/basics.d.ts +0 -4
  284. package/dist/testing/conformance/workflows/basics.js +0 -144
  285. package/dist/testing/conformance/workflows/engine.d.ts +0 -4
  286. package/dist/testing/conformance/workflows/engine.js +0 -80
  287. package/dist/testing/conformance/workflows/guards.d.ts +0 -4
  288. package/dist/testing/conformance/workflows/guards.js +0 -172
  289. package/dist/testing/conformance/workflows/harness.d.ts +0 -14
  290. package/dist/testing/conformance/workflows/harness.js +0 -44
  291. package/dist/testing/conformance/workflows/recovery.d.ts +0 -4
  292. package/dist/testing/conformance/workflows/recovery.js +0 -181
  293. package/dist/testing/conformance/workflows/starts.d.ts +0 -4
  294. package/dist/testing/conformance/workflows/starts.js +0 -57
  295. package/dist/testing/conformance/workflows/suspension.d.ts +0 -4
  296. package/dist/testing/conformance/workflows/suspension.js +0 -106
  297. package/dist/testing/conformance/workflows/waits.d.ts +0 -4
  298. package/dist/testing/conformance/workflows/waits.js +0 -284
  299. package/dist/testing/conformance/workflows.d.ts +0 -4
  300. package/dist/testing/conformance/workflows.js +0 -19
  301. package/dist/testing/conformance.d.ts +0 -330
  302. package/dist/testing/conformance.js +0 -364
  303. package/dist/testing/foundation.d.ts +0 -41
  304. package/dist/testing/foundation.js +0 -517
  305. package/dist/testing/simulate-cluster.d.ts +0 -112
  306. package/dist/testing/simulate-cluster.js +0 -257
  307. package/dist/testing/simulate.d.ts +0 -90
  308. package/dist/testing/simulate.js +0 -127
@@ -1,433 +0,0 @@
1
- import { Clock, Context, Crypto, Deferred, DateTime, Effect, Exit, Fiber, Layer, Option, Schema, Scope, } from "effect";
2
- import { Actor, ActorError, Actors, CommandExpired, MailboxFull, RunnerAtCapacity, } from "../../index.js";
3
- import { commandTimes } from "../../identity/command.js";
4
- import { ACTIVATION_MAILBOX } from "../../runtime/entity/register.js";
5
- import { TurnConnections } from "../../runtime/turn/pipeline.js";
6
- import { TurnHooks } from "../../runtime/turn/hooks.js";
7
- import { ActorTest } from "../actor-test.js";
8
- import { ActorCluster } from "../cluster.js";
9
- const Touch = Actor.command("Touch", { success: Schema.Finite });
10
- const Hold = Actor.command("Hold");
11
- let hold = Effect.void;
12
- const count = Actor.state({
13
- count: Schema.Finite.pipe(Schema.withDecodingDefault(Effect.succeed(0))),
14
- });
15
- const Unbounded = Actor.make("CapacityUnbounded", {
16
- key: Schema.NonEmptyString,
17
- state: count,
18
- api: { Touch },
19
- policy: { deliveryTimeout: "5 seconds" },
20
- });
21
- const Bounded = Actor.make("CapacityBounded", {
22
- key: Schema.NonEmptyString,
23
- state: count,
24
- api: { Touch, Hold },
25
- policy: { deliveryTimeout: "5 seconds", mailboxCapacity: 1 },
26
- });
27
- const Sleepy = Actor.make("CapacitySleepy", {
28
- key: Schema.NonEmptyString,
29
- state: count,
30
- api: { Touch },
31
- policy: { deliveryTimeout: "20 seconds", hibernateAfter: "1 second" },
32
- });
33
- const Hot = Actor.make("CapacityHot", {
34
- key: Schema.NonEmptyString,
35
- state: count,
36
- api: { Touch },
37
- policy: { deliveryTimeout: "30 seconds" },
38
- });
39
- const WarmUp = Actor.make("CapacityWarmUp", { key: Schema.NonEmptyString, api: { Touch } });
40
- const Patient = Actor.make("CapacityPatient", { key: Schema.NonEmptyString, api: { Touch } });
41
- const Quick = Actor.make("CapacityQuick", {
42
- key: Schema.NonEmptyString,
43
- api: { Touch },
44
- policy: { deliveryTimeout: "20 seconds", hibernateAfter: "1 second" },
45
- });
46
- /**
47
- * `Patient` comes first, so its type, with the default 60-second
48
- * `hibernateAfter`, registers before `Quick`'s one second.
49
- */
50
- const HibernationLive = Layer.mergeAll(Patient.toLayer(Effect.succeed({ Touch: () => Effect.succeed(0) })), Quick.toLayer(Effect.succeed({ Touch: () => Effect.succeed(0) })));
51
- /** The longest an idle activation may outlive its `hibernateAfter`: the idle sweep runs every 5 seconds. */
52
- const SWEEP_MS = 5_000;
53
- const CapacityLive = Layer.mergeAll(Sleepy.toLayer(Effect.succeed({
54
- Touch: Effect.fnUntraced(function* () {
55
- const turn = yield* Sleepy.Turn;
56
- yield* turn.state.set({ count: turn.state.count + 1 });
57
- return turn.state.count;
58
- }),
59
- })), Unbounded.toLayer(Effect.succeed({
60
- Touch: Effect.fnUntraced(function* () {
61
- const turn = yield* Unbounded.Turn;
62
- yield* turn.state.set({ count: turn.state.count + 1 });
63
- return turn.state.count;
64
- }),
65
- })), Bounded.toLayer(Effect.succeed({
66
- Touch: Effect.fnUntraced(function* () {
67
- const turn = yield* Bounded.Turn;
68
- yield* turn.state.set({ count: turn.state.count + 1 });
69
- return turn.state.count;
70
- }),
71
- Hold: () => Effect.suspend(() => hold),
72
- })), Hot.toLayer(Effect.succeed({
73
- Touch: Effect.fnUntraced(function* () {
74
- const turn = yield* Hot.Turn;
75
- yield* turn.state.set({ count: turn.state.count + 1 });
76
- return turn.state.count;
77
- }),
78
- })), WarmUp.toLayer(Effect.succeed({ Touch: () => Effect.succeed(0) })));
79
- /**
80
- * A runtime of its own on a fresh database, so only these actors hold resident
81
- * slots. A runner on Postgres takes seconds to acquire its shards, so one
82
- * warm-up command with a long delivery timeout runs first, in a slot of its own.
83
- */
84
- const withCapacity = (environment, limits, body) => environment.run(Effect.gen(function* () {
85
- const crypto = yield* Crypto.Crypto;
86
- const database = yield* environment.freshDatabase;
87
- const services = yield* Layer.build(Layer.fresh(CapacityLive.pipe(Layer.provideMerge(ActorTest.layer({
88
- database,
89
- maxResidentActors: limits.maxResidentActors + 1,
90
- admission: limits.admission,
91
- }).pipe(Layer.provide(Layer.succeed(TurnHooks, { at: limits.at ?? (() => Effect.void) })))), Layer.provide(Layer.succeed(Crypto.Crypto, crypto)), Layer.orDie)));
92
- return yield* WarmUp.get("warm-up").pipe(Effect.flatMap((actor) => actor.Touch()), Effect.andThen(body), Effect.provideContext(services));
93
- }));
94
- const reasonOf = (exit) => {
95
- if (Exit.isSuccess(exit))
96
- return "success";
97
- const error = Exit.findErrorOption(exit);
98
- return Option.isSome(error) && Schema.is(ActorError)(error.value)
99
- ? error.value.reason._tag
100
- : "other";
101
- };
102
- /**
103
- * Capacity cases: a caller over capacity gets `RunnerAtCapacity` after
104
- * `deliveryTimeout`, a resident bounded actor with a full mailbox reports
105
- * `MailboxFull`, and a full runner or default-bounded activation refuses at
106
- * once with `ActorUnavailable`.
107
- */
108
- export const capacityConformance = [
109
- {
110
- name: "a capacity-rejected command that expires before its first admission never runs or writes a receipt",
111
- timeoutMs: 30_000,
112
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 1 }, Effect.gen(function* () {
113
- const test = yield* ActorTest;
114
- const resident = yield* Sleepy.get("expiry-resident");
115
- const waiting = yield* Sleepy.get("expiry-waiting");
116
- expect(yield* resident.Touch()).toBe(1);
117
- const minted = commandTimes(yield* (yield* Actors).mintCommandId);
118
- const now = DateTime.toEpochMillis(yield* test.now);
119
- const id = `v1.${now + 500 - (minted.expiresAt - minted.issuedAt)}.${now + 500}.d1a434bc-10c3-444a-8c76-223f6169c958`;
120
- const holding = yield* test.pauseNext("beforeCommit");
121
- const occupied = yield* resident.Touch().pipe(Effect.forkChild);
122
- yield* holding.reached;
123
- const call = yield* waiting
124
- .Touch()
125
- .pipe(Actor.commandId(id), Effect.flip, Effect.forkChild);
126
- yield* Effect.sleep("800 millis");
127
- yield* holding.release;
128
- expect(yield* Fiber.join(occupied)).toBe(2);
129
- expect((yield* Fiber.join(call)).reason).toEqual(CommandExpired.make({ commandId: id }));
130
- const inspected = yield* test.inspect(waiting.ref);
131
- expect(inspected.receipts).toBe(0);
132
- expect(inspected.state).toEqual({});
133
- })),
134
- },
135
- {
136
- name: "over-capacity load on an unbounded mailbox fails RunnerAtCapacity after deliveryTimeout, never MailboxFull",
137
- timeoutMs: 30_000,
138
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 8 }, Effect.gen(function* () {
139
- const test = yield* ActorTest;
140
- const ids = Array.from({ length: 32 }, (_, index) => `actor-${index}`);
141
- const outcomes = yield* Effect.forEach([...ids, ...ids], (id) => Effect.gen(function* () {
142
- const actor = yield* Unbounded.get(id);
143
- const started = yield* Clock.currentTimeMillis;
144
- const exit = yield* actor.Touch().pipe(Effect.exit);
145
- return { id, exit, elapsedMs: (yield* Clock.currentTimeMillis) - started };
146
- }), { concurrency: "unbounded" });
147
- const reasons = outcomes.map(({ exit }) => reasonOf(exit));
148
- expect(reasons.filter((reason) => reason === "MailboxFull")).toEqual([]);
149
- expect(reasons.filter((reason) => reason !== "success" && reason !== "RunnerAtCapacity")).toEqual([]);
150
- const admitted = new Set(outcomes.filter(({ exit }) => Exit.isSuccess(exit)).map(({ id }) => id));
151
- expect(admitted.size).toBe(8);
152
- const rejected = outcomes.filter(({ exit }) => Exit.isFailure(exit));
153
- expect(rejected.length).toBe(48);
154
- for (const { id, exit, elapsedMs } of rejected) {
155
- expect(admitted.has(id)).toBe(false);
156
- expect(elapsedMs >= 4500).toBe(true);
157
- expect(Exit.findErrorOption(exit)).toMatchObject({
158
- value: { reason: RunnerAtCapacity.make({}), isRetryable: true },
159
- });
160
- }
161
- for (const id of ids) {
162
- const inspection = yield* test.inspect((yield* Unbounded.get(id)).ref);
163
- expect(inspection.receipts).toBe(admitted.has(id) ? 2 : 0);
164
- }
165
- })),
166
- },
167
- {
168
- name: "a bounded mailbox that is not resident reports RunnerAtCapacity, not MailboxFull",
169
- timeoutMs: 30_000,
170
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 1 }, Effect.gen(function* () {
171
- expect(yield* (yield* Bounded.get("resident")).Touch()).toBe(1);
172
- const exit = yield* (yield* Bounded.get("waiting")).Touch().pipe(Effect.exit);
173
- expect(reasonOf(exit)).toBe("RunnerAtCapacity");
174
- })),
175
- },
176
- {
177
- name: "a resident bounded actor with a full mailbox still reports MailboxFull",
178
- requiresIndependentConnections: true,
179
- timeoutMs: 30_000,
180
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 10 }, Effect.gen(function* () {
181
- const actor = yield* Bounded.get("busy");
182
- const reached = yield* Deferred.make();
183
- const release = yield* Deferred.make();
184
- hold = Deferred.succeed(reached, undefined).pipe(Effect.andThen(Deferred.await(release)));
185
- const held = yield* actor.Hold().pipe(Effect.forkScoped);
186
- yield* Deferred.await(reached);
187
- const exit = yield* actor.Touch().pipe(Effect.exit);
188
- expect(Exit.findErrorOption(exit)).toMatchObject({
189
- value: { reason: MailboxFull.make({}) },
190
- });
191
- yield* Deferred.succeed(release, undefined);
192
- yield* Fiber.await(held);
193
- hold = Effect.void;
194
- })),
195
- },
196
- {
197
- name: "a runner holding admission.concurrency commands refuses one that waits out admission.wait with ActorUnavailable, and that id runs exactly once after a slot frees",
198
- timeoutMs: 30_000,
199
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 8, admission: { concurrency: 2, wait: "50 millis" } }, Effect.gen(function* () {
200
- const test = yield* ActorTest;
201
- const first = yield* test.pauseNext("beforeDelivery");
202
- const second = yield* test.pauseNext("beforeDelivery");
203
- const heldA = yield* (yield* Unbounded.get("held-a")).Touch().pipe(Effect.forkScoped);
204
- const heldB = yield* (yield* Unbounded.get("held-b")).Touch().pipe(Effect.forkScoped);
205
- yield* first.reached;
206
- yield* second.reached;
207
- const refused = yield* Unbounded.get("refused");
208
- const touch = refused.Touch();
209
- const exit = yield* touch.pipe(Effect.exit);
210
- expect(reasonOf(exit)).toBe("ActorUnavailable");
211
- const refusal = Exit.findErrorOption(exit).pipe(Option.filter(Schema.is(ActorError)), Option.getOrThrow);
212
- expect(refusal.isRetryable).toBe(true);
213
- expect(Option.isSome(refusal.retryAfter)).toBe(true);
214
- expect(yield* test.inspect(refused.ref)).toMatchObject({
215
- generation: undefined,
216
- receipts: 0,
217
- });
218
- yield* first.release;
219
- yield* second.release;
220
- expect(yield* Fiber.join(heldA)).toBe(1);
221
- expect(yield* Fiber.join(heldB)).toBe(1);
222
- expect(yield* touch).toBe(1);
223
- expect(yield* touch).toBe(1);
224
- expect(yield* test.inspect(refused.ref)).toMatchObject({
225
- receipts: 1,
226
- state: { count: 1 },
227
- });
228
- })),
229
- },
230
- {
231
- name: "interrupting a command waiter does not free its runtime admission slot or cancel its accepted command",
232
- timeoutMs: 30_000,
233
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 8, admission: { concurrency: 1, wait: "50 millis" } }, Effect.gen(function* () {
234
- const test = yield* ActorTest;
235
- const actor = yield* Unbounded.get("interrupted");
236
- const pause = yield* test.pauseNext("beforeDelivery");
237
- const touch = actor.Touch();
238
- const caller = yield* touch.pipe(Effect.forkScoped);
239
- yield* pause.reached;
240
- yield* Fiber.interrupt(caller);
241
- const other = yield* Unbounded.get("still-full");
242
- expect(reasonOf(yield* other.Touch().pipe(Effect.exit))).toBe("ActorUnavailable");
243
- expect(yield* test.inspect(other.ref)).toMatchObject({ receipts: 0 });
244
- yield* pause.release;
245
- yield* Effect.sleep("10 millis").pipe(Effect.repeat({
246
- until: Effect.fnUntraced(function* () {
247
- return (yield* test.inspect(actor.ref)).receipts === 1;
248
- }),
249
- }));
250
- expect(yield* touch).toBe(1);
251
- expect(yield* test.inspect(actor.ref)).toMatchObject({ receipts: 1, state: { count: 1 } });
252
- expect(yield* other.Touch()).toBe(1);
253
- })),
254
- },
255
- {
256
- name: "a delivery timeout retains admission until the accepted turn settles, then the same id replays exactly once",
257
- requiresIndependentConnections: true,
258
- timeoutMs: 30_000,
259
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 8, admission: { concurrency: 1, wait: "50 millis" } }, Effect.gen(function* () {
260
- const test = yield* ActorTest;
261
- const actor = yield* Unbounded.get("timed-out");
262
- const pause = yield* test.pauseNext("beforeHandler");
263
- const touch = actor.Touch();
264
- const caller = yield* touch.pipe(Effect.forkScoped);
265
- yield* pause.reached;
266
- expect(reasonOf(yield* Fiber.await(caller))).toBe("Timeout");
267
- const other = yield* Unbounded.get("timeout-still-full");
268
- expect(reasonOf(yield* other.Touch().pipe(Effect.exit))).toBe("ActorUnavailable");
269
- expect(yield* test.inspect(other.ref)).toMatchObject({ receipts: 0 });
270
- yield* pause.release;
271
- yield* Effect.sleep("10 millis").pipe(Effect.repeat({
272
- until: Effect.fnUntraced(function* () {
273
- return (yield* test.inspect(actor.ref)).receipts === 1;
274
- }),
275
- }));
276
- expect(yield* touch).toBe(1);
277
- expect(yield* test.inspect(actor.ref)).toMatchObject({ receipts: 1, state: { count: 1 } });
278
- expect(yield* other.Touch()).toBe(1);
279
- })),
280
- },
281
- {
282
- name: "a full turn checkout queue refuses before the handler or fence and retries the same id exactly once after capacity returns",
283
- requiresIndependentConnections: true,
284
- timeoutMs: 30_000,
285
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 8 }, Effect.gen(function* () {
286
- const turns = Option.getOrThrow(yield* Effect.serviceOption(TurnConnections));
287
- const test = yield* ActorTest;
288
- const held = yield* Scope.fork(yield* Effect.scope);
289
- yield* Effect.forEach(Array.from({ length: 10 }), () => turns.lease.pipe(Scope.provide(held)));
290
- const release = yield* Deferred.make();
291
- const queued = yield* Effect.forEach(Array.from({ length: 64 }), () => Effect.scoped(Effect.andThen(turns.lease, Deferred.await(release))).pipe(Effect.forkScoped));
292
- yield* Effect.yieldNow.pipe(Effect.repeat({ until: () => turns.sessions().waiting === 64 }));
293
- const actor = yield* Unbounded.get("pool-refused");
294
- const touch = actor.Touch();
295
- const exit = yield* touch.pipe(Effect.exit);
296
- expect(reasonOf(exit)).toBe("ActorUnavailable");
297
- expect(yield* test.inspect(actor.ref)).toMatchObject({
298
- generation: undefined,
299
- receipts: 0,
300
- });
301
- for (const fiber of queued)
302
- yield* Fiber.interrupt(fiber);
303
- yield* Scope.close(held, Exit.void);
304
- expect(yield* touch).toBe(1);
305
- expect(yield* touch).toBe(1);
306
- expect(yield* test.inspect(actor.ref)).toMatchObject({ receipts: 1, state: { count: 1 } });
307
- })),
308
- },
309
- {
310
- name: "an activation holding its default mailbox bound refuses the next command at once with ActorUnavailable, never MailboxFull, and that command never runs",
311
- requiresIndependentConnections: true,
312
- timeoutMs: 90_000,
313
- run: ({ environment, expect }) => {
314
- let waiting = 0;
315
- return withCapacity(environment, {
316
- maxResidentActors: 8,
317
- admission: { concurrency: ACTIVATION_MAILBOX * 2 },
318
- at: (point, request) => Effect.sync(() => {
319
- if (point === "queued" && request.ref.id === "hot")
320
- waiting += 1;
321
- }),
322
- }, Effect.gen(function* () {
323
- const test = yield* ActorTest;
324
- const actor = yield* Hot.get("hot");
325
- const paused = yield* test.pauseNext("beforeHandler");
326
- const held = yield* actor.Touch().pipe(Effect.forkScoped);
327
- yield* paused.reached;
328
- const queued = yield* Effect.forEach(Array.from({ length: ACTIVATION_MAILBOX - 1 }), (_, index) => Effect.gen(function* () {
329
- const fiber = yield* actor.Touch().pipe(Effect.forkScoped);
330
- yield* Effect.yieldNow.pipe(Effect.repeat({ until: () => waiting === index + 2 }));
331
- return fiber;
332
- }));
333
- const overflow = actor.Touch();
334
- const exit = yield* overflow.pipe(Effect.exit);
335
- expect(reasonOf(exit)).toBe("ActorUnavailable");
336
- expect(waiting).toBe(ACTIVATION_MAILBOX);
337
- yield* paused.release;
338
- yield* Fiber.join(held);
339
- const values = yield* Effect.forEach(queued, Fiber.join);
340
- expect(values.length).toBe(ACTIVATION_MAILBOX - 1);
341
- expect(yield* test.inspect(actor.ref)).toMatchObject({
342
- receipts: ACTIVATION_MAILBOX,
343
- state: { count: ACTIVATION_MAILBOX },
344
- });
345
- expect(yield* overflow).toBe(ACTIVATION_MAILBOX + 1);
346
- expect(yield* test.inspect(actor.ref)).toMatchObject({
347
- receipts: ACTIVATION_MAILBOX + 1,
348
- state: { count: ACTIVATION_MAILBOX + 1 },
349
- });
350
- }));
351
- },
352
- },
353
- {
354
- name: "a remote default mailbox refuses with serialized ActorUnavailable and retryAfter without retrying or receipting the command",
355
- requiresIndependentConnections: true,
356
- timeoutMs: 90_000,
357
- run: ({ environment, expect }) => environment.run(Effect.gen(function* () {
358
- const services = yield* Layer.build(ActorTest.cluster({
359
- database: yield* environment.freshDatabase,
360
- runners: 2,
361
- holdersOnly: [1],
362
- shardLockExpiration: "5 seconds",
363
- admission: { concurrency: ACTIVATION_MAILBOX * 2 },
364
- actors: CapacityLive,
365
- }).pipe(Layer.provide(Layer.succeed(Crypto.Crypto, yield* Crypto.Crypto))));
366
- const cluster = Context.get(services, ActorCluster);
367
- yield* cluster.ready;
368
- const actor = yield* cluster.on(1)(Hot.get("remote-hot"));
369
- expect(yield* cluster.on(1)(actor.Touch())).toBe(1);
370
- const pause = yield* cluster.on(0)(Effect.flatMap(ActorTest, (test) => test.pauseNext("beforeHandler")));
371
- const held = yield* cluster.on(1)(actor.Touch()).pipe(Effect.forkScoped);
372
- yield* pause.reached;
373
- const queued = yield* Effect.forEach(Array.from({ length: ACTIVATION_MAILBOX - 1 }), () => Effect.gen(function* () {
374
- const reached = yield* cluster.on(0)(Effect.flatMap(ActorTest, (test) => test.pauseNext("queued")));
375
- const fiber = yield* cluster.on(1)(actor.Touch()).pipe(Effect.forkScoped);
376
- yield* reached.reached;
377
- yield* reached.release;
378
- return fiber;
379
- }));
380
- const overflow = actor.Touch();
381
- const exit = yield* cluster.on(1)(overflow).pipe(Effect.exit);
382
- expect(reasonOf(exit)).toBe("ActorUnavailable");
383
- const error = Exit.findErrorOption(exit).pipe(Option.filter(Schema.is(ActorError)), Option.getOrThrow);
384
- expect(error.reason).toMatchObject({ overloaded: true });
385
- expect(error.isRetryable).toBe(true);
386
- const retryAfter = Option.getOrThrow(error.retryAfter);
387
- expect(retryAfter >= 125 && retryAfter <= 375).toBe(true);
388
- yield* pause.release;
389
- yield* Fiber.join(held);
390
- yield* Effect.forEach(queued, Fiber.join);
391
- const inspect = cluster.on(0)(Effect.flatMap(ActorTest, (test) => test.inspect(actor.ref)));
392
- expect(yield* inspect).toMatchObject({
393
- receipts: ACTIVATION_MAILBOX + 1,
394
- state: { count: ACTIVATION_MAILBOX + 1 },
395
- });
396
- expect(yield* cluster.on(1)(overflow)).toBe(ACTIVATION_MAILBOX + 2);
397
- expect(yield* cluster.on(1)(overflow)).toBe(ACTIVATION_MAILBOX + 2);
398
- expect(yield* inspect).toMatchObject({
399
- receipts: ACTIVATION_MAILBOX + 2,
400
- state: { count: ACTIVATION_MAILBOX + 2 },
401
- });
402
- })),
403
- },
404
- {
405
- name: "a caller over capacity succeeds on retry once an idle actor hibernates",
406
- timeoutMs: 40_000,
407
- run: ({ environment, expect }) => withCapacity(environment, { maxResidentActors: 2 }, Effect.gen(function* () {
408
- const test = yield* ActorTest;
409
- expect(yield* (yield* Sleepy.get("first")).Touch()).toBe(1);
410
- expect(yield* (yield* Sleepy.get("second")).Touch()).toBe(1);
411
- const third = yield* Sleepy.get("third");
412
- expect(yield* third.Touch()).toBe(1);
413
- expect(yield* test.inspect(third.ref)).toMatchObject({ receipts: 1, state: { count: 1 } });
414
- })),
415
- },
416
- {
417
- name: "hibernates an idle actor within one idle sweep of its hibernateAfter when a type with a longer one registered first",
418
- timeoutMs: 45_000,
419
- run: ({ environment, expect }) => environment.run(Effect.gen(function* () {
420
- const database = yield* environment.freshDatabase;
421
- const services = yield* Layer.build(Layer.fresh(HibernationLive.pipe(Layer.provideMerge(ActorTest.layer({ database, maxResidentActors: 2 })), Layer.provide(Layer.succeed(Crypto.Crypto, yield* Crypto.Crypto)), Layer.orDie)));
422
- yield* Effect.gen(function* () {
423
- yield* (yield* Patient.get("stays")).Touch();
424
- yield* (yield* Quick.get("idle")).Touch();
425
- const waiting = yield* Quick.get("waiting");
426
- const started = yield* Clock.currentTimeMillis;
427
- const exit = yield* waiting.Touch().pipe(Effect.exit);
428
- expect(reasonOf(exit)).toBe("success");
429
- expect((yield* Clock.currentTimeMillis) - started < 1_000 + SWEEP_MS + 3_000).toBe(true);
430
- }).pipe(Effect.provideContext(services));
431
- })),
432
- },
433
- ];
@@ -1,5 +0,0 @@
1
- import type { ConformanceCase, ConformanceSuite } from "../conformance.ts";
2
- /** Client cases: optimistic reducers apply at once, converge on committed replies, and roll back when the server rejects them. */
3
- export declare const clientConformance: ReadonlyArray<ConformanceCase>;
4
- /** Client cases call the served HTTP actors. */
5
- export declare const clientSuite: ConformanceSuite;