@rikalabs/akter 0.1.0-alpha.0

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 (603) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +8 -0
  4. package/README.md +116 -0
  5. package/dist/actor/codecs.d.ts +77 -0
  6. package/dist/actor/codecs.js +87 -0
  7. package/dist/actor/connections.d.ts +34 -0
  8. package/dist/actor/connections.js +145 -0
  9. package/dist/actor/definition.d.ts +893 -0
  10. package/dist/actor/definition.js +147 -0
  11. package/dist/actor/descriptor.d.ts +172 -0
  12. package/dist/actor/descriptor.js +367 -0
  13. package/dist/actor/handles.d.ts +77 -0
  14. package/dist/actor/handles.js +265 -0
  15. package/dist/actor/jobs.d.ts +10 -0
  16. package/dist/actor/jobs.js +137 -0
  17. package/dist/actor/layers.d.ts +41 -0
  18. package/dist/actor/layers.js +177 -0
  19. package/dist/actor/reads.d.ts +47 -0
  20. package/dist/actor/reads.js +224 -0
  21. package/dist/actor/served.d.ts +120 -0
  22. package/dist/actor/served.js +72 -0
  23. package/dist/actor/turns.d.ts +13 -0
  24. package/dist/actor/turns.js +332 -0
  25. package/dist/actor/workflows.d.ts +16 -0
  26. package/dist/actor/workflows.js +37 -0
  27. package/dist/client/calls.d.ts +47 -0
  28. package/dist/client/calls.js +425 -0
  29. package/dist/client/clock.d.ts +56 -0
  30. package/dist/client/clock.js +119 -0
  31. package/dist/client/fleet-page.d.ts +15 -0
  32. package/dist/client/fleet-page.js +13 -0
  33. package/dist/client/fleet.d.ts +29 -0
  34. package/dist/client/fleet.js +51 -0
  35. package/dist/client/index.d.ts +17 -0
  36. package/dist/client/index.js +6 -0
  37. package/dist/client/make.d.ts +157 -0
  38. package/dist/client/make.js +221 -0
  39. package/dist/client/offline/queue.d.ts +118 -0
  40. package/dist/client/offline/queue.js +292 -0
  41. package/dist/client/offline/store.d.ts +74 -0
  42. package/dist/client/offline/store.js +78 -0
  43. package/dist/client/optimistic.d.ts +57 -0
  44. package/dist/client/optimistic.js +136 -0
  45. package/dist/client/report.d.ts +2 -0
  46. package/dist/client/report.js +8 -0
  47. package/dist/client/sessions/connection.d.ts +118 -0
  48. package/dist/client/sessions/connection.js +162 -0
  49. package/dist/client/sessions/feed.d.ts +42 -0
  50. package/dist/client/sessions/feed.js +43 -0
  51. package/dist/client/sessions/sse.d.ts +47 -0
  52. package/dist/client/sessions/sse.js +112 -0
  53. package/dist/client/sessions/stream.d.ts +28 -0
  54. package/dist/client/sessions/stream.js +35 -0
  55. package/dist/client/sessions/watch.d.ts +34 -0
  56. package/dist/client/sessions/watch.js +40 -0
  57. package/dist/client/transport.d.ts +37 -0
  58. package/dist/client/transport.js +66 -0
  59. package/dist/contexts/command.d.ts +132 -0
  60. package/dist/contexts/command.js +20 -0
  61. package/dist/contexts/connection.d.ts +68 -0
  62. package/dist/contexts/connection.js +0 -0
  63. package/dist/contexts/job.d.ts +49 -0
  64. package/dist/contexts/job.js +0 -0
  65. package/dist/contexts/workflow.d.ts +147 -0
  66. package/dist/contexts/workflow.js +22 -0
  67. package/dist/errors/actor.d.ts +200 -0
  68. package/dist/errors/actor.js +271 -0
  69. package/dist/errors/content.d.ts +19 -0
  70. package/dist/errors/content.js +14 -0
  71. package/dist/errors/database.d.ts +22 -0
  72. package/dist/errors/database.js +23 -0
  73. package/dist/errors/events.d.ts +17 -0
  74. package/dist/errors/events.js +14 -0
  75. package/dist/errors/subscription.d.ts +12 -0
  76. package/dist/errors/subscription.js +8 -0
  77. package/dist/errors/workflow.d.ts +28 -0
  78. package/dist/errors/workflow.js +17 -0
  79. package/dist/handles/actors.d.ts +17 -0
  80. package/dist/handles/actors.js +7 -0
  81. package/dist/handles/content.d.ts +59 -0
  82. package/dist/handles/content.js +36 -0
  83. package/dist/handles/intents.d.ts +164 -0
  84. package/dist/handles/intents.js +214 -0
  85. package/dist/handles/run.d.ts +31 -0
  86. package/dist/handles/run.js +21 -0
  87. package/dist/handles/workflow.d.ts +27 -0
  88. package/dist/handles/workflow.js +23 -0
  89. package/dist/identity/caller.d.ts +105 -0
  90. package/dist/identity/caller.js +68 -0
  91. package/dist/identity/child.d.ts +18 -0
  92. package/dist/identity/child.js +39 -0
  93. package/dist/identity/command.d.ts +19 -0
  94. package/dist/identity/command.js +21 -0
  95. package/dist/identity/connection.d.ts +24 -0
  96. package/dist/identity/connection.js +29 -0
  97. package/dist/identity/content.d.ts +18 -0
  98. package/dist/identity/content.js +12 -0
  99. package/dist/identity/digest.d.ts +4 -0
  100. package/dist/identity/digest.js +5 -0
  101. package/dist/identity/execution.d.ts +32 -0
  102. package/dist/identity/execution.js +63 -0
  103. package/dist/identity/mint.d.ts +51 -0
  104. package/dist/identity/mint.js +76 -0
  105. package/dist/identity/version.d.ts +2 -0
  106. package/dist/identity/version.js +3 -0
  107. package/dist/index.d.ts +159 -0
  108. package/dist/index.js +97 -0
  109. package/dist/members/blob.d.ts +43 -0
  110. package/dist/members/blob.js +29 -0
  111. package/dist/members/command.d.ts +109 -0
  112. package/dist/members/command.js +61 -0
  113. package/dist/members/connection.d.ts +55 -0
  114. package/dist/members/connection.js +49 -0
  115. package/dist/members/event.d.ts +36 -0
  116. package/dist/members/event.js +24 -0
  117. package/dist/members/job.d.ts +157 -0
  118. package/dist/members/job.js +67 -0
  119. package/dist/members/payload.d.ts +93 -0
  120. package/dist/members/payload.js +145 -0
  121. package/dist/members/reducer.d.ts +64 -0
  122. package/dist/members/reducer.js +27 -0
  123. package/dist/members/stream.d.ts +36 -0
  124. package/dist/members/stream.js +14 -0
  125. package/dist/members/subscription.d.ts +182 -0
  126. package/dist/members/subscription.js +91 -0
  127. package/dist/members/workflow.d.ts +99 -0
  128. package/dist/members/workflow.js +2 -0
  129. package/dist/policies/access.d.ts +35 -0
  130. package/dist/policies/access.js +6 -0
  131. package/dist/policies/command.d.ts +127 -0
  132. package/dist/policies/command.js +45 -0
  133. package/dist/policies/job.d.ts +28 -0
  134. package/dist/policies/job.js +60 -0
  135. package/dist/policies/schedules.d.ts +33 -0
  136. package/dist/policies/schedules.js +131 -0
  137. package/dist/protocol/frames.d.ts +66 -0
  138. package/dist/protocol/frames.js +55 -0
  139. package/dist/protocol/inspection.d.ts +807 -0
  140. package/dist/protocol/inspection.js +243 -0
  141. package/dist/protocol/wire.d.ts +184 -0
  142. package/dist/protocol/wire.js +150 -0
  143. package/dist/runtime/actors.d.ts +155 -0
  144. package/dist/runtime/actors.js +4 -0
  145. package/dist/runtime/admission.d.ts +34 -0
  146. package/dist/runtime/admission.js +72 -0
  147. package/dist/runtime/adoption/backfill.d.ts +27 -0
  148. package/dist/runtime/adoption/backfill.js +144 -0
  149. package/dist/runtime/adoption/enforce.d.ts +55 -0
  150. package/dist/runtime/adoption/enforce.js +241 -0
  151. package/dist/runtime/adoption/observe.d.ts +43 -0
  152. package/dist/runtime/adoption/observe.js +139 -0
  153. package/dist/runtime/adoption/plan.d.ts +45 -0
  154. package/dist/runtime/adoption/plan.js +192 -0
  155. package/dist/runtime/adoption/startup.d.ts +32 -0
  156. package/dist/runtime/adoption/startup.js +76 -0
  157. package/dist/runtime/adoption/status.d.ts +23 -0
  158. package/dist/runtime/adoption/status.js +47 -0
  159. package/dist/runtime/adoption/target.d.ts +33 -0
  160. package/dist/runtime/adoption/target.js +49 -0
  161. package/dist/runtime/connections/holder.d.ts +221 -0
  162. package/dist/runtime/connections/holder.js +816 -0
  163. package/dist/runtime/connections/owner.d.ts +263 -0
  164. package/dist/runtime/connections/owner.js +896 -0
  165. package/dist/runtime/connections/protocol.d.ts +441 -0
  166. package/dist/runtime/connections/protocol.js +222 -0
  167. package/dist/runtime/connections/reads.d.ts +24 -0
  168. package/dist/runtime/connections/reads.js +19 -0
  169. package/dist/runtime/connections/streams.d.ts +62 -0
  170. package/dist/runtime/connections/streams.js +128 -0
  171. package/dist/runtime/connections/transport.d.ts +40 -0
  172. package/dist/runtime/connections/transport.js +68 -0
  173. package/dist/runtime/connections/watch.d.ts +52 -0
  174. package/dist/runtime/connections/watch.js +159 -0
  175. package/dist/runtime/content/grant.d.ts +34 -0
  176. package/dist/runtime/content/grant.js +58 -0
  177. package/dist/runtime/content/store.d.ts +63 -0
  178. package/dist/runtime/content/store.js +294 -0
  179. package/dist/runtime/cron/key.d.ts +2 -0
  180. package/dist/runtime/cron/key.js +2 -0
  181. package/dist/runtime/cron/schedule.d.ts +69 -0
  182. package/dist/runtime/cron/schedule.js +144 -0
  183. package/dist/runtime/database/bounded.d.ts +43 -0
  184. package/dist/runtime/database/bounded.js +108 -0
  185. package/dist/runtime/database/connection.d.ts +8 -0
  186. package/dist/runtime/database/connection.js +18 -0
  187. package/dist/runtime/database/coordination.d.ts +19 -0
  188. package/dist/runtime/database/coordination.js +72 -0
  189. package/dist/runtime/database/flock.d.ts +10 -0
  190. package/dist/runtime/database/flock.js +60 -0
  191. package/dist/runtime/database/gate.d.ts +26 -0
  192. package/dist/runtime/database/gate.js +54 -0
  193. package/dist/runtime/database/keepalive.d.ts +11 -0
  194. package/dist/runtime/database/keepalive.js +22 -0
  195. package/dist/runtime/database/migrations.d.ts +177 -0
  196. package/dist/runtime/database/migrations.js +1018 -0
  197. package/dist/runtime/database/neki/migrations.d.ts +31 -0
  198. package/dist/runtime/database/neki/migrations.js +276 -0
  199. package/dist/runtime/database/neki/session.d.ts +23 -0
  200. package/dist/runtime/database/neki/session.js +31 -0
  201. package/dist/runtime/database/pglite.d.ts +21 -0
  202. package/dist/runtime/database/pglite.js +74 -0
  203. package/dist/runtime/database/replica.d.ts +41 -0
  204. package/dist/runtime/database/replica.js +51 -0
  205. package/dist/runtime/database/shards.d.ts +21 -0
  206. package/dist/runtime/database/shards.js +37 -0
  207. package/dist/runtime/database/snapshot.d.ts +7 -0
  208. package/dist/runtime/database/snapshot.js +7 -0
  209. package/dist/runtime/database/tenancy.d.ts +69 -0
  210. package/dist/runtime/database/tenancy.js +145 -0
  211. package/dist/runtime/database/transient.d.ts +10 -0
  212. package/dist/runtime/database/transient.js +25 -0
  213. package/dist/runtime/drain.d.ts +132 -0
  214. package/dist/runtime/drain.js +109 -0
  215. package/dist/runtime/entity/mailbox.d.ts +86 -0
  216. package/dist/runtime/entity/mailbox.js +121 -0
  217. package/dist/runtime/entity/register.d.ts +424 -0
  218. package/dist/runtime/entity/register.js +669 -0
  219. package/dist/runtime/events/append.d.ts +192 -0
  220. package/dist/runtime/events/append.js +128 -0
  221. package/dist/runtime/events/cursor.d.ts +2 -0
  222. package/dist/runtime/events/cursor.js +5 -0
  223. package/dist/runtime/events/replay.d.ts +20 -0
  224. package/dist/runtime/events/replay.js +45 -0
  225. package/dist/runtime/feeds.d.ts +26 -0
  226. package/dist/runtime/feeds.js +100 -0
  227. package/dist/runtime/fleet/checks.d.ts +17 -0
  228. package/dist/runtime/fleet/checks.js +106 -0
  229. package/dist/runtime/fleet/maintainer.d.ts +38 -0
  230. package/dist/runtime/fleet/maintainer.js +383 -0
  231. package/dist/runtime/fleet/pgoutput.d.ts +41 -0
  232. package/dist/runtime/fleet/pgoutput.js +102 -0
  233. package/dist/runtime/fleet/setup.d.ts +36 -0
  234. package/dist/runtime/fleet/setup.js +58 -0
  235. package/dist/runtime/fleet/subscribe.d.ts +42 -0
  236. package/dist/runtime/fleet/subscribe.js +147 -0
  237. package/dist/runtime/index.d.ts +66 -0
  238. package/dist/runtime/index.js +37 -0
  239. package/dist/runtime/inspector/http.d.ts +19 -0
  240. package/dist/runtime/inspector/http.js +36 -0
  241. package/dist/runtime/inspector/layer.d.ts +46 -0
  242. package/dist/runtime/inspector/layer.js +180 -0
  243. package/dist/runtime/inspector/queries.d.ts +711 -0
  244. package/dist/runtime/inspector/queries.js +494 -0
  245. package/dist/runtime/jobs/attempt.d.ts +254 -0
  246. package/dist/runtime/jobs/attempt.js +413 -0
  247. package/dist/runtime/jobs/isolation.d.ts +20 -0
  248. package/dist/runtime/jobs/isolation.js +10 -0
  249. package/dist/runtime/jobs/progress.d.ts +95 -0
  250. package/dist/runtime/jobs/progress.js +144 -0
  251. package/dist/runtime/layer.d.ts +260 -0
  252. package/dist/runtime/layer.js +876 -0
  253. package/dist/runtime/members.d.ts +381 -0
  254. package/dist/runtime/members.js +8 -0
  255. package/dist/runtime/operators/audit.d.ts +64 -0
  256. package/dist/runtime/operators/audit.js +56 -0
  257. package/dist/runtime/operators/auth.d.ts +29 -0
  258. package/dist/runtime/operators/auth.js +42 -0
  259. package/dist/runtime/operators/export.d.ts +68 -0
  260. package/dist/runtime/operators/export.js +137 -0
  261. package/dist/runtime/operators/grants.d.ts +45 -0
  262. package/dist/runtime/operators/grants.js +40 -0
  263. package/dist/runtime/operators/repair.d.ts +206 -0
  264. package/dist/runtime/operators/repair.js +226 -0
  265. package/dist/runtime/operators/routes.d.ts +35 -0
  266. package/dist/runtime/operators/routes.js +190 -0
  267. package/dist/runtime/operators/seed.d.ts +123 -0
  268. package/dist/runtime/operators/seed.js +123 -0
  269. package/dist/runtime/payloads/versions.d.ts +65 -0
  270. package/dist/runtime/payloads/versions.js +240 -0
  271. package/dist/runtime/peering/authority.d.ts +42 -0
  272. package/dist/runtime/peering/authority.js +132 -0
  273. package/dist/runtime/peering/credentials.d.ts +21 -0
  274. package/dist/runtime/peering/credentials.js +13 -0
  275. package/dist/runtime/peering/transport.d.ts +51 -0
  276. package/dist/runtime/peering/transport.js +175 -0
  277. package/dist/runtime/queries.d.ts +18 -0
  278. package/dist/runtime/queries.js +169 -0
  279. package/dist/runtime/readiness.d.ts +36 -0
  280. package/dist/runtime/readiness.js +44 -0
  281. package/dist/runtime/registration.d.ts +58 -0
  282. package/dist/runtime/registration.js +186 -0
  283. package/dist/runtime/request.d.ts +158 -0
  284. package/dist/runtime/request.js +102 -0
  285. package/dist/runtime/retry.d.ts +8 -0
  286. package/dist/runtime/retry.js +11 -0
  287. package/dist/runtime/runner.d.ts +93 -0
  288. package/dist/runtime/runner.js +122 -0
  289. package/dist/runtime/storage/codec.d.ts +39 -0
  290. package/dist/runtime/storage/codec.js +41 -0
  291. package/dist/runtime/storage/generation.d.ts +69 -0
  292. package/dist/runtime/storage/generation.js +49 -0
  293. package/dist/runtime/storage/placements.d.ts +15 -0
  294. package/dist/runtime/storage/placements.js +38 -0
  295. package/dist/runtime/storage/platform.d.ts +6 -0
  296. package/dist/runtime/storage/platform.js +9 -0
  297. package/dist/runtime/storage/retention.d.ts +73 -0
  298. package/dist/runtime/storage/retention.js +158 -0
  299. package/dist/runtime/subscriptions/identity.d.ts +31 -0
  300. package/dist/runtime/subscriptions/identity.js +45 -0
  301. package/dist/runtime/subscriptions/relay.d.ts +175 -0
  302. package/dist/runtime/subscriptions/relay.js +763 -0
  303. package/dist/runtime/subscriptions/storage.d.ts +40 -0
  304. package/dist/runtime/subscriptions/storage.js +98 -0
  305. package/dist/runtime/sweeps.d.ts +39 -0
  306. package/dist/runtime/sweeps.js +54 -0
  307. package/dist/runtime/telemetry/defects.d.ts +57 -0
  308. package/dist/runtime/telemetry/defects.js +43 -0
  309. package/dist/runtime/telemetry/metrics.d.ts +52 -0
  310. package/dist/runtime/telemetry/metrics.js +138 -0
  311. package/dist/runtime/telemetry/routes.d.ts +19 -0
  312. package/dist/runtime/telemetry/routes.js +18 -0
  313. package/dist/runtime/telemetry/sampler.d.ts +26 -0
  314. package/dist/runtime/telemetry/sampler.js +101 -0
  315. package/dist/runtime/telemetry/spans.d.ts +38 -0
  316. package/dist/runtime/telemetry/spans.js +44 -0
  317. package/dist/runtime/telemetry/usage.d.ts +52 -0
  318. package/dist/runtime/telemetry/usage.js +30 -0
  319. package/dist/runtime/topology/admission.d.ts +13 -0
  320. package/dist/runtime/topology/admission.js +36 -0
  321. package/dist/runtime/topology/locks.d.ts +56 -0
  322. package/dist/runtime/topology/locks.js +81 -0
  323. package/dist/runtime/topology/messages.d.ts +15 -0
  324. package/dist/runtime/topology/messages.js +32 -0
  325. package/dist/runtime/turn/admission.d.ts +22 -0
  326. package/dist/runtime/turn/admission.js +41 -0
  327. package/dist/runtime/turn/blobs.d.ts +38 -0
  328. package/dist/runtime/turn/blobs.js +215 -0
  329. package/dist/runtime/turn/execute.d.ts +208 -0
  330. package/dist/runtime/turn/execute.js +972 -0
  331. package/dist/runtime/turn/group.d.ts +165 -0
  332. package/dist/runtime/turn/group.js +326 -0
  333. package/dist/runtime/turn/hooks.d.ts +44 -0
  334. package/dist/runtime/turn/hooks.js +28 -0
  335. package/dist/runtime/turn/outbox.d.ts +159 -0
  336. package/dist/runtime/turn/outbox.js +269 -0
  337. package/dist/runtime/turn/pipeline.d.ts +68 -0
  338. package/dist/runtime/turn/pipeline.js +83 -0
  339. package/dist/runtime/turn/receipt.d.ts +81 -0
  340. package/dist/runtime/turn/receipt.js +32 -0
  341. package/dist/runtime/turn/relay.d.ts +179 -0
  342. package/dist/runtime/turn/relay.js +685 -0
  343. package/dist/runtime/turn/rows.d.ts +43 -0
  344. package/dist/runtime/turn/rows.js +592 -0
  345. package/dist/runtime/workflows/compatibility.d.ts +125 -0
  346. package/dist/runtime/workflows/compatibility.js +285 -0
  347. package/dist/runtime/workflows/engine.d.ts +107 -0
  348. package/dist/runtime/workflows/engine.js +826 -0
  349. package/dist/runtime/workflows/manifest.d.ts +34 -0
  350. package/dist/runtime/workflows/manifest.js +39 -0
  351. package/dist/runtime/workflows/steps.d.ts +33 -0
  352. package/dist/runtime/workflows/steps.js +152 -0
  353. package/dist/serve/api.d.ts +99 -0
  354. package/dist/serve/api.js +403 -0
  355. package/dist/serve/assertion/binding.d.ts +41 -0
  356. package/dist/serve/assertion/binding.js +92 -0
  357. package/dist/serve/assertion/verify.d.ts +93 -0
  358. package/dist/serve/assertion/verify.js +189 -0
  359. package/dist/serve/auth.d.ts +200 -0
  360. package/dist/serve/auth.js +92 -0
  361. package/dist/serve/clock.d.ts +10 -0
  362. package/dist/serve/clock.js +25 -0
  363. package/dist/serve/jwt.d.ts +65 -0
  364. package/dist/serve/jwt.js +202 -0
  365. package/dist/serve/layer.d.ts +98 -0
  366. package/dist/serve/layer.js +809 -0
  367. package/dist/serve/mcp/endpoint.d.ts +39 -0
  368. package/dist/serve/mcp/endpoint.js +187 -0
  369. package/dist/serve/mcp/tools.d.ts +37 -0
  370. package/dist/serve/mcp/tools.js +125 -0
  371. package/dist/serve/origin.d.ts +6 -0
  372. package/dist/serve/origin.js +21 -0
  373. package/dist/serve/sessions/feed.d.ts +79 -0
  374. package/dist/serve/sessions/feed.js +115 -0
  375. package/dist/serve/sessions/socket.d.ts +56 -0
  376. package/dist/serve/sessions/socket.js +212 -0
  377. package/dist/serve/sessions/sse.d.ts +27 -0
  378. package/dist/serve/sessions/sse.js +26 -0
  379. package/dist/serve/sessions/stream.d.ts +9 -0
  380. package/dist/serve/sessions/stream.js +9 -0
  381. package/dist/serve/sessions/watch.d.ts +12 -0
  382. package/dist/serve/sessions/watch.js +11 -0
  383. package/dist/serve/wire.d.ts +16 -0
  384. package/dist/serve/wire.js +50 -0
  385. package/dist/state/blob.d.ts +71 -0
  386. package/dist/state/blob.js +0 -0
  387. package/dist/state/migration.d.ts +53 -0
  388. package/dist/state/migration.js +29 -0
  389. package/dist/tables/fleet.d.ts +170 -0
  390. package/dist/tables/fleet.js +214 -0
  391. package/dist/tables/owned.d.ts +250 -0
  392. package/dist/tables/owned.js +233 -0
  393. package/dist/testing/actor-test.d.ts +360 -0
  394. package/dist/testing/actor-test.js +337 -0
  395. package/dist/testing/cluster.d.ts +93 -0
  396. package/dist/testing/cluster.js +296 -0
  397. package/dist/testing/conformance/access.d.ts +5 -0
  398. package/dist/testing/conformance/access.js +531 -0
  399. package/dist/testing/conformance/admission.d.ts +11 -0
  400. package/dist/testing/conformance/admission.js +182 -0
  401. package/dist/testing/conformance/adoption.d.ts +2 -0
  402. package/dist/testing/conformance/adoption.js +1019 -0
  403. package/dist/testing/conformance/assertions.d.ts +202 -0
  404. package/dist/testing/conformance/assertions.js +849 -0
  405. package/dist/testing/conformance/batches.d.ts +41 -0
  406. package/dist/testing/conformance/batches.js +388 -0
  407. package/dist/testing/conformance/blobs.d.ts +14 -0
  408. package/dist/testing/conformance/blobs.js +405 -0
  409. package/dist/testing/conformance/capacity.d.ts +8 -0
  410. package/dist/testing/conformance/capacity.js +433 -0
  411. package/dist/testing/conformance/client.d.ts +5 -0
  412. package/dist/testing/conformance/client.js +719 -0
  413. package/dist/testing/conformance/cold-serve.d.ts +16 -0
  414. package/dist/testing/conformance/cold-serve.js +254 -0
  415. package/dist/testing/conformance/connections/actors.d.ts +1143 -0
  416. package/dist/testing/conformance/connections/actors.js +180 -0
  417. package/dist/testing/conformance/connections/harness.d.ts +1754 -0
  418. package/dist/testing/conformance/connections/harness.js +142 -0
  419. package/dist/testing/conformance/connections/holders.d.ts +4 -0
  420. package/dist/testing/conformance/connections/holders.js +165 -0
  421. package/dist/testing/conformance/connections/lifecycle.d.ts +4 -0
  422. package/dist/testing/conformance/connections/lifecycle.js +113 -0
  423. package/dist/testing/conformance/connections/limits.d.ts +4 -0
  424. package/dist/testing/conformance/connections/limits.js +127 -0
  425. package/dist/testing/conformance/connections/reauthorization.d.ts +4 -0
  426. package/dist/testing/conformance/connections/reauthorization.js +170 -0
  427. package/dist/testing/conformance/connections/resync.d.ts +4 -0
  428. package/dist/testing/conformance/connections/resync.js +360 -0
  429. package/dist/testing/conformance/connections/takeover.d.ts +4 -0
  430. package/dist/testing/conformance/connections/takeover.js +287 -0
  431. package/dist/testing/conformance/connections.d.ts +4 -0
  432. package/dist/testing/conformance/connections.js +15 -0
  433. package/dist/testing/conformance/content-blobs.d.ts +16 -0
  434. package/dist/testing/conformance/content-blobs.js +534 -0
  435. package/dist/testing/conformance/counter.d.ts +16 -0
  436. package/dist/testing/conformance/counter.js +813 -0
  437. package/dist/testing/conformance/cron.d.ts +5 -0
  438. package/dist/testing/conformance/cron.js +665 -0
  439. package/dist/testing/conformance/drain.d.ts +26 -0
  440. package/dist/testing/conformance/drain.js +540 -0
  441. package/dist/testing/conformance/effect-control.d.ts +38 -0
  442. package/dist/testing/conformance/effect-control.js +1059 -0
  443. package/dist/testing/conformance/effects.d.ts +23 -0
  444. package/dist/testing/conformance/effects.js +432 -0
  445. package/dist/testing/conformance/events.d.ts +28 -0
  446. package/dist/testing/conformance/events.js +335 -0
  447. package/dist/testing/conformance/export.d.ts +2 -0
  448. package/dist/testing/conformance/export.js +368 -0
  449. package/dist/testing/conformance/fleet.d.ts +444 -0
  450. package/dist/testing/conformance/fleet.js +1009 -0
  451. package/dist/testing/conformance/groups.d.ts +7 -0
  452. package/dist/testing/conformance/groups.js +353 -0
  453. package/dist/testing/conformance/heap.d.ts +3 -0
  454. package/dist/testing/conformance/heap.js +149 -0
  455. package/dist/testing/conformance/http.d.ts +2809 -0
  456. package/dist/testing/conformance/http.js +1234 -0
  457. package/dist/testing/conformance/inspection-views.d.ts +8 -0
  458. package/dist/testing/conformance/inspection-views.js +272 -0
  459. package/dist/testing/conformance/inspector.d.ts +7 -0
  460. package/dist/testing/conformance/inspector.js +650 -0
  461. package/dist/testing/conformance/mint.d.ts +58 -0
  462. package/dist/testing/conformance/mint.js +692 -0
  463. package/dist/testing/conformance/multi-runner.d.ts +8 -0
  464. package/dist/testing/conformance/multi-runner.js +403 -0
  465. package/dist/testing/conformance/neki/plan.d.ts +19 -0
  466. package/dist/testing/conformance/neki/plan.js +30 -0
  467. package/dist/testing/conformance/observability.d.ts +3 -0
  468. package/dist/testing/conformance/observability.js +343 -0
  469. package/dist/testing/conformance/offline.d.ts +4 -0
  470. package/dist/testing/conformance/offline.js +474 -0
  471. package/dist/testing/conformance/operator-harness.d.ts +57 -0
  472. package/dist/testing/conformance/operator-harness.js +78 -0
  473. package/dist/testing/conformance/operator.d.ts +3 -0
  474. package/dist/testing/conformance/operator.js +379 -0
  475. package/dist/testing/conformance/outbox-cross-shard.d.ts +14 -0
  476. package/dist/testing/conformance/outbox-cross-shard.js +160 -0
  477. package/dist/testing/conformance/outbox.d.ts +36 -0
  478. package/dist/testing/conformance/outbox.js +437 -0
  479. package/dist/testing/conformance/payload-migrations.d.ts +3 -0
  480. package/dist/testing/conformance/payload-migrations.js +612 -0
  481. package/dist/testing/conformance/pipeline.d.ts +3 -0
  482. package/dist/testing/conformance/pipeline.js +1040 -0
  483. package/dist/testing/conformance/placement.d.ts +22 -0
  484. package/dist/testing/conformance/placement.js +539 -0
  485. package/dist/testing/conformance/platform.d.ts +40 -0
  486. package/dist/testing/conformance/platform.js +101 -0
  487. package/dist/testing/conformance/progress.d.ts +39 -0
  488. package/dist/testing/conformance/progress.js +666 -0
  489. package/dist/testing/conformance/properties.d.ts +6 -0
  490. package/dist/testing/conformance/properties.js +295 -0
  491. package/dist/testing/conformance/protocols.d.ts +4 -0
  492. package/dist/testing/conformance/protocols.js +618 -0
  493. package/dist/testing/conformance/provider/advertise.d.ts +21 -0
  494. package/dist/testing/conformance/provider/advertise.js +44 -0
  495. package/dist/testing/conformance/read-your-writes.d.ts +20 -0
  496. package/dist/testing/conformance/read-your-writes.js +192 -0
  497. package/dist/testing/conformance/reducers.d.ts +8 -0
  498. package/dist/testing/conformance/reducers.js +258 -0
  499. package/dist/testing/conformance/relay.d.ts +42 -0
  500. package/dist/testing/conformance/relay.js +1115 -0
  501. package/dist/testing/conformance/restore.d.ts +43 -0
  502. package/dist/testing/conformance/restore.js +341 -0
  503. package/dist/testing/conformance/retention.d.ts +14 -0
  504. package/dist/testing/conformance/retention.js +463 -0
  505. package/dist/testing/conformance/rls.d.ts +24 -0
  506. package/dist/testing/conformance/rls.js +576 -0
  507. package/dist/testing/conformance/simulation.d.ts +31 -0
  508. package/dist/testing/conformance/simulation.js +167 -0
  509. package/dist/testing/conformance/single-shard.d.ts +2 -0
  510. package/dist/testing/conformance/single-shard.js +125 -0
  511. package/dist/testing/conformance/singleton.d.ts +3 -0
  512. package/dist/testing/conformance/singleton.js +293 -0
  513. package/dist/testing/conformance/statements.d.ts +60 -0
  514. package/dist/testing/conformance/statements.js +108 -0
  515. package/dist/testing/conformance/streams.d.ts +7 -0
  516. package/dist/testing/conformance/streams.js +280 -0
  517. package/dist/testing/conformance/subscriptions/access.d.ts +4 -0
  518. package/dist/testing/conformance/subscriptions/access.js +98 -0
  519. package/dist/testing/conformance/subscriptions/actors.d.ts +4910 -0
  520. package/dist/testing/conformance/subscriptions/actors.js +372 -0
  521. package/dist/testing/conformance/subscriptions/cluster.d.ts +4 -0
  522. package/dist/testing/conformance/subscriptions/cluster.js +89 -0
  523. package/dist/testing/conformance/subscriptions/delivery.d.ts +4 -0
  524. package/dist/testing/conformance/subscriptions/delivery.js +253 -0
  525. package/dist/testing/conformance/subscriptions/deploys.d.ts +4 -0
  526. package/dist/testing/conformance/subscriptions/deploys.js +162 -0
  527. package/dist/testing/conformance/subscriptions/epochs.d.ts +4 -0
  528. package/dist/testing/conformance/subscriptions/epochs.js +169 -0
  529. package/dist/testing/conformance/subscriptions/failures.d.ts +4 -0
  530. package/dist/testing/conformance/subscriptions/failures.js +108 -0
  531. package/dist/testing/conformance/subscriptions/feeds.d.ts +4 -0
  532. package/dist/testing/conformance/subscriptions/feeds.js +218 -0
  533. package/dist/testing/conformance/subscriptions/harness.d.ts +124 -0
  534. package/dist/testing/conformance/subscriptions/harness.js +143 -0
  535. package/dist/testing/conformance/subscriptions/operator.d.ts +4 -0
  536. package/dist/testing/conformance/subscriptions/operator.js +128 -0
  537. package/dist/testing/conformance/subscriptions/retention.d.ts +4 -0
  538. package/dist/testing/conformance/subscriptions/retention.js +288 -0
  539. package/dist/testing/conformance/subscriptions/routing.d.ts +4 -0
  540. package/dist/testing/conformance/subscriptions/routing.js +179 -0
  541. package/dist/testing/conformance/subscriptions.d.ts +4 -0
  542. package/dist/testing/conformance/subscriptions.js +19 -0
  543. package/dist/testing/conformance/tables.d.ts +125 -0
  544. package/dist/testing/conformance/tables.js +664 -0
  545. package/dist/testing/conformance/transports/actors.d.ts +1907 -0
  546. package/dist/testing/conformance/transports/actors.js +163 -0
  547. package/dist/testing/conformance/transports/client.d.ts +3 -0
  548. package/dist/testing/conformance/transports/client.js +237 -0
  549. package/dist/testing/conformance/transports/feeds.d.ts +3 -0
  550. package/dist/testing/conformance/transports/feeds.js +232 -0
  551. package/dist/testing/conformance/transports/harness.d.ts +93 -0
  552. package/dist/testing/conformance/transports/harness.js +84 -0
  553. package/dist/testing/conformance/transports/streams.d.ts +3 -0
  554. package/dist/testing/conformance/transports/streams.js +96 -0
  555. package/dist/testing/conformance/transports/websocket.d.ts +3 -0
  556. package/dist/testing/conformance/transports/websocket.js +384 -0
  557. package/dist/testing/conformance/transports/wire.d.ts +141 -0
  558. package/dist/testing/conformance/transports/wire.js +204 -0
  559. package/dist/testing/conformance/transports.d.ts +3 -0
  560. package/dist/testing/conformance/transports.js +11 -0
  561. package/dist/testing/conformance/watch.d.ts +59 -0
  562. package/dist/testing/conformance/watch.js +879 -0
  563. package/dist/testing/conformance/workflow-engine.d.ts +97 -0
  564. package/dist/testing/conformance/workflow-engine.js +253 -0
  565. package/dist/testing/conformance/workflow-versions.d.ts +3 -0
  566. package/dist/testing/conformance/workflow-versions.js +545 -0
  567. package/dist/testing/conformance/workflows/access.d.ts +4 -0
  568. package/dist/testing/conformance/workflows/access.js +147 -0
  569. package/dist/testing/conformance/workflows/actors.d.ts +2317 -0
  570. package/dist/testing/conformance/workflows/actors.js +305 -0
  571. package/dist/testing/conformance/workflows/basics.d.ts +4 -0
  572. package/dist/testing/conformance/workflows/basics.js +144 -0
  573. package/dist/testing/conformance/workflows/engine.d.ts +4 -0
  574. package/dist/testing/conformance/workflows/engine.js +80 -0
  575. package/dist/testing/conformance/workflows/guards.d.ts +4 -0
  576. package/dist/testing/conformance/workflows/guards.js +172 -0
  577. package/dist/testing/conformance/workflows/harness.d.ts +14 -0
  578. package/dist/testing/conformance/workflows/harness.js +44 -0
  579. package/dist/testing/conformance/workflows/recovery.d.ts +4 -0
  580. package/dist/testing/conformance/workflows/recovery.js +181 -0
  581. package/dist/testing/conformance/workflows/starts.d.ts +4 -0
  582. package/dist/testing/conformance/workflows/starts.js +57 -0
  583. package/dist/testing/conformance/workflows/suspension.d.ts +4 -0
  584. package/dist/testing/conformance/workflows/suspension.js +106 -0
  585. package/dist/testing/conformance/workflows/waits.d.ts +4 -0
  586. package/dist/testing/conformance/workflows/waits.js +284 -0
  587. package/dist/testing/conformance/workflows.d.ts +4 -0
  588. package/dist/testing/conformance/workflows.js +19 -0
  589. package/dist/testing/conformance.d.ts +330 -0
  590. package/dist/testing/conformance.js +364 -0
  591. package/dist/testing/database.d.ts +31 -0
  592. package/dist/testing/database.js +70 -0
  593. package/dist/testing/foundation.d.ts +41 -0
  594. package/dist/testing/foundation.js +517 -0
  595. package/dist/testing/index.d.ts +20 -0
  596. package/dist/testing/index.js +12 -0
  597. package/dist/testing/property.d.ts +40 -0
  598. package/dist/testing/property.js +95 -0
  599. package/dist/testing/simulate-cluster.d.ts +112 -0
  600. package/dist/testing/simulate-cluster.js +257 -0
  601. package/dist/testing/simulate.d.ts +90 -0
  602. package/dist/testing/simulate.js +127 -0
  603. package/package.json +1 -0
@@ -0,0 +1,19 @@
1
+ import { dual } from "effect/Function";
2
+ /** A read set that has recorded nothing. */
3
+ export const emptyReadSet = () => ({
4
+ state: false,
5
+ events: new Set(),
6
+ tables: new Set(),
7
+ blobs: new Set(),
8
+ group: false,
9
+ caller: false,
10
+ });
11
+ /** Whether a commit that wrote `writes` may have changed the result of a query that read `reads`. */
12
+ export const invalidates = dual(2, (writes, reads) => (writes.state && reads.state) ||
13
+ writes.events.some((tag) => reads.events.has(tag)) ||
14
+ writes.tables.some((table) => reads.tables.has(table)) ||
15
+ writes.blobs.some((blob) => reads.blobs.has(blob)));
16
+ /** The read that makes a query unwatchable, named for the refusal; undefined when every read is supported. */
17
+ export const unsupportedRead = (reads) => reads.group
18
+ ? "The query reads its placement group, which has no commit signal per actor"
19
+ : undefined;
@@ -0,0 +1,62 @@
1
+ import { Effect, Stream } from "effect";
2
+ import type { SqlClient } from "effect/sql";
3
+ import { ActorError } from "../../errors/actor.ts";
4
+ import type { ActorRef, Caller } from "../../identity/caller.ts";
5
+ import type { Registration, StreamInput } from "../members.ts";
6
+ import type { Activation } from "./owner.ts";
7
+ import type { Transport } from "./transport.ts";
8
+ /** One live subscription, owned until its subscriber or activation ends. */
9
+ export interface Subscription {
10
+ readonly member: string;
11
+ readonly caller: Caller;
12
+ /** When authorization last succeeded, on the framework clock. */
13
+ lastAuthorized: number;
14
+ checking: boolean;
15
+ /** Since when the handler has waited on a full window. */
16
+ stalledSince: number | undefined;
17
+ readonly end: (error: ActorError, discard: boolean) => Effect.Effect<void>;
18
+ }
19
+ /** Decides whether a caller may open a stream or renew its access; `false` refuses. */
20
+ export type Authorize = (request: {
21
+ readonly caller: Caller;
22
+ readonly ref: ActorRef;
23
+ readonly command: string;
24
+ readonly kind: "stream" | "reauthorize";
25
+ /** A stream tag must not be interpreted as a feed event tag. */
26
+ readonly of?: "stream";
27
+ }) => Effect.Effect<boolean>;
28
+ /**
29
+ * Owns stream admission, producer lifetime, bounded delivery and revocation.
30
+ * The connection owner supplies the committed read context only after access
31
+ * and capacity are checked; it retains generation acquisition and the ordered
32
+ * broadcast channel. Streams have no durable session rows or replay promise.
33
+ */
34
+ export declare const streamSubscriptions: ({ registration, activations, transport, authorize, now, prepare, }: {
35
+ readonly registration: Registration;
36
+ readonly activations: ReadonlyMap<string, Activation>;
37
+ readonly transport: Pick<Transport, "holder" | "epoch">;
38
+ readonly authorize: Authorize;
39
+ readonly now: Effect.Effect<number>;
40
+ readonly prepare: (activation: Activation) => Effect.Effect<Omit<StreamInput, "caller">, ActorError, SqlClient.SqlClient>;
41
+ }) => {
42
+ subscribe: (activation: Activation, request: {
43
+ readonly member: string;
44
+ readonly caller: Caller;
45
+ readonly input: string;
46
+ readonly authorizedUntil: number;
47
+ }) => Stream.Stream<{
48
+ readonly _tag: "Done";
49
+ } | {
50
+ readonly _tag: "Element";
51
+ readonly value: string;
52
+ } | {
53
+ readonly _tag: "Started";
54
+ readonly owner: string;
55
+ readonly ownerEpoch: string;
56
+ }, ActorError | {
57
+ readonly _tag: "StreamFailed";
58
+ readonly value: string;
59
+ }, SqlClient.SqlClient>;
60
+ end: (activation: Activation) => Effect.Effect<void, never, never>;
61
+ watch: Effect.Effect<void, never, never>;
62
+ };
@@ -0,0 +1,128 @@
1
+ import { Cause, Effect, Exit, Fiber, Queue, Schedule, Stream } from "effect";
2
+ import { ActorError, RunnerAtCapacity, SessionEnded, Unauthorized } from "../../errors/actor.js";
3
+ import { StreamFailed, StreamItem } from "./protocol.js";
4
+ /** Open stream subscriptions one actor may have. */
5
+ const MAX_ACTOR_STREAMS = 256;
6
+ /** Stream elements held for one subscriber before its handler waits. */
7
+ const STREAM_WINDOW = 256;
8
+ /** How long a stream's window may stay full before the subscription ends. */
9
+ const STREAM_STALL_MS = 30_000;
10
+ /** How often the owner checks subscriptions' authorization and windows. */
11
+ const STREAM_TICK = "100 millis";
12
+ const unauthorized = (code) => ActorError.make({ reason: Unauthorized.make({ code }) });
13
+ const ended = (cause, resync) => ActorError.make({ reason: SessionEnded.make({ cause, resync }) });
14
+ /**
15
+ * Owns stream admission, producer lifetime, bounded delivery and revocation.
16
+ * The connection owner supplies the committed read context only after access
17
+ * and capacity are checked; it retains generation acquisition and the ordered
18
+ * broadcast channel. Streams have no durable session rows or replay promise.
19
+ */
20
+ export const streamSubscriptions = ({ registration, activations, transport, authorize, now, prepare, }) => {
21
+ /** Natural completion follows all elements; every other end is an explicit error. */
22
+ const subscribe = (activation, request) => Stream.unwrap(Effect.gen(function* () {
23
+ const stream = registration.streams.get(request.member);
24
+ if (stream === undefined)
25
+ return yield* Effect.die(new Error(`Unregistered stream ${request.member}`));
26
+ if ((yield* now) >= request.authorizedUntil)
27
+ return yield* unauthorized("reauthorization_unavailable");
28
+ const allowed = yield* authorize({
29
+ caller: request.caller,
30
+ ref: activation.ref,
31
+ command: request.member,
32
+ kind: "stream",
33
+ });
34
+ if (!allowed)
35
+ return yield* unauthorized("access_denied");
36
+ const queue = yield* Queue.bounded(STREAM_WINDOW);
37
+ let producer;
38
+ let closed = false;
39
+ const subscription = {
40
+ member: request.member,
41
+ caller: request.caller,
42
+ lastAuthorized: yield* now,
43
+ checking: false,
44
+ stalledSince: undefined,
45
+ end: (error, discard) => Effect.gen(function* () {
46
+ if (closed)
47
+ return;
48
+ closed = true;
49
+ activation.streams.delete(subscription);
50
+ if (producer !== undefined)
51
+ yield* Fiber.interrupt(producer);
52
+ if (discard)
53
+ yield* Queue.clear(queue).pipe(Effect.ignore);
54
+ yield* Queue.fail(queue, error);
55
+ }),
56
+ };
57
+ const admitted = yield* Effect.sync(() => {
58
+ if (activation.streams.size >= MAX_ACTOR_STREAMS)
59
+ return false;
60
+ activation.streams.add(subscription);
61
+ return true;
62
+ });
63
+ if (!admitted)
64
+ return yield* ActorError.make({ reason: RunnerAtCapacity.make({}) });
65
+ yield* Effect.addFinalizer(() => Effect.gen(function* () {
66
+ closed = true;
67
+ activation.streams.delete(subscription);
68
+ if (producer !== undefined)
69
+ yield* Fiber.interrupt(producer);
70
+ }));
71
+ const input = yield* prepare(activation);
72
+ const offer = (item) => Effect.gen(function* () {
73
+ if (Queue.offerUnsafe(queue, item))
74
+ return;
75
+ subscription.stalledSince = yield* now;
76
+ yield* Queue.offer(queue, item);
77
+ subscription.stalledSince = undefined;
78
+ });
79
+ producer = yield* stream.run(request.input, { ...input, caller: request.caller }).pipe(Stream.runForEach((value) => offer(StreamItem.cases.Element.make({ value }))), Effect.andThen(offer(StreamItem.cases.Done.make({}))), Effect.andThen(Queue.end(queue)), Effect.catch(({ failure }) => Queue.fail(queue, StreamFailed.make({ value: failure }))), Effect.catchDefect((cause) => Effect.andThen(Effect.logError("Stream handler defect", Cause.die(cause)), Queue.fail(queue, ended("Defect", false)))), Effect.asVoid, Effect.ensuring(Effect.sync(() => {
80
+ closed = true;
81
+ activation.streams.delete(subscription);
82
+ })), Effect.forkDetach);
83
+ return Stream.succeed(StreamItem.cases.Started.make({ owner: transport.holder, ownerEpoch: transport.epoch })).pipe(Stream.concat(Stream.fromQueue(queue)));
84
+ }));
85
+ const end = (activation) => Effect.forEach([...activation.streams], (subscription) => subscription.end(ended("ActivationEnded", false), false), { discard: true });
86
+ const reauthorize = (activation, subscription, at) => Effect.gen(function* () {
87
+ subscription.checking = true;
88
+ const every = registration.policy.reauthorizeMs;
89
+ const allowed = yield* authorize({
90
+ caller: subscription.caller,
91
+ ref: activation.ref,
92
+ command: subscription.member,
93
+ kind: "reauthorize",
94
+ of: "stream",
95
+ }).pipe(Effect.timeout(Math.min(10_000, every / 2)), Effect.exit);
96
+ subscription.checking = false;
97
+ const bound = subscription.lastAuthorized + every;
98
+ if (Exit.isSuccess(allowed) && allowed.value && (yield* now) >= bound)
99
+ yield* subscription.end(unauthorized("reauthorization_unavailable"), true);
100
+ else if (Exit.isSuccess(allowed) && allowed.value)
101
+ subscription.lastAuthorized = at;
102
+ else if (Exit.isSuccess(allowed))
103
+ yield* subscription.end(unauthorized("access_denied"), true);
104
+ });
105
+ /** Revocation discards undelivered elements, including while a check is in flight. */
106
+ const watch = Effect.gen(function* () {
107
+ const at = yield* now;
108
+ const every = registration.policy.reauthorizeMs;
109
+ for (const activation of activations.values())
110
+ for (const subscription of activation.streams) {
111
+ if (at >= subscription.lastAuthorized + every) {
112
+ yield* subscription
113
+ .end(unauthorized("reauthorization_unavailable"), true)
114
+ .pipe(Effect.forkDetach);
115
+ continue;
116
+ }
117
+ if (subscription.stalledSince !== undefined &&
118
+ at - subscription.stalledSince >= STREAM_STALL_MS) {
119
+ yield* subscription.end(ended("SlowConsumer", true), true).pipe(Effect.forkDetach);
120
+ continue;
121
+ }
122
+ if (!subscription.checking &&
123
+ at >= subscription.lastAuthorized + every - Math.min(10_000, every / 2))
124
+ yield* reauthorize(activation, subscription, at).pipe(Effect.forkDetach);
125
+ }
126
+ }).pipe(Effect.repeat(Schedule.spaced(STREAM_TICK)), Effect.asVoid);
127
+ return { subscribe, end, watch };
128
+ };
@@ -0,0 +1,40 @@
1
+ import { Crypto, Effect, Schema } from "effect";
2
+ import { Sharding, ShardingConfig } from "effect/cluster";
3
+ import { type Deliver, type Delivered } from "./protocol.ts";
4
+ declare const HolderUnreachable_base: Schema.Class<HolderUnreachable, Schema.TaggedStruct<"HolderUnreachable", {
5
+ readonly message: Schema.String;
6
+ }>, import("effect/Cause").YieldableError>;
7
+ /** A holder could not be reached: the owner treats its connections as lost. */
8
+ export declare class HolderUnreachable extends HolderUnreachable_base {
9
+ }
10
+ /**
11
+ * This runner's transport identity and the channel to every other runner's
12
+ * holder. A runner with a Cluster address hosts a holder entity in a shard
13
+ * group named after that address; an unclustered runtime reaches only itself.
14
+ */
15
+ export interface Transport {
16
+ readonly holder: string;
17
+ readonly epoch: string;
18
+ readonly deliver: (holder: string, epoch: string, message: Deliver) => Effect.Effect<Delivered, HolderUnreachable>;
19
+ /** Whether the runner `holder` is still running the process that took `epoch`. */
20
+ readonly ping: (holder: string, epoch: string) => Effect.Effect<boolean>;
21
+ }
22
+ /**
23
+ * A runner that hosts no actors still hosts its own holder, so its group is
24
+ * assigned regardless of the configured ones.
25
+ */
26
+ export declare const holderShardGroups: (config: Partial<ShardingConfig.ShardingConfig["Service"]>) => {} | {
27
+ availableShardGroups: string[];
28
+ assignedShardGroups: string[];
29
+ };
30
+ /**
31
+ * Shard placement for the holder's own group can lag a moment behind registration,
32
+ * so an unassigned entity is retried.
33
+ */
34
+ export declare const holderTransport: (local: (message: Deliver) => Effect.Effect<Delivered>) => Effect.Effect<{
35
+ holder: string;
36
+ epoch: string;
37
+ deliver: (holder: string, epoch: string, message: Deliver) => Effect.Effect<Delivered, HolderUnreachable>;
38
+ ping: (holder: string, epoch: string) => Effect.Effect<boolean>;
39
+ }, never, Crypto.Crypto | import("effect/Scope").Scope | Sharding.Sharding | ShardingConfig.ShardingConfig>;
40
+ export {};
@@ -0,0 +1,68 @@
1
+ import { Crypto, Effect, Option, Schedule, Schema } from "effect";
2
+ import { ClusterError, EntityId, Sharding, ShardingConfig } from "effect/cluster";
3
+ import { HolderEntity, holderEntityId, holderGroup, } from "./protocol.js";
4
+ const LOCAL = "local";
5
+ /** How long an owner waits for a holder to acknowledge one message, before one retry. */
6
+ const ACK_TIMEOUT = "1 second";
7
+ /** A holder could not be reached: the owner treats its connections as lost. */
8
+ export class HolderUnreachable extends Schema.TaggedError()("HolderUnreachable", { message: Schema.String }) {
9
+ }
10
+ /**
11
+ * A runner that hosts no actors still hosts its own holder, so its group is
12
+ * assigned regardless of the configured ones.
13
+ */
14
+ export const holderShardGroups = (config) => Option.match(config.runnerAddress ?? Option.none(), {
15
+ onNone: () => ({}),
16
+ onSome: (address) => ({
17
+ availableShardGroups: ["default", holderGroup(address)],
18
+ assignedShardGroups: [...(config.assignedShardGroups ?? ["default"]), holderGroup(address)],
19
+ }),
20
+ });
21
+ /**
22
+ * Shard placement for the holder's own group can lag a moment behind registration,
23
+ * so an unassigned entity is retried.
24
+ */
25
+ export const holderTransport = Effect.fnUntraced(function* (local) {
26
+ const config = yield* ShardingConfig.ShardingConfig;
27
+ const sharding = yield* Sharding.Sharding;
28
+ const crypto = yield* Crypto.Crypto;
29
+ const epoch = yield* crypto.randomUUIDv7.pipe(Effect.orDie);
30
+ const holder = Option.match(config.runnerAddress, {
31
+ onNone: () => LOCAL,
32
+ onSome: holderGroup,
33
+ });
34
+ const clustered = holder !== LOCAL && config.assignedShardGroups.includes(holder);
35
+ if (clustered)
36
+ yield* sharding.registerEntity(HolderEntity, Effect.succeed(HolderEntity.of({
37
+ Deliver: ({ payload }) => payload.epoch === epoch
38
+ ? local(payload)
39
+ : Effect.succeed({ wrongEpoch: true, unknown: [] }),
40
+ Ping: ({ payload }) => Effect.succeed(payload.epoch === epoch),
41
+ })), { concurrency: "unbounded" });
42
+ const client = clustered ? yield* sharding.makeClient(HolderEntity) : undefined;
43
+ const deliver = (target, targetEpoch, message) => {
44
+ if (target === holder)
45
+ return targetEpoch === epoch
46
+ ? local(message)
47
+ : Effect.succeed({ wrongEpoch: true, unknown: [] });
48
+ if (client === undefined || target === LOCAL)
49
+ return Effect.fail(HolderUnreachable.make({ message: `Holder ${target} is not reachable` }));
50
+ return client(EntityId.make(holderEntityId({ holder: target, epoch: targetEpoch })))
51
+ .Deliver(message)
52
+ .pipe(Effect.retry({
53
+ while: (error) => ClusterError.EntityNotAssignedToRunner.is(error) ||
54
+ ClusterError.RunnerUnavailable.is(error),
55
+ schedule: Schedule.spaced("50 millis"),
56
+ }), Effect.timeout(ACK_TIMEOUT), Effect.retry({ times: 1 }), Effect.mapError(() => HolderUnreachable.make({ message: `Holder ${target} did not acknowledge` })));
57
+ };
58
+ const ping = (target, targetEpoch) => {
59
+ if (target === holder)
60
+ return Effect.succeed(targetEpoch === epoch);
61
+ if (client === undefined || target === LOCAL)
62
+ return Effect.succeed(false);
63
+ return client(EntityId.make(holderEntityId({ holder: target, epoch: targetEpoch })))
64
+ .Ping({ epoch: targetEpoch })
65
+ .pipe(Effect.timeout(ACK_TIMEOUT), Effect.retry({ times: 1 }), Effect.orElseSucceed(() => false));
66
+ };
67
+ return { holder, epoch, deliver, ping };
68
+ });
@@ -0,0 +1,52 @@
1
+ import { Context, Effect, Stream } from "effect";
2
+ import { ActorError } from "../../errors/actor.ts";
3
+ import { Outcome, type Request } from "../request.ts";
4
+ import { type WatchResult } from "../members.ts";
5
+ import type { Holder } from "./holder.ts";
6
+ import { type ReadSet } from "./reads.ts";
7
+ /**
8
+ * Asked before an owner broadcasts a commit's `Committed` frame; `true` drops
9
+ * it, as a lost best-effort broadcast would. Tests drop frames here to show
10
+ * the reconcile rerun recovers them.
11
+ */
12
+ export declare const WatchTap: Context.Reference<{
13
+ readonly dropsCommitted: () => boolean;
14
+ }>;
15
+ /** What a watch needs from its runner: the holder its connection parks at, and one rerun of the query. */
16
+ export interface WatchOptions {
17
+ readonly holder: Holder;
18
+ /** The request to watch: `command` is the query and `payload` its encoded input. */
19
+ readonly request: Request;
20
+ readonly minIntervalMs: number;
21
+ readonly reconcileMs: number;
22
+ /** A commit version the first result must reflect at least. */
23
+ readonly minVersion: string | undefined;
24
+ /** The credential's own expiry in epoch milliseconds, if it has one. */
25
+ readonly expiresAt: number | undefined;
26
+ /**
27
+ * Reruns the query for this watch and records what it read. `version` is
28
+ * called once the rerun holds its place among the runner's reruns, so a rerun
29
+ * that waited for one starts from the newest version seen meanwhile.
30
+ */
31
+ readonly rerun: (version: () => string | undefined, reads: ReadSet) => Effect.Effect<Outcome, ActorError>;
32
+ }
33
+ /**
34
+ * A watch on one query: its current result first, then the newest result after
35
+ * each commit whose writes intersect what the last run read. The watch is a
36
+ * parked framework connection, so the owner sends it one `Committed` frame per
37
+ * commit and nothing keeps the actor resident.
38
+ *
39
+ * Reruns are coalesced: at most one runs and one waits, frames that arrive
40
+ * meanwhile only raise the version the next rerun waits for, and reruns of one
41
+ * watch start at least `minIntervalMs` apart. A result equal to the last one
42
+ * sent is not sent, and the newest result replaces one nobody has read yet, so
43
+ * a slow reader never ends the watch. The broadcast is best-effort, so the
44
+ * watch also reruns every `reconcileMs`, after a holder resync, and after a
45
+ * reopen, which is how a lost frame or a change no commit reports is shown.
46
+ * A rerun that reads what a commit signal cannot cover ends the watch with
47
+ * `not_watchable`, and one that fails transiently is retried. A result read
48
+ * for a session past its authorization bound is dropped.
49
+ */
50
+ export declare const watchStream: (options: WatchOptions) => Effect.Effect<Stream.Stream<WatchResult, ActorError | {
51
+ readonly failure: string;
52
+ }, never>, ActorError, never>;
@@ -0,0 +1,159 @@
1
+ import { Clock, Context, Deferred, Effect, Match, Option, Predicate, Queue, Result, Schema, Stream, } from "effect";
2
+ import { ActorError, InvalidInput, SessionEnded } from "../../errors/actor.js";
3
+ import { Outcome } from "../request.js";
4
+ import {} from "../members.js";
5
+ import { Committed, watchMember } from "./protocol.js";
6
+ import { emptyReadSet, invalidates, unsupportedRead } from "./reads.js";
7
+ /**
8
+ * Asked before an owner broadcasts a commit's `Committed` frame; `true` drops
9
+ * it, as a lost best-effort broadcast would. Tests drop frames here to show
10
+ * the reconcile rerun recovers them.
11
+ */
12
+ export const WatchTap = Context.Reference("@rikalabs/akter/runtime/connections/watch/WatchTap", { defaultValue: () => ({ dropsCommitted: () => false }) });
13
+ /** How long a watch waits before it reruns after a rerun failed for a reason a later attempt may not share. */
14
+ const RERUN_RETRY_MS = 1_000;
15
+ const decodeCommitted = Schema.decodeEffect(Schema.fromJsonString(Committed));
16
+ /** Ends that a watch survives by reopening at its holder and rerunning, as a feed does. */
17
+ const recoverable = (error) => Predicate.isTagged(error.reason, "SessionEnded") &&
18
+ ["SlowConsumer", "OwnerLost", "ActorUnavailable"].includes(error.reason.cause);
19
+ /** Failures of a rerun that the next attempt may not repeat. */
20
+ const transient = (error) => Predicate.isTagged(error.reason, "ActorUnavailable") ||
21
+ Predicate.isTagged(error.reason, "Timeout") ||
22
+ Predicate.isTagged(error.reason, "RunnerAtCapacity");
23
+ /**
24
+ * A watch on one query: its current result first, then the newest result after
25
+ * each commit whose writes intersect what the last run read. The watch is a
26
+ * parked framework connection, so the owner sends it one `Committed` frame per
27
+ * commit and nothing keeps the actor resident.
28
+ *
29
+ * Reruns are coalesced: at most one runs and one waits, frames that arrive
30
+ * meanwhile only raise the version the next rerun waits for, and reruns of one
31
+ * watch start at least `minIntervalMs` apart. A result equal to the last one
32
+ * sent is not sent, and the newest result replaces one nobody has read yet, so
33
+ * a slow reader never ends the watch. The broadcast is best-effort, so the
34
+ * watch also reruns every `reconcileMs`, after a holder resync, and after a
35
+ * reopen, which is how a lost frame or a change no commit reports is shown.
36
+ * A rerun that reads what a commit signal cannot cover ends the watch with
37
+ * `not_watchable`, and one that fails transiently is retried. A result read
38
+ * for a session past its authorization bound is dropped.
39
+ */
40
+ export const watchStream = Effect.fnUntraced(function* (options) {
41
+ const { holder, request } = options;
42
+ const open = holder
43
+ .open({
44
+ ref: request.ref,
45
+ member: watchMember(request.command),
46
+ caller: request.caller,
47
+ params: "",
48
+ expiresAt: options.expiresAt,
49
+ })
50
+ .pipe(Effect.catchTag("OpenRejected", () => Effect.die(new Error("A watch has no open handler"))));
51
+ const first = yield* open;
52
+ return Stream.callback((out) => Effect.gen(function* () {
53
+ let held = first;
54
+ let pending = options.minVersion === undefined ? undefined : BigInt(options.minVersion);
55
+ let reads;
56
+ let dirty = true;
57
+ let sent;
58
+ let settling = [];
59
+ const signal = yield* Queue.sliding(1);
60
+ yield* Effect.addFinalizer(() => held.close);
61
+ const raise = () => {
62
+ dirty = true;
63
+ Queue.offerUnsafe(signal, undefined);
64
+ };
65
+ const note = (committed) => {
66
+ const version = BigInt(committed.version);
67
+ if (pending === undefined || version > pending)
68
+ pending = version;
69
+ if (reads === undefined || invalidates(committed.writes, reads))
70
+ raise();
71
+ };
72
+ const listen = (connection) => connection.messages.pipe(Stream.runForEach((item) => Match.value(item).pipe(Match.tagsExhaustive({
73
+ Frame: (frame) => decodeCommitted(frame.frame).pipe(Effect.orDie, Effect.map(note)),
74
+ Resync: () => Effect.void,
75
+ ResyncReplayed: () => Effect.gen(function* () {
76
+ const done = yield* Deferred.make();
77
+ settling.push(done);
78
+ raise();
79
+ yield* Deferred.await(done);
80
+ yield* connection.resyncDone;
81
+ }),
82
+ Progress: () => Effect.void,
83
+ }))));
84
+ const follow = Effect.gen(function* () {
85
+ while (true) {
86
+ const ended = yield* listen(held).pipe(Effect.flip, Effect.option);
87
+ if (Option.isNone(ended))
88
+ return;
89
+ if (!recoverable(ended.value))
90
+ return yield* ended.value;
91
+ held = yield* open;
92
+ raise();
93
+ }
94
+ });
95
+ const refuse = (reason) => ActorError.make({
96
+ reason: InvalidInput.make({
97
+ code: "not_watchable",
98
+ issues: [{ path: request.command, message: reason }],
99
+ }),
100
+ });
101
+ const rerun = Effect.gen(function* () {
102
+ const read = emptyReadSet();
103
+ let version;
104
+ const outcome = yield* options
105
+ .rerun(() => (version = pending?.toString()), read)
106
+ .pipe(Effect.result);
107
+ if (Result.isFailure(outcome)) {
108
+ if (!transient(outcome.failure))
109
+ return yield* outcome.failure;
110
+ raise();
111
+ yield* Effect.sleep(RERUN_RETRY_MS);
112
+ return;
113
+ }
114
+ const result = outcome.success;
115
+ if (Outcome.guards.Failure(result))
116
+ return yield* Effect.fail({ failure: result.value });
117
+ if (Outcome.guards.Defect(result)) {
118
+ yield* Effect.logError("Watch handler defect", result.cause);
119
+ return yield* ActorError.make({
120
+ reason: SessionEnded.make({ cause: "Defect", resync: false }),
121
+ });
122
+ }
123
+ if (!Outcome.guards.Success(result))
124
+ return yield* Effect.die(new Error("A query cannot acknowledge"));
125
+ const unsupported = unsupportedRead(read);
126
+ if (unsupported !== undefined)
127
+ return yield* refuse(unsupported);
128
+ reads = read;
129
+ if (result.value === sent || !(yield* held.authorized))
130
+ return;
131
+ sent = result.value;
132
+ yield* Queue.offer(out, { version, value: result.value });
133
+ });
134
+ const reruns = Effect.gen(function* () {
135
+ let startedAt = Number.NEGATIVE_INFINITY;
136
+ while (true) {
137
+ while (!dirty) {
138
+ const woke = yield* Queue.take(signal).pipe(Effect.timeoutOption(options.reconcileMs));
139
+ if (Option.isNone(woke))
140
+ dirty = true;
141
+ }
142
+ const wait = startedAt + options.minIntervalMs - (yield* Clock.currentTimeMillis);
143
+ if (wait > 0)
144
+ yield* Effect.sleep(wait);
145
+ startedAt = yield* Clock.currentTimeMillis;
146
+ dirty = false;
147
+ const covered = settling;
148
+ settling = [];
149
+ yield* rerun;
150
+ yield* Effect.forEach(covered, (done) => Deferred.succeed(done, undefined), {
151
+ discard: true,
152
+ });
153
+ }
154
+ });
155
+ yield* Effect.all([follow, reruns], { concurrency: "unbounded", discard: true }).pipe(Effect.catch((error) => Schema.is(ActorError)(error) && Predicate.isTagged(error.reason, "Unauthorized")
156
+ ? Effect.andThen(Effect.ignore(Queue.clear(out)), Queue.fail(out, error))
157
+ : Queue.fail(out, error)), Effect.catchCause((cause) => Queue.failCause(out, cause)), Effect.forkScoped);
158
+ }), { bufferSize: 1, strategy: "sliding" });
159
+ });
@@ -0,0 +1,34 @@
1
+ import { Effect, Redacted, Result } from "effect";
2
+ import type { InvalidContentRef } from "../../errors/content.ts";
3
+ /** How long a grant lasts from when it is issued. */
4
+ export declare const GRANT_LIFETIME_MS = 3600000;
5
+ /** One deployment secret grants are signed or verified with. */
6
+ export interface GrantKey {
7
+ /** Named in every grant it signs, so a rotated-out key still verifies its grants. */
8
+ readonly id: string;
9
+ /** At least 32 bytes of UTF-8. */
10
+ readonly secret: Redacted.Redacted<string>;
11
+ }
12
+ /** What a grant binds. The deployment id keeps grants of one database out of another. */
13
+ export interface Granted {
14
+ readonly tenant: string;
15
+ readonly hash: string;
16
+ readonly size: number;
17
+ readonly expiresAt: number;
18
+ }
19
+ /** Signs and verifies content grants. Verification compares MACs in constant time (WebCrypto). */
20
+ export interface Grants {
21
+ /** Signs with the first key. */
22
+ readonly sign: (granted: Granted) => Effect.Effect<string>;
23
+ /**
24
+ * Checks a grant's MAC under any configured key; returns its expiry. The
25
+ * caller checks the expiry against the database clock.
26
+ */
27
+ readonly verify: (grant: string, bound: Omit<Granted, "expiresAt">) => Effect.Effect<Result.Result<number, InvalidContentRef["reason"]>>;
28
+ }
29
+ /**
30
+ * Validates `keys` and imports them once. The first key signs; every key
31
+ * verifies, so an operator adds the new key first, keeps the old one listed
32
+ * for one grant lifetime, and then removes it.
33
+ */
34
+ export declare const grantKeys: (keys: readonly GrantKey[], deployment: string) => Effect.Effect<Grants, never, never>;
@@ -0,0 +1,58 @@
1
+ import { Effect, Redacted, Result } from "effect";
2
+ import { Base64Url } from "effect/encoding";
3
+ /** How long a grant lasts from when it is issued. */
4
+ export const GRANT_LIFETIME_MS = 3_600_000;
5
+ const KEY_ID = /^[A-Za-z0-9_-]{1,32}$/;
6
+ /** A grant is `g1.<key id>.<expires ms>.<mac>`, the MAC as unpadded base64url of 32 bytes. */
7
+ const GRANT = /^g1\.([A-Za-z0-9_-]{1,32})\.([1-9][0-9]{0,15})\.([A-Za-z0-9_-]{43})$/;
8
+ const utf8 = new TextEncoder();
9
+ /** The signed message: length-prefixed parts, so no two bindings encode to the same message. */
10
+ const message = (deployment, granted) => utf8.encode([
11
+ "durable-content/v1",
12
+ deployment,
13
+ granted.tenant,
14
+ granted.hash,
15
+ String(granted.size),
16
+ String(granted.expiresAt),
17
+ ]
18
+ .map((part) => `${part.length}:${part}`)
19
+ .join(""));
20
+ /**
21
+ * Validates `keys` and imports them once. The first key signs; every key
22
+ * verifies, so an operator adds the new key first, keeps the old one listed
23
+ * for one grant lifetime, and then removes it.
24
+ */
25
+ export const grantKeys = Effect.fnUntraced(function* (keys, deployment) {
26
+ if (keys.length === 0)
27
+ return yield* Effect.die(new Error("content.keys needs at least one key"));
28
+ const imported = new Map();
29
+ for (const key of keys) {
30
+ if (!KEY_ID.test(key.id))
31
+ return yield* Effect.die(new Error("content.keys ids are 1-32 letters, digits, - or _"));
32
+ if (imported.has(key.id))
33
+ return yield* Effect.die(new Error(`content.keys lists ${key.id} twice`));
34
+ const secret = utf8.encode(Redacted.value(key.secret));
35
+ if (secret.byteLength < 32)
36
+ return yield* Effect.die(new Error(`content.keys ${key.id} needs a secret of at least 32 bytes`));
37
+ imported.set(key.id, yield* Effect.promise(() => globalThis.crypto.subtle.importKey("raw", secret, { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"])));
38
+ }
39
+ const signer = keys[0].id;
40
+ const grants = {
41
+ sign: (granted) => Effect.promise(() => globalThis.crypto.subtle.sign("HMAC", imported.get(signer), message(deployment, granted))).pipe(Effect.map((mac) => `g1.${signer}.${granted.expiresAt}.${Base64Url.encode(new Uint8Array(mac))}`)),
42
+ verify: (grant, bound) => Effect.gen(function* () {
43
+ const parts = GRANT.exec(grant);
44
+ if (parts === null)
45
+ return Result.fail("malformed");
46
+ const expiresAt = Number(parts[2]);
47
+ const key = imported.get(parts[1]);
48
+ const mac = Base64Url.decode(parts[3]);
49
+ if (!Number.isSafeInteger(expiresAt) || Result.isFailure(mac))
50
+ return Result.fail("malformed");
51
+ if (key === undefined)
52
+ return Result.fail("invalid");
53
+ const valid = yield* Effect.promise(() => globalThis.crypto.subtle.verify("HMAC", key, new Uint8Array(mac.success), message(deployment, { ...bound, expiresAt })));
54
+ return valid ? Result.succeed(expiresAt) : Result.fail("invalid");
55
+ }),
56
+ };
57
+ return grants;
58
+ });