@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,128 +0,0 @@
1
- import { Effect, Exit, Option } from "effect";
2
- import { OperatorRuntime } from "../../../runtime/operators/repair.js";
3
- import { ActorTest } from "../../actor-test.js";
4
- import { SubFollower, SubOrder } from "./actors.js";
5
- import { drain, followerLog, query, run, sourceRows } from "./harness.js";
6
- /** Operator skip and listing of stuck subscription rows. */
7
- export const subscriptionOperatorConformance = [
8
- {
9
- name: "skips a stuck row's events through a cursor for an operator, records the skip, and delivers a marker for the range",
10
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
11
- const test = yield* ActorTest;
12
- const operators = yield* OperatorRuntime;
13
- const follower = yield* SubFollower.get("skip-follower");
14
- yield* follower.Follow({ source: "skip-a" });
15
- yield* drain;
16
- fixture.behave = (entry) => (entry.includes("/skip-a#2:") ? "defect" : "apply");
17
- yield* (yield* SubOrder.get("skip-a")).PlaceMany({ customerId: "s", count: 3 });
18
- yield* drain;
19
- const [stuck] = yield* sourceRows("skip-a");
20
- expect(stuck).toMatchObject({ delivered: "1", attempts: 1 });
21
- const skipped = yield* operators
22
- .skip({
23
- target: { tenant: test.tenant, actorType: "SubOrder", actorId: "skip-a" },
24
- subscriberType: "SubFollower",
25
- subscription: "FollowedOrders",
26
- subscriberId: "skip-follower",
27
- through: "2",
28
- audit: {
29
- operator: "oncall",
30
- action: "subscriptions.skip",
31
- tenant: test.tenant,
32
- actorType: "SubOrder",
33
- actorId: "skip-a",
34
- target: "SubFollower.FollowedOrders/skip-follower",
35
- capability: Option.none(),
36
- reason: "bad payload",
37
- },
38
- })
39
- .pipe(Effect.exit);
40
- expect(Exit.isSuccess(skipped)).toBe(true);
41
- fixture.behave = () => "apply";
42
- yield* drain;
43
- expect(yield* followerLog("skip-follower")).toEqual([
44
- "skip-a#1:OrderPlaced",
45
- "skip-a~gap:1-2",
46
- "skip-a#3:OrderPlaced",
47
- ]);
48
- expect(yield* sourceRows("skip-a")).toMatchObject([
49
- { delivered: "3", attempts: 0, last_error: null },
50
- ]);
51
- const audit = yield* query((sql) => sql `
52
- SELECT action, reason, outcome FROM durable.operator_audit
53
- WHERE tenant_id = ${test.tenant} AND actor_id = 'skip-a'`);
54
- expect(audit.length).toBe(1);
55
- expect(audit[0]).toMatchObject({ action: "subscriptions.skip", reason: "bad payload" });
56
- expect(audit[0].outcome).toContain('"after":"1"');
57
- expect(audit[0].outcome).toContain('"through":"2"');
58
- const again = yield* operators
59
- .skip({
60
- target: { tenant: test.tenant, actorType: "SubOrder", actorId: "skip-a" },
61
- subscriberType: "SubFollower",
62
- subscription: "FollowedOrders",
63
- subscriberId: "skip-follower",
64
- through: "3",
65
- audit: {
66
- operator: "oncall",
67
- action: "subscriptions.skip",
68
- tenant: test.tenant,
69
- capability: Option.none(),
70
- },
71
- })
72
- .pipe(Effect.exit);
73
- expect(Exit.isFailure(again)).toBe(true);
74
- })),
75
- },
76
- {
77
- name: "lists a failing row with its lag and last error for an operator, and drops it once skipped",
78
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
79
- const test = yield* ActorTest;
80
- const operators = yield* OperatorRuntime;
81
- const follower = yield* SubFollower.get("lag-follower");
82
- yield* follower.Follow({ source: "lag-a" });
83
- yield* follower.Follow({ source: "lag-b" });
84
- yield* drain;
85
- fixture.behave = (entry) => (entry.includes("/lag-a#2:") ? "defect" : "apply");
86
- yield* (yield* SubOrder.get("lag-a")).PlaceMany({ customerId: "l", count: 3 });
87
- yield* (yield* SubOrder.get("lag-b")).PlaceMany({ customerId: "l", count: 3 });
88
- yield* drain;
89
- const page = { tenant: test.tenant, minAttempts: 1, limit: 100 };
90
- /** Other cases in this file leave their own rows behind in the tenant. */
91
- const lagging = (input) => Effect.map(operators.lagging(input), (rows) => rows.filter((row) => row.sourceId.startsWith("lag-")));
92
- const failing = yield* lagging(page);
93
- expect(new Set(failing.map((entry) => entry.sourceId))).toEqual(new Set(["lag-a"]));
94
- const row = failing.find((entry) => entry.subscriberType === "SubFollower");
95
- expect(row).toMatchObject({
96
- sourceType: "SubOrder",
97
- sourceId: "lag-a",
98
- subscriberId: "lag-follower",
99
- delivered: "1",
100
- head: "3",
101
- lag: "2",
102
- attempts: 1,
103
- });
104
- expect(row.lastError).toContain("lag-a#2");
105
- expect(yield* lagging({ ...page, minAttempts: 8 })).toEqual([]);
106
- expect(yield* lagging({ ...page, tenant: `${test.tenant}-other` })).toEqual([]);
107
- yield* operators.skip({
108
- target: { tenant: test.tenant, actorType: "SubOrder", actorId: "lag-a" },
109
- subscriberType: "SubFollower",
110
- subscription: "FollowedOrders",
111
- subscriberId: "lag-follower",
112
- through: "2",
113
- audit: {
114
- operator: "oncall",
115
- action: "subscriptions.skip",
116
- tenant: test.tenant,
117
- capability: Option.none(),
118
- reason: "bad payload",
119
- },
120
- });
121
- fixture.behave = () => "apply";
122
- yield* drain;
123
- const remaining = (yield* lagging(page)).map((entry) => entry.subscriberType);
124
- expect(remaining.length).toBe(failing.length - 1);
125
- expect(remaining).not.toContain("SubFollower");
126
- })),
127
- },
128
- ];
@@ -1,4 +0,0 @@
1
- import type { ConformanceCase } from "../../conformance.ts";
2
- import { type SubscriptionsFixture } from "./actors.ts";
3
- /** Wake, retention holds, gaps, broadcasts, and workflow waits. */
4
- export declare const subscriptionsRetentionConformance: ReadonlyArray<ConformanceCase<SubscriptionsFixture>>;
@@ -1,288 +0,0 @@
1
- import { Effect, Fiber, Schema, Stream } from "effect";
2
- import { ActorTest } from "../../actor-test.js";
3
- import { CLAIM_LEASE } from "../outbox.js";
4
- import { Live, ShipOrder, SubFollower, SubJournal, SubOrder, SubShipment, } from "./actors.js";
5
- import { crashOnce, drain, followerLog, logOf, LogState, pauseOnce, query, run, sourceRows, subscriber, tagMismatches, } from "./harness.js";
6
- import { Tenant } from "../../../index.js";
7
- const journalRow = (source, subscriberType) => Effect.gen(function* () {
8
- const test = yield* ActorTest;
9
- return (yield* query((sql) => sql `
10
- SELECT delivered::text AS delivered, gaps::text AS gaps, gap_through::text AS gap_through
11
- FROM actor_subscriptions WHERE tenant_id = ${test.tenant} AND source_type = 'SubJournal'
12
- AND source_id = ${source} AND subscriber_type = ${subscriberType}`))[0];
13
- });
14
- const journalEvents = (source) => ActorTest.use((test) => test
15
- .inspect({ tenant: test.tenant, actor: "SubJournal", id: source })
16
- .pipe(Effect.map((inspection) => inspection.events)));
17
- /** Wake, retention holds, gaps, broadcasts, and workflow waits. */
18
- export const subscriptionsRetentionConformance = [
19
- {
20
- name: "keeps events above the lowest subscriber cursor inside the hold, then prunes past it and delivers one RetentionGap, then resumes",
21
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
22
- const test = yield* ActorTest;
23
- const journal = yield* SubJournal.get("hold-j");
24
- yield* (yield* SubFollower.get("hold-f")).FollowJournal({ source: "hold-j" });
25
- yield* drain;
26
- fixture.behave = (entry) => (entry.startsWith("SubFollower/hold-f/") ? "defect" : "apply");
27
- yield* journal.Record({ customerId: "hold-c", count: 3 });
28
- yield* drain;
29
- yield* test.advance("90 minutes");
30
- yield* test.cleanup;
31
- expect(yield* journalEvents("hold-j")).toBe(3);
32
- yield* test.advance("40 minutes");
33
- yield* test.cleanup;
34
- expect(yield* journalEvents("hold-j")).toBe(0);
35
- fixture.behave = () => "apply";
36
- yield* journal.Record({ customerId: "hold-c", count: 1 });
37
- yield* test.advance("300 seconds");
38
- expect(yield* followerLog("hold-f")).toEqual(["hold-j~gap:0-3", "hold-j#4:OrderPlaced"]);
39
- expect(yield* journalRow("hold-j", "SubFollower")).toMatchObject({
40
- delivered: "4",
41
- gap_through: null,
42
- });
43
- })),
44
- },
45
- {
46
- name: 'reports RetentionGap first for a from: "start" subscription after pruning',
47
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
48
- const test = yield* ActorTest;
49
- const journal = yield* SubJournal.get("pruned-j");
50
- yield* journal.Record({ customerId: "pruned-c", count: 2 });
51
- yield* drain;
52
- yield* test.advance("3 hours");
53
- yield* test.cleanup;
54
- yield* journal.Record({ customerId: "pruned-c", count: 1 });
55
- yield* (yield* SubFollower.get("pruned-jf")).FollowJournal({
56
- source: "pruned-j",
57
- from: "start",
58
- });
59
- yield* drain;
60
- expect(yield* followerLog("pruned-jf")).toEqual([
61
- "pruned-j~gap:0-2",
62
- "pruned-j#3:OrderPlaced",
63
- ]);
64
- })),
65
- },
66
- {
67
- name: "counts an id-routed gap on the row and delivers a singleton-routed gap",
68
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
69
- const test = yield* ActorTest;
70
- const journal = yield* SubJournal.get("routegap-j");
71
- fixture.behave = (entry) => (entry.includes("/routegap-j#") ? "defect" : "apply");
72
- yield* journal.Record({ customerId: "routegap-c", count: 2 });
73
- yield* drain;
74
- yield* test.advance("3 hours");
75
- yield* test.cleanup;
76
- expect(yield* journalEvents("routegap-j")).toBe(0);
77
- fixture.behave = () => "apply";
78
- yield* journal.Record({ customerId: "routegap-c", count: 1 });
79
- yield* test.advance("300 seconds");
80
- expect(yield* logOf("SubSummary", "routegap-c")).toEqual(["routegap-j#3:OrderPlaced"]);
81
- expect(yield* journalRow("routegap-j", "SubSummary")).toMatchObject({
82
- gaps: "1",
83
- delivered: "3",
84
- });
85
- expect((yield* logOf("SubDashboard", "singleton")).filter((entry) => entry.startsWith("routegap-j"))).toEqual(["routegap-j~gap:0-2", "routegap-j#3:OrderPlaced"]);
86
- expect(yield* journalRow("routegap-j", "SubDashboard")).toMatchObject({ gaps: "0" });
87
- })),
88
- },
89
- {
90
- name: "repeats a gap's id and range on redelivery after pruning advances",
91
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
92
- const test = yield* ActorTest;
93
- const journal = yield* SubJournal.get("repeat-j");
94
- yield* (yield* SubFollower.get("repeat-f")).FollowJournal({ source: "repeat-j" });
95
- yield* drain;
96
- fixture.behave = (entry) => entry.startsWith("SubFollower/repeat-f/") ? "defect" : "apply";
97
- yield* journal.Record({ customerId: "repeat-c", count: 2 });
98
- yield* drain;
99
- yield* test.advance("3 hours");
100
- yield* test.cleanup;
101
- fixture.behave = () => "apply";
102
- const settle = crashOnce(fixture, "beforeSettle", subscriber("repeat-f"));
103
- yield* journal.Record({ customerId: "repeat-c", count: 1 });
104
- yield* test.advance("300 seconds");
105
- expect(settle.crashed).toBe(true);
106
- expect(yield* journalRow("repeat-j", "SubFollower")).toMatchObject({
107
- delivered: "0",
108
- gap_through: "2",
109
- });
110
- yield* test.advance("3 hours");
111
- yield* test.cleanup;
112
- expect(yield* journalEvents("repeat-j")).toBe(0);
113
- yield* test.advance(CLAIM_LEASE);
114
- yield* test.advance("300 seconds");
115
- expect(yield* followerLog("repeat-f")).toEqual([
116
- "repeat-j~gap:0-2",
117
- "repeat-j#3:OrderPlaced",
118
- ]);
119
- for (const entry of ["repeat-j~gap:0-2", "repeat-j#3:OrderPlaced"])
120
- expect(fixture.runs.filter((run) => run === `SubFollower/repeat-f/${entry}`).length).toBe(1);
121
- expect(yield* journalRow("repeat-j", "SubFollower")).toMatchObject({
122
- delivered: "3",
123
- gap_through: null,
124
- });
125
- })),
126
- },
127
- {
128
- name: "acknowledges a RetentionGap redelivered after its receipt was pruned without running the handler again",
129
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
130
- const test = yield* ActorTest;
131
- const journal = yield* SubJournal.get("gapreceipt-j");
132
- yield* (yield* SubFollower.get("gapreceipt-f")).FollowJournal({ source: "gapreceipt-j" });
133
- yield* drain;
134
- fixture.behave = (entry) => entry.startsWith("SubFollower/gapreceipt-f/") ? "defect" : "apply";
135
- yield* journal.Record({ customerId: "gapreceipt-c", count: 2 });
136
- yield* drain;
137
- yield* test.advance("3 hours");
138
- yield* test.cleanup;
139
- expect(yield* journalEvents("gapreceipt-j")).toBe(0);
140
- fixture.behave = () => "apply";
141
- const settle = crashOnce(fixture, "beforeSettle", subscriber("gapreceipt-f"));
142
- yield* journal.Record({ customerId: "gapreceipt-c", count: 1 });
143
- yield* test.advance("300 seconds");
144
- expect(settle.crashed).toBe(true);
145
- expect(yield* followerLog("gapreceipt-f")).toContain("gapreceipt-j~gap:0-2");
146
- expect(yield* journalRow("gapreceipt-j", "SubFollower")).toMatchObject({
147
- delivered: "0",
148
- });
149
- yield* query((sql) => sql `DELETE FROM actor_receipts WHERE tenant_id = ${test.tenant}
150
- AND actor_type = 'SubFollower' AND actor_id = 'gapreceipt-f' AND command = 'OnOrder'`);
151
- yield* test.advance(CLAIM_LEASE);
152
- yield* test.advance("300 seconds");
153
- expect(yield* followerLog("gapreceipt-f")).toEqual([
154
- "gapreceipt-j~gap:0-2",
155
- "gapreceipt-j#3:OrderPlaced",
156
- ]);
157
- for (const entry of ["gapreceipt-j~gap:0-2", "gapreceipt-j#3:OrderPlaced"])
158
- expect(fixture.runs.filter((run) => run === `SubFollower/gapreceipt-f/${entry}`).length).toBe(1);
159
- expect(yield* journalRow("gapreceipt-j", "SubFollower")).toMatchObject({
160
- delivered: "3",
161
- gap_through: null,
162
- });
163
- })),
164
- },
165
- {
166
- name: "delivers a RetentionGap, never a skip, when retention prunes a claimed row's events before it reads them",
167
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
168
- const test = yield* ActorTest;
169
- const journal = yield* SubJournal.get("claimrace-j");
170
- yield* (yield* SubFollower.get("claimrace-f")).FollowJournal({ source: "claimrace-j" });
171
- yield* drain;
172
- fixture.behave = (entry) => entry.startsWith("SubFollower/claimrace-f/") ? "defect" : "apply";
173
- yield* journal.Record({ customerId: "claimrace-c", count: 2 });
174
- yield* drain;
175
- yield* test.advance("3 hours");
176
- fixture.behave = () => "apply";
177
- const pause = yield* pauseOnce(fixture, "afterClaim", (request) => request.ref.id === "claimrace-j" && request.commandId === "claimrace-f");
178
- const delivering = yield* test.advance("300 seconds").pipe(Effect.forkChild);
179
- yield* pause.reached;
180
- yield* test.cleanup;
181
- expect(yield* journalEvents("claimrace-j")).toBe(0);
182
- yield* pause.release;
183
- yield* Fiber.join(delivering);
184
- yield* test.advance("300 seconds");
185
- expect(yield* followerLog("claimrace-f")).toEqual(["claimrace-j~gap:0-2"]);
186
- expect(yield* journalRow("claimrace-j", "SubFollower")).toMatchObject({
187
- delivered: "2",
188
- gap_through: null,
189
- });
190
- })),
191
- },
192
- {
193
- name: "widens no tombstone at startup, so it gains no tag and never becomes due",
194
- run: ({ expect, environment, fixture }) => Effect.gen(function* () {
195
- const tenant = yield* Effect.promise(() => run(environment, fixture, Effect.gen(function* () {
196
- const test = yield* ActorTest;
197
- const follower = yield* SubFollower.get("tomb-follower");
198
- yield* follower.Follow({ source: "tomb-order" });
199
- yield* drain;
200
- yield* follower.Unfollow("tomb-order");
201
- yield* drain;
202
- yield* query((sql) => sql `UPDATE actor_subscriptions SET events = ARRAY['OrderPlaced']
203
- WHERE tenant_id = ${test.tenant} AND source_id = 'tomb-order'
204
- AND subscriber_id = 'tomb-follower'`);
205
- expect(yield* sourceRows("tomb-order")).toMatchObject([
206
- { epoch: "2", active: false, due: false },
207
- ]);
208
- return test.tenant;
209
- })));
210
- yield* environment.restart;
211
- yield* Effect.promise(() => run(environment, fixture, Effect.gen(function* () {
212
- const row = query((sql) => sql `
213
- SELECT to_jsonb(events)::text AS events, active, due_at_ms IS NOT NULL AS due
214
- FROM actor_subscriptions WHERE tenant_id = ${tenant}
215
- AND source_id = 'tomb-order' AND subscriber_id = 'tomb-follower'`);
216
- const tags = query((sql) => sql `SELECT event FROM actor_subscription_tags
217
- WHERE tenant_id = ${tenant} AND source_id = 'tomb-order'`);
218
- expect(yield* row).toEqual([{ events: '["OrderPlaced"]', active: false, due: false }]);
219
- expect(yield* tags).toEqual([]);
220
- expect(yield* tagMismatches).toEqual([]);
221
- yield* Effect.gen(function* () {
222
- yield* (yield* SubOrder.get("tomb-order")).CancelOrder("t");
223
- }).pipe(Effect.provideService(Tenant, tenant));
224
- yield* drain;
225
- expect(yield* row).toEqual([{ events: '["OrderPlaced"]', active: false, due: false }]);
226
- const { state } = yield* (yield* ActorTest).inspect({
227
- tenant,
228
- actor: "SubFollower",
229
- id: "tomb-follower",
230
- });
231
- expect((yield* Schema.decodeUnknownEffect(LogState)(state).pipe(Effect.orDie)).log ?? []).toEqual([]);
232
- })));
233
- }).pipe(Effect.runPromise),
234
- },
235
- {
236
- name: "wakes a hibernated subscriber and commits the delivery",
237
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
238
- const test = yield* ActorTest;
239
- yield* (yield* SubFollower.get("sleepy-f")).Follow({ source: "sleepy-o" });
240
- yield* drain;
241
- yield* test.hibernate({ tenant: test.tenant, actor: "SubFollower", id: "sleepy-f" });
242
- yield* (yield* SubOrder.get("sleepy-o")).Place({ customerId: "s", amount: 1 });
243
- yield* drain;
244
- expect(yield* followerLog("sleepy-f")).toEqual(["sleepy-o#1:OrderPlaced"]);
245
- })),
246
- },
247
- {
248
- name: "flushes a delivery's broadcast to the parked subscriber's connection after commit, and discards it on declared failure",
249
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
250
- const test = yield* ActorTest;
251
- const ref = { tenant: test.tenant, actor: "SubSummary", id: "live-c" };
252
- const connection = yield* test.connect(ref, Live, undefined);
253
- yield* test.hibernate(ref);
254
- fixture.behave = (entry) => (entry.includes("live-o#1:") ? "refuse" : "apply");
255
- const order = yield* SubOrder.get("live-o");
256
- yield* order.Place({ customerId: "live-c", amount: 1 });
257
- yield* order.Place({ customerId: "live-c", amount: 2 });
258
- yield* drain;
259
- const frames = yield* connection.frames.pipe(Stream.take(1), Stream.runCollect, Effect.timeout("10 seconds"));
260
- expect(Array.from(frames)).toEqual(["live-o#2:OrderPlaced"]);
261
- expect(yield* logOf("SubSummary", "live-c")).toEqual(["live-o#2:OrderPlaced"]);
262
- yield* connection.close;
263
- })),
264
- },
265
- {
266
- name: "resolves an owner wait from a subscription delivery that re-emits",
267
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
268
- const shipment = yield* SubShipment.get("wf-ship");
269
- const execution = yield* shipment.PlaceOrder("wf-order");
270
- const workflow = yield* SubShipment.run(ShipOrder, execution);
271
- yield* drain;
272
- yield* (yield* SubOrder.get("wf-order")).Place({ customerId: "wf", amount: 1 });
273
- yield* drain;
274
- expect(yield* workflow.result.pipe(Effect.timeout("20 seconds"))).toBe("paid");
275
- })),
276
- },
277
- {
278
- name: "subscribes in the workflow's start turn and delivers after the start commits",
279
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
280
- yield* (yield* SubOrder.get("wf-early")).Place({ customerId: "wf", amount: 1 });
281
- const shipment = yield* SubShipment.get("wf-early-ship");
282
- const execution = yield* shipment.PlaceOrder("wf-early");
283
- const workflow = yield* SubShipment.run(ShipOrder, execution);
284
- yield* drain;
285
- expect(yield* workflow.result.pipe(Effect.timeout("20 seconds"))).toBe("paid");
286
- })),
287
- },
288
- ];
@@ -1,4 +0,0 @@
1
- import type { ConformanceCase } from "../../conformance.ts";
2
- import { type SubscriptionsFixture } from "./actors.ts";
3
- /** Routing, start positions, and first delivery of event subscriptions. */
4
- export declare const subscriptionRoutingConformance: ReadonlyArray<ConformanceCase<SubscriptionsFixture>>;
@@ -1,179 +0,0 @@
1
- import { Effect } from "effect";
2
- import { Refused, SubFollower, SubOrder } from "./actors.js";
3
- import { cursorRows, drain, followerLog, logOf, outboxOf, run, sourceRows, tagMismatches, } from "./harness.js";
4
- /** Routing, start positions, and first delivery of event subscriptions. */
5
- export const subscriptionRoutingConformance = [
6
- {
7
- name: "routes each event to the id route returns",
8
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
9
- const first = yield* SubOrder.get("route-1");
10
- const second = yield* SubOrder.get("route-2");
11
- yield* first.Place({ customerId: "route-alice", amount: 1 });
12
- yield* second.Place({ customerId: "route-bob", amount: 2 });
13
- yield* first.Note("not subscribed");
14
- yield* first.CancelOrder("route-alice");
15
- yield* drain;
16
- expect(yield* logOf("SubSummary", "route-alice")).toEqual([
17
- "route-1#1:OrderPlaced",
18
- "route-1#3:OrderCancelled",
19
- ]);
20
- expect(yield* logOf("SubSummary", "route-bob")).toEqual(["route-2#1:OrderPlaced"]);
21
- expect(yield* sourceRows("route-1", "SubSummary")).toEqual([
22
- {
23
- subscriber_type: "SubSummary",
24
- subscription: "CustomerOrders",
25
- subscriber_id: "",
26
- epoch: "0",
27
- active: true,
28
- delivered: "3",
29
- due: false,
30
- attempts: 0,
31
- last_error: null,
32
- },
33
- ]);
34
- expect(yield* cursorRows("SubSummary", "route-alice")).toEqual([
35
- {
36
- subscription: "CustomerOrders",
37
- source_id: "route-1",
38
- epoch: "0",
39
- active: true,
40
- applied: "3",
41
- },
42
- ]);
43
- expect(yield* tagMismatches).toEqual([]);
44
- })),
45
- },
46
- {
47
- name: "routes to the tenant's singleton with route: Actor.singleton",
48
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
49
- const before = (yield* logOf("SubDashboard", "singleton")).length;
50
- yield* (yield* SubOrder.get("fan-1")).Place({ customerId: "fan-a", amount: 1 });
51
- yield* (yield* SubOrder.get("fan-2")).Place({ customerId: "fan-b", amount: 1 });
52
- yield* (yield* SubOrder.get("fan-2")).CancelOrder("fan-b");
53
- yield* drain;
54
- const log = (yield* logOf("SubDashboard", "singleton")).slice(before);
55
- expect([...log].sort()).toEqual(["fan-1#1:OrderPlaced", "fan-2#1:OrderPlaced"]);
56
- })),
57
- },
58
- {
59
- name: 'delivers events committed after the registration and none before, with from: "now"',
60
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
61
- const order = yield* SubOrder.get("now-order");
62
- const follower = yield* SubFollower.get("now-follower");
63
- yield* order.Place({ customerId: "now-x", amount: 1 });
64
- yield* follower.Follow({ source: "now-order" });
65
- yield* drain;
66
- yield* order.Place({ customerId: "now-x", amount: 2 });
67
- yield* order.Note("ignored");
68
- yield* order.CancelOrder("now-x");
69
- yield* drain;
70
- expect(yield* followerLog("now-follower")).toEqual([
71
- "now-order#2:OrderPlaced",
72
- "now-order#4:OrderCancelled",
73
- ]);
74
- expect(yield* cursorRows("SubFollower", "now-follower")).toEqual([
75
- {
76
- subscription: "FollowedOrders",
77
- source_id: "now-order",
78
- epoch: "1",
79
- active: true,
80
- applied: "4",
81
- },
82
- ]);
83
- expect(yield* tagMismatches).toEqual([]);
84
- })),
85
- },
86
- {
87
- name: 'delivers retained history to a from: "start" subscription on a source that never emits again',
88
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
89
- const order = yield* SubOrder.get("start-order");
90
- yield* order.PlaceMany({ customerId: "start-x", count: 3 });
91
- yield* order.Note("between");
92
- yield* order.CancelOrder("start-x");
93
- yield* drain;
94
- yield* (yield* SubFollower.get("start-follower")).Follow({
95
- source: "start-order",
96
- from: "start",
97
- });
98
- yield* drain;
99
- expect(yield* followerLog("start-follower")).toEqual([
100
- "start-order#1:OrderPlaced",
101
- "start-order#2:OrderPlaced",
102
- "start-order#3:OrderPlaced",
103
- "start-order#5:OrderCancelled",
104
- ]);
105
- })),
106
- },
107
- {
108
- name: "resumes after an explicit cursor",
109
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
110
- const order = yield* SubOrder.get("cursor-order");
111
- yield* order.PlaceMany({ customerId: "cursor-x", count: 3 });
112
- yield* (yield* SubFollower.get("cursor-follower")).Follow({
113
- source: "cursor-order",
114
- from: "2",
115
- });
116
- yield* drain;
117
- yield* order.CancelOrder("cursor-x");
118
- yield* drain;
119
- expect(yield* followerLog("cursor-follower")).toEqual([
120
- "cursor-order#3:OrderPlaced",
121
- "cursor-order#4:OrderCancelled",
122
- ]);
123
- })),
124
- },
125
- {
126
- name: "stages nothing when the subscribing turn fails with a declared error",
127
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
128
- const follower = yield* SubFollower.get("refused-follower");
129
- const refused = yield* follower.FollowThenRefuse("refused-order").pipe(Effect.flip);
130
- expect(refused).toBeInstanceOf(Refused);
131
- yield* (yield* SubOrder.get("refused-order")).Place({ customerId: "r", amount: 1 });
132
- yield* drain;
133
- expect(yield* cursorRows("SubFollower", "refused-follower")).toEqual([]);
134
- expect(yield* outboxOf("SubFollower", "refused-follower", "control")).toBe(0);
135
- expect((yield* sourceRows("refused-order")).filter((row) => row.subscriber_type === "SubFollower")).toEqual([]);
136
- expect(yield* followerLog("refused-follower")).toEqual([]);
137
- })),
138
- },
139
- {
140
- name: "delivers Rejected and deactivates the subscription for a cursor above the source's head",
141
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
142
- const order = yield* SubOrder.get("reject-order");
143
- yield* order.PlaceMany({ customerId: "reject-x", count: 2 });
144
- const follower = yield* SubFollower.get("reject-follower");
145
- yield* follower.Follow({ source: "reject-order", from: "9" });
146
- yield* drain;
147
- expect(yield* followerLog("reject-follower")).toEqual(["reject-order!rejected:9"]);
148
- expect(yield* cursorRows("SubFollower", "reject-follower")).toEqual([
149
- {
150
- subscription: "FollowedOrders",
151
- source_id: "reject-order",
152
- epoch: "1",
153
- active: false,
154
- applied: "9",
155
- },
156
- ]);
157
- expect((yield* sourceRows("reject-order")).filter((row) => row.subscriber_type === "SubFollower")).toMatchObject([
158
- { subscriber_id: "reject-follower", epoch: "1", active: false, due: false },
159
- ]);
160
- yield* order.Place({ customerId: "reject-x", amount: 3 });
161
- yield* drain;
162
- expect(yield* followerLog("reject-follower")).toEqual(["reject-order!rejected:9"]);
163
- expect(yield* tagMismatches).toEqual([]);
164
- })),
165
- },
166
- {
167
- name: "subscribes to a source that has never been created, and delivers its first event",
168
- run: ({ expect, environment, fixture }) => run(environment, fixture, Effect.gen(function* () {
169
- yield* (yield* SubFollower.get("early-follower")).Follow({ source: "early-order" });
170
- yield* drain;
171
- expect(yield* sourceRows("early-order")).toMatchObject([
172
- { subscriber_id: "early-follower", active: true, delivered: "0" },
173
- ]);
174
- yield* (yield* SubOrder.get("early-order")).Place({ customerId: "early-x", amount: 1 });
175
- yield* drain;
176
- expect(yield* followerLog("early-follower")).toEqual(["early-order#1:OrderPlaced"]);
177
- })),
178
- },
179
- ];
@@ -1,4 +0,0 @@
1
- import type { ConformanceCase } from "../conformance.ts";
2
- import type { SubscriptionsFixture } from "./subscriptions/actors.ts";
3
- /** Subscription cases: routing, start positions, delivery, and failure handling of event subscriptions. */
4
- export declare const subscriptionsConformance: ReadonlyArray<ConformanceCase<SubscriptionsFixture>>;
@@ -1,19 +0,0 @@
1
- import { subscriptionAccessConformance } from "./subscriptions/access.js";
2
- import { subscriptionDeliveryConformance } from "./subscriptions/delivery.js";
3
- import { subscriptionDeployConformance } from "./subscriptions/deploys.js";
4
- import { subscriptionEpochConformance } from "./subscriptions/epochs.js";
5
- import { subscriptionFailureConformance } from "./subscriptions/failures.js";
6
- import { subscriptionFeedConformance } from "./subscriptions/feeds.js";
7
- import { subscriptionOperatorConformance } from "./subscriptions/operator.js";
8
- import { subscriptionRoutingConformance } from "./subscriptions/routing.js";
9
- /** Subscription cases: routing, start positions, delivery, and failure handling of event subscriptions. */
10
- export const subscriptionsConformance = [
11
- ...subscriptionRoutingConformance,
12
- ...subscriptionEpochConformance,
13
- ...subscriptionFeedConformance,
14
- ...subscriptionDeliveryConformance,
15
- ...subscriptionOperatorConformance,
16
- ...subscriptionFailureConformance,
17
- ...subscriptionAccessConformance,
18
- ...subscriptionDeployConformance,
19
- ];