@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,876 @@
1
+ import { PgClient, PgTypes } from "@effect/sql-pg";
2
+ import { PgliteClient } from "@effect/sql-pglite";
3
+ import { Cause, Clock, Semaphore, Context, Crypto, Duration, Deferred, Effect, Fiber, Layer, Option, Result, Schedule, Schema, Stream, } from "effect";
4
+ import { ClusterError, Entity, EntityId, RunnerHealth, Runners, RunnerStorage, Sharding, ShardingConfig, } from "effect/cluster";
5
+ import { SqlClient, SqlError } from "effect/sql";
6
+ import { ActorError, ActorUnavailable, InvalidInput, Unauthorized, Timeout, MailboxFull, RunnerAtCapacity, } from "../errors/actor.js";
7
+ import { Actors } from "../handles/actors.js";
8
+ import {} from "./members.js";
9
+ import { DeliveryFailed } from "./request.js";
10
+ import { InternalActors } from "./actors.js";
11
+ import { System } from "../identity/caller.js";
12
+ import { deriveMintId } from "../identity/mint.js";
13
+ import { migrate } from "./database/migrations.js";
14
+ import { NekiTurnSessions } from "./database/neki/session.js";
15
+ import { queryPoolLayer, ReadReplica, replicaLayer } from "./database/replica.js";
16
+ import { Coordination, coordinationLayer } from "./database/coordination.js";
17
+ import { withKeepalives } from "./database/keepalive.js";
18
+ import { checkRowLevelSecurity, TenantScope } from "./database/tenancy.js";
19
+ import { retryDelay } from "./retry.js";
20
+ import { withoutDatabase } from "./jobs/isolation.js";
21
+ import { pglite } from "./database/pglite.js";
22
+ import { commandEntity, connectionEntity, encodeEntityId } from "./entity/register.js";
23
+ import { connectionHolder } from "./connections/holder.js";
24
+ import { holderShardGroups, holderTransport } from "./connections/transport.js";
25
+ import { ProgressSink, ProgressTap } from "./jobs/progress.js";
26
+ import { FEED_MEMBER, isWatchMember, watchedQuery } from "./connections/protocol.js";
27
+ import { checkIdentity, databaseTime, FrameworkClock } from "./turn/admission.js";
28
+ import { routingKey } from "./storage/codec.js";
29
+ import { recordedPlacement } from "./storage/placements.js";
30
+ import { TurnHooks } from "./turn/hooks.js";
31
+ import { requestAttributes, SpanNames } from "./telemetry/spans.js";
32
+ import { DefectLog, boundedDefectLog } from "./telemetry/defects.js";
33
+ import { OperatorRuntime, operatorRuntime } from "./operators/repair.js";
34
+ import { seedRuntime } from "./operators/seed.js";
35
+ import { TelemetrySampler } from "./telemetry/sampler.js";
36
+ import { turnGroups } from "./turn/group.js";
37
+ import { TurnConnections, turnConnections } from "./turn/pipeline.js";
38
+ import { outboxRelay } from "./turn/relay.js";
39
+ import { subscriptionRelay, } from "./subscriptions/relay.js";
40
+ import { DEFAULT_WRITER_WINDOW_MS, refreshWriters } from "./payloads/versions.js";
41
+ import { ExecutionTarget, INTERRUPT } from "../handles/workflow.js";
42
+ import { decodeExecutionId } from "../identity/execution.js";
43
+ import { coordinatedRunnerStorage, keepAcquiredShards, ShardLease, tableShardLease, } from "./topology/locks.js";
44
+ import { directMessages } from "./topology/messages.js";
45
+ import { MailboxRefusals, mailboxRefusals } from "./topology/admission.js";
46
+ import { bindBlobs } from "./turn/blobs.js";
47
+ import { ContentStore } from "../handles/content.js";
48
+ import { isContent } from "../members/blob.js";
49
+ import { grantKeys } from "./content/grant.js";
50
+ import { MAX_CONTENT_BYTES, tenantContent } from "./content/store.js";
51
+ import { ContentHooks } from "./turn/hooks.js";
52
+ import { bindTables, rowsDatabase } from "./turn/rows.js";
53
+ import { admissionLimit, isOverloaded, overloaded } from "./admission.js";
54
+ import { boundedLayer, isPoolRefusal } from "./database/bounded.js";
55
+ import { RuntimeControl, runtimeControl, turnGate } from "./drain.js";
56
+ import { eventFeeds } from "./feeds.js";
57
+ import { committedReads } from "./queries.js";
58
+ import { servingReadiness } from "./readiness.js";
59
+ import { acquiredShards, checkRunnerConfiguration, RunnerReadiness, LocalRequestSerialization, RunnerWiring, } from "./runner.js";
60
+ import { actorRegistration } from "./registration.js";
61
+ import { startSweeps } from "./sweeps.js";
62
+ import { checkFleet } from "./fleet/checks.js";
63
+ import { maintain } from "./fleet/maintainer.js";
64
+ import { fleetSubscriptions } from "./fleet/subscribe.js";
65
+ const Count = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1_000_000 }));
66
+ const Millis = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 2_147_483_647 }));
67
+ const millis = (duration) => Millis.make(Math.floor(Duration.toMillis(Duration.fromInputUnsafe(duration))));
68
+ const decodeTarget = Schema.decodeEffect(ExecutionTarget);
69
+ /** How often a fleet subscription is authorized again when its source's actor type is not registered here. */
70
+ const DEFAULT_REAUTHORIZE_MS = 60_000;
71
+ /** Added to the longest turn a claimed intent's receiver may take. */
72
+ const CLAIM_MARGIN_MS = 5000;
73
+ /** The claim lease when no actor type is registered: default policies' 30 s + 2 s + margin. */
74
+ const DEFAULT_CLAIM_LEASE_MS = 37_000;
75
+ /** How long a progress send may take before it is given up as a lost frame. */
76
+ const PROGRESS_SEND_TIMEOUT = "5 seconds";
77
+ /**
78
+ * An entity type with no messages, registered before any actor. The cluster's
79
+ * idle sweep takes its interval from the first entity type registered and
80
+ * sleeps that long before it reads any later one, so an actor type with a
81
+ * 60-second `hibernateAfter` registering first held every activation for up to
82
+ * 30 seconds past its own `hibernateAfter`. This type's 5-second idle time, the
83
+ * sweep's shortest interval, makes every sweep 5 seconds apart from the start.
84
+ */
85
+ const IdleSweep = Entity.make("akter/IdleSweep", []);
86
+ /**
87
+ * Builds the runtime: migrates and checks the database, registers every actor,
88
+ * effect, query, and subscription layer, and starts the relay and background
89
+ * sweeps. The returned layer provides `RuntimeControl`, and fails to build when
90
+ * the schema or declared payloads are incompatible.
91
+ *
92
+ * Constraints the wiring keeps:
93
+ * - Turns run through the drain gate, so a drain refuses new turns and
94
+ * interrupts the rest. The runtime scope, not the caller, owns an in-flight
95
+ * turn: interrupting a waiter never cancels it.
96
+ * - Commands are direct, so Cluster keeps no messages and the receipt is the
97
+ * only admission record; a restarted activation or lost runner drops the
98
+ * uncommitted attempt, the handle retries with the same command id, and the
99
+ * receipt replays anything that committed. Durable intents use the
100
+ * actor-shard outbox. Retries wait from the error's own `retryAfter`, bounded
101
+ * in total by the delivery timeout.
102
+ * - Intents are admitted by their sending turn, so internal delivery skips the
103
+ * external access and expiry checks: revocation stops new commands, not
104
+ * committed obligations. A draining runner admits no new external work. Only
105
+ * the relay presents a mint proof or delivers a subscription envelope.
106
+ * - A turn runs only in a resident activation. After a capacity rejection with
107
+ * none resident, the latest attempt was not admitted, though an earlier one
108
+ * may have committed.
109
+ * - Queries and feeds read committed rows on the caller's node without an
110
+ * activation, generation fence, receipt, or command id. State and events are
111
+ * read against one event head so they describe one moment; a replica answers
112
+ * only once it has replayed the caller's commit version, else the primary
113
+ * does. Types with owned tables or blobs read their state on the primary,
114
+ * one server per query. No `statement_timeout` bounds query reads;
115
+ * interrupting one past `commandTimeout` cancels its statement on the server.
116
+ * Access is rechecked after the handler, so a result is released only to a
117
+ * caller still allowed. A failed replay read is unavailability, not a defect.
118
+ * - Effect progress is fire-and-forget to the performing actor's connection
119
+ * entity: no retry, no acknowledgment, and a lost message is a lost frame.
120
+ * Each effect's last frame is awaited so its close never overtakes it.
121
+ * - Payload versions this runtime writes are recorded and heartbeat before a
122
+ * type takes any shard, refreshed one at a time with the time taken before
123
+ * the statement is sent, so the gate's window can only end early.
124
+ * - Content grants are bound to the database's deployment id. The content
125
+ * sweep waits out the longest turn that may attach content across every
126
+ * runner, and each tenant is swept at most once an hour.
127
+ * - Exactly one runner of the deployment runs the telemetry sampler; runtimes
128
+ * sharing one Sharding in a process share its one sampler.
129
+ * - Readiness on PGlite always answers from the layer's own lifetime, since a
130
+ * single connection held by a turn would make a probe report unready; on
131
+ * Postgres the database answers at most once a second.
132
+ * - PGlite keeps runner bookkeeping in memory because SqlRunnerStorage would
133
+ * reserve its single connection for the layer's lifetime. Postgres uses
134
+ * advisory locks, held by a live session, so no second runner can take a
135
+ * shard while its holder runs.
136
+ * - An unreachable database fails a read as `ActorUnavailable`, which callers
137
+ * retry like any delivery failure; it is not a defect.
138
+ */
139
+ export const layer = (options = {}) => {
140
+ const enforcedTypes = new Set();
141
+ const retryWindowMs = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 2_592_000_000 })).make(options.retryWindowMs ?? 86_400_000);
142
+ const maxResidentActors = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 2_147_483_647 })).make(options.maxResidentActors ?? 10_000);
143
+ const admissionSettings = {
144
+ concurrency: Count.make(options.admission?.concurrency ?? 64),
145
+ wait: Duration.millis(millis(options.admission?.wait ?? "100 millis")),
146
+ requests: Count.make(options.admission?.requests ?? 64),
147
+ };
148
+ const executorLeaseMs = millis(options.executors?.lease ?? "60 seconds");
149
+ if (executorLeaseMs < 3000)
150
+ throw new Error("executors.lease must be at least 3 seconds");
151
+ const cancelCheckMs = Math.min(options.executors?.cancelCheck === undefined
152
+ ? executorLeaseMs / 3
153
+ : millis(options.executors.cancelCheck), executorLeaseMs / 3);
154
+ if (cancelCheckMs < 1000)
155
+ throw new Error("executors.cancelCheck must be at least 1 second");
156
+ const claimLeaseMs = options.relay?.claimLease === undefined ? undefined : millis(options.relay.claimLease);
157
+ const relaySettings = {
158
+ pollMs: millis(options.relay?.poll ?? "1 second"),
159
+ passLimit: Count.make(options.relay?.passLimit ?? 256),
160
+ deliveryConcurrency: Count.make(options.relay?.deliveryConcurrency ?? 16),
161
+ maxBackoffMs: millis(options.relay?.maxBackoff ?? "256 seconds"),
162
+ executorConcurrency: Count.make(options.executors?.concurrency ?? 64),
163
+ executorLeaseMs,
164
+ retryWindowMs,
165
+ cancelCheckMs,
166
+ };
167
+ const defectCapacity = Count.make(options.observability?.defects ?? 1000);
168
+ const sampleEveryMs = millis(options.observability?.sampleEvery ?? "15 seconds");
169
+ const contentGraceMs = Duration.toMillis(Duration.fromInputUnsafe(options.content?.grace ?? "24 hours"));
170
+ const contentSkewMs = Duration.toMillis(Duration.fromInputUnsafe(options.content?.skew ?? "60 seconds"));
171
+ if (!Number.isSafeInteger(contentGraceMs) ||
172
+ contentGraceMs < 0 ||
173
+ !Number.isSafeInteger(contentSkewMs) ||
174
+ contentSkewMs < 0)
175
+ throw new Error("content.grace and content.skew must be finite, non-negative whole milliseconds");
176
+ const subscriptionConcurrency = Count.make(options.relay?.subscriptionConcurrency ?? 16);
177
+ const writerWindowMs = options.payloadWriterWindow === undefined
178
+ ? DEFAULT_WRITER_WINDOW_MS
179
+ : millis(options.payloadWriterWindow);
180
+ if (writerWindowMs < 1000)
181
+ throw new Error("payloadWriterWindow must be at least 1 second");
182
+ const subscriptionBatch = Count.make(options.relay?.subscriptionBatch ?? 16);
183
+ const runtime = Layer.effectContext(Effect.gen(function* () {
184
+ const crypto = yield* Crypto.Crypto;
185
+ const scope = yield* Effect.scope;
186
+ const sharding = yield* Sharding.Sharding;
187
+ yield* sharding.registerEntity(IdleSweep, Effect.succeed(IdleSweep.of({})), {
188
+ maxIdleTime: "5 seconds",
189
+ });
190
+ const registrations = new Map();
191
+ const residency = new Map();
192
+ const refusals = yield* MailboxRefusals;
193
+ refusals.refuse = (address) => {
194
+ const registration = registrations.get(address.entityType);
195
+ if (registration === undefined ||
196
+ residency.get(address.entityType)?.(address.entityId) !== true)
197
+ return undefined;
198
+ return registration.policy.mailboxCapacity === "unbounded"
199
+ ? overloaded("activation")
200
+ : ActorError.make({ reason: MailboxFull.make({}) });
201
+ };
202
+ const diagnostics = new Map();
203
+ const owners = new Map();
204
+ const sweepsWorkflows = new Set();
205
+ const queryRegistrations = new Map();
206
+ const jobRegistrations = new Map();
207
+ const runtimeId = yield* crypto.randomUUIDv4.pipe(Effect.orDie);
208
+ const frameworkClock = yield* FrameworkClock;
209
+ const writerDeclarations = [];
210
+ let refreshedAt;
211
+ const services = yield* Effect.context();
212
+ const defectLog = boundedDefectLog(defectCapacity);
213
+ const database = yield* rowsDatabase;
214
+ const clockOffset = yield* FrameworkClock;
215
+ const content = options.content === undefined
216
+ ? undefined
217
+ : tenantContent({
218
+ grants: yield* grantKeys(options.content.keys, (yield* (yield* SqlClient.SqlClient) `
219
+ SELECT deployment_id FROM actor_deployment`.pipe(Effect.orDie))[0].deployment_id),
220
+ graceMs: contentGraceMs,
221
+ skewMs: contentSkewMs,
222
+ singleConnection: Option.isSome(yield* Effect.serviceOption(PgliteClient.PgliteClient)),
223
+ offset: () => clockOffset.offsetMillis(),
224
+ hooks: yield* ContentHooks,
225
+ });
226
+ const contentBinding = content === undefined
227
+ ? undefined
228
+ : { store: content, skewMs: contentSkewMs, offset: () => clockOffset.offsetMillis() };
229
+ const primary = Context.get(services, SqlClient.SqlClient);
230
+ const replica = yield* ReadReplica;
231
+ let observed;
232
+ const observe = (executed) => Effect.sync(() => {
233
+ const version = executed.version;
234
+ if (version !== undefined &&
235
+ (observed === undefined || BigInt(version) > BigInt(observed)))
236
+ observed = version;
237
+ });
238
+ const gate = turnGate();
239
+ const admission = admissionLimit({
240
+ limit: admissionSettings.concurrency,
241
+ wait: admissionSettings.wait,
242
+ });
243
+ const requests = admissionLimit({ limit: admissionSettings.requests, wait: Duration.zero });
244
+ let holder;
245
+ const transport = yield* holderTransport((message) => Effect.suspend(() => holder.deliver(message)));
246
+ const connectionCall = (effect) => Effect.suspend(() => effect.pipe(Effect.forkIn(scope))).pipe(Effect.flatMap(Fiber.join), Effect.catchCause((cause) => {
247
+ const failure = Cause.findErrorOption(cause);
248
+ if (Option.isSome(failure) && Schema.is(ActorError)(failure.value))
249
+ return Effect.fail(failure.value);
250
+ return Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause: Cause.squash(cause) }) }));
251
+ }));
252
+ const heldTypes = new Map();
253
+ const shardLockMs = Duration.toMillis(Option.match(yield* Effect.serviceOption(ShardingConfig.ShardingConfig), {
254
+ onNone: () => ShardingConfig.defaults.shardLockExpiration,
255
+ onSome: (config) => config.shardLockExpiration,
256
+ }));
257
+ const heldType = (registration) => {
258
+ const entity = connectionEntity(registration.name);
259
+ const client = (ref) => Effect.gen(function* () {
260
+ const make = yield* sharding.makeClient(entity);
261
+ return make(yield* entityId(ref));
262
+ });
263
+ return {
264
+ deliveryMs: registration.policy.deliveryMs,
265
+ takeoverMs: shardLockMs + registration.policy.deliveryMs,
266
+ reauthorizeMs: registration.policy.reauthorizeMs,
267
+ retryWindowMs,
268
+ placement: registration.placement,
269
+ routingKey: (ref) => routingKey({ ref, placement: registration.placement }),
270
+ hasResync: (member) => member === FEED_MEMBER ||
271
+ isWatchMember(member) ||
272
+ (registration.connections.get(member)?.hasResync ?? false),
273
+ hasMember: (member) => member === FEED_MEMBER
274
+ ? registration.feeds.size > 0
275
+ : isWatchMember(member)
276
+ ? registration.watches.has(watchedQuery(member))
277
+ : registration.connections.has(member),
278
+ channel: {
279
+ open: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Open(request))),
280
+ frame: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Frame(request))),
281
+ close: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Close(request))),
282
+ resync: (request) => connectionCall(Effect.flatMap(client(request.ref), (c) => c.Resync(request))),
283
+ },
284
+ };
285
+ };
286
+ /**
287
+ * Whether the request is allowed: the global `authorize` and the
288
+ * actor's `access` both when both exist, either alone when only one
289
+ * does, and with neither, a `System` caller. A registration the runner
290
+ * does not hold has no `access`, so only the global hook or the default
291
+ * applies.
292
+ */
293
+ const permitted = Effect.fnUntraced(function* (request) {
294
+ const access = (registrations.get(request.ref.actor) ?? queryRegistrations.get(request.ref.actor))?.access;
295
+ if (options.authorize === undefined && access === undefined)
296
+ return Schema.is(System)(request.caller);
297
+ if (options.authorize !== undefined && !(yield* options.authorize(request)))
298
+ return false;
299
+ if (access === undefined)
300
+ return true;
301
+ const allowed = access(request);
302
+ return Effect.isEffect(allowed) ? yield* allowed : allowed;
303
+ });
304
+ holder = yield* connectionHolder({
305
+ transport: () => transport,
306
+ actorType: (name) => heldTypes.get(name),
307
+ authorize: permitted,
308
+ });
309
+ const checked = new Set();
310
+ const authorizedAs = (request) => request.command !== INTERRUPT
311
+ ? Effect.succeed(request)
312
+ : decodeTarget(request.payload).pipe(Effect.flatMap(({ executionId }) => decodeExecutionId(executionId)), Effect.map(({ workflow }) => ({ ...request, command: workflow })), Effect.orElseSucceed(() => request));
313
+ const allow = Effect.fnUntraced(function* (request, kind = "command") {
314
+ const { caller, ref, command } = yield* authorizedAs(request);
315
+ if (!(yield* permitted({ caller, ref, command, kind })))
316
+ return yield* ActorError.make({ reason: Unauthorized.make({ code: "access_denied" }) });
317
+ });
318
+ /**
319
+ * Rechecks access and expiry before an external caller gets its outcome.
320
+ * `endedAtMs` is the clock the turn read after its transaction ended;
321
+ * an outcome without one, a defect, reads the clock again. A reply may
322
+ * already have committed, so a full clock-read pool must wait, never
323
+ * report pre-turn refusal.
324
+ */
325
+ const authorize = Effect.fnUntraced(function* (request, endedAtMs) {
326
+ yield* allow(request, "command");
327
+ yield* checkIdentity(request.commandId, retryWindowMs, endedAtMs === undefined
328
+ ? yield* databaseTime.pipe(Effect.retry({
329
+ while: isPoolRefusal,
330
+ schedule: Schedule.spaced("10 millis"),
331
+ }))
332
+ : endedAtMs + frameworkClock.offsetMillis());
333
+ });
334
+ const refreshing = Semaphore.makeUnsafe(1);
335
+ const refreshPayloadWriters = Effect.gen(function* () {
336
+ if (writerDeclarations.length === 0)
337
+ return;
338
+ const sentAt = yield* Clock.currentTimeMillis;
339
+ yield* refreshWriters(runtimeId, writerWindowMs, writerDeclarations);
340
+ refreshedAt = sentAt;
341
+ }).pipe(refreshing.withPermits(1), Effect.provideContext(services), Effect.provideService(FrameworkClock, frameworkClock));
342
+ /**
343
+ * A runtime that could not refresh its writer rows within the window
344
+ * may already count as gone to `durable payloads clear`, so it starts
345
+ * no turn until a refresh succeeds. The check is local.
346
+ */
347
+ const writable = Effect.gen(function* () {
348
+ if (refreshedAt === undefined)
349
+ return;
350
+ if ((yield* Clock.currentTimeMillis) - refreshedAt > writerWindowMs)
351
+ return yield* ActorError.make({
352
+ reason: ActorUnavailable.make({
353
+ cause: new Error("This runtime's payload writer rows are older than its window; turns wait for a refresh"),
354
+ }),
355
+ });
356
+ });
357
+ const entityId = (ref) => encodeEntityId([ref.tenant, ref.id]).pipe(Effect.orDie);
358
+ const databaseNow = databaseTime.pipe(Effect.provideContext(services), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }))));
359
+ const mintCommandId = Effect.gen(function* () {
360
+ const now = yield* databaseNow;
361
+ const uuid = yield* crypto.randomUUIDv4.pipe(Effect.orDie);
362
+ return `v1.${now}.${now + retryWindowMs}.${uuid}`;
363
+ });
364
+ const publicActors = Actors.of({ mintCommandId });
365
+ /**
366
+ * Logs what this runner knows of a delivery's target when the delivery
367
+ * waits out `deliveryTimeout`: the target activation's handlers, worker
368
+ * phase, mailbox and batch, the turn pool's leased and waiting sessions,
369
+ * and any other activation on the runner being rebuilt or restarted, so
370
+ * a stall names its cause from one log line.
371
+ */
372
+ const deliveryTimedOut = (request, address) => Effect.gen(function* () {
373
+ const target = diagnostics.get(request.ref.actor);
374
+ const turns = Option.getOrUndefined(yield* Effect.serviceOption(TurnConnections));
375
+ yield* Effect.logWarning("Delivery timed out").pipe(Effect.annotateLogs({
376
+ actor: request.ref.actor,
377
+ id: request.ref.id,
378
+ tenant: request.ref.tenant,
379
+ command: request.command,
380
+ commandId: request.commandId,
381
+ activation: target?.diagnose(address),
382
+ turnSessions: turns?.sessions(),
383
+ restarting: [...diagnostics].flatMap(([actor, { restarting }]) => restarting()
384
+ .filter((entityId) => actor !== request.ref.actor || entityId !== address)
385
+ .map((entityId) => `${actor}:${entityId}`)),
386
+ }));
387
+ });
388
+ const makeCommandClient = (actor) => sharding.makeClient(commandEntity(actor));
389
+ const commandClients = new Map();
390
+ /** Cluster keeps one client per entity for the runtime's life, so its lookup is done once per actor type. */
391
+ const commandClient = (actor) => {
392
+ const cached = commandClients.get(actor);
393
+ if (cached !== undefined)
394
+ return Effect.succeed(cached);
395
+ return Effect.tap(makeCommandClient(actor), (make) => Effect.sync(() => {
396
+ commandClients.set(actor, make);
397
+ }));
398
+ };
399
+ const dispatch = Effect.fnUntraced(function* (request, external, pending) {
400
+ const registration = registrations.get(request.ref.actor);
401
+ if (registration === undefined)
402
+ return yield* ActorError.make({
403
+ reason: ActorUnavailable.make({ cause: new Error("Actor not registered") }),
404
+ });
405
+ if (external && !gate.open)
406
+ return yield* ActorError.make({
407
+ reason: ActorUnavailable.make({ cause: new Error("Runner is draining") }),
408
+ });
409
+ const address = yield* entityId(request.ref);
410
+ const isResident = () => residency.get(request.ref.actor)?.(address) === true;
411
+ let rejectedAtCapacity = false;
412
+ return yield* Effect.gen(function* () {
413
+ if (external &&
414
+ (request.intent !== undefined ||
415
+ request.delivery !== undefined ||
416
+ request.redelivered !== undefined ||
417
+ request.clockOffset !== undefined ||
418
+ (Schema.is(System)(request.caller) &&
419
+ (request.caller.mint !== undefined || request.caller.source === "subscription"))))
420
+ return yield* ActorError.make({
421
+ reason: Unauthorized.make({ code: "access_denied" }),
422
+ });
423
+ if (external) {
424
+ yield* allow(request, "command");
425
+ yield* checkIdentity(request.commandId, retryWindowMs);
426
+ }
427
+ const client = (yield* commandClient(request.ref.actor))(address);
428
+ yield* (yield* TurnHooks).at("beforeDelivery", request);
429
+ let admitted = false;
430
+ const deliver = Clock.currentTimeMillis.pipe(Effect.flatMap((queuedAtMs) => client
431
+ .Execute(!external
432
+ ? { ...request, queuedAtMs }
433
+ : !admitted
434
+ ? {
435
+ ...request,
436
+ external,
437
+ clockOffset: frameworkClock.offsetMillis(),
438
+ queuedAtMs,
439
+ }
440
+ : {
441
+ ...request,
442
+ external,
443
+ redelivered: true,
444
+ clockOffset: frameworkClock.offsetMillis(),
445
+ queuedAtMs,
446
+ })
447
+ .pipe(Effect.interruptible, Effect.forkIn(scope), Effect.tap((fiber) => Effect.sync(() => {
448
+ pending?.add(fiber);
449
+ })), Effect.uninterruptible)), Effect.flatMap(Fiber.join), Effect.catchCause((cause) => {
450
+ const failure = Cause.findErrorOption(cause);
451
+ if (Option.isSome(failure) && Schema.is(DeliveryFailed)(failure.value)) {
452
+ admitted ||= failure.value.admitted;
453
+ return Effect.fail(failure.value.error);
454
+ }
455
+ if (Option.isSome(failure) && Schema.is(ActorError)(failure.value))
456
+ return Effect.fail(failure.value);
457
+ if (Option.isSome(failure) && Schema.is(ClusterError.MailboxFull)(failure.value)) {
458
+ if (isResident())
459
+ return Effect.fail(registration.policy.mailboxCapacity === "unbounded"
460
+ ? overloaded("activation")
461
+ : ActorError.make({ reason: MailboxFull.make({}) }));
462
+ rejectedAtCapacity = true;
463
+ return Effect.fail(ActorError.make({ reason: RunnerAtCapacity.make({}) }));
464
+ }
465
+ return Effect.fail(ActorError.make({
466
+ reason: ActorUnavailable.make({ cause: Cause.squash(cause) }),
467
+ }));
468
+ }));
469
+ const retrying = (attempt) => deliver.pipe(Effect.catchIf((error) => (Schema.is(ActorUnavailable)(error.reason) && !isOverloaded(error)) ||
470
+ Schema.is(RunnerAtCapacity)(error.reason), (error) => Effect.sleep(retryDelay(attempt)(error)).pipe(Effect.andThen(Effect.suspend(() => retrying(attempt + 1))))));
471
+ const executed = yield* retrying(0);
472
+ if (external)
473
+ yield* authorize(request, executed.endedAtMs);
474
+ return executed;
475
+ }).pipe(Effect.timeoutOrElse({
476
+ duration: registration.policy.deliveryMs,
477
+ orElse: () => rejectedAtCapacity && !isResident()
478
+ ? Effect.fail(ActorError.make({ reason: RunnerAtCapacity.make({}) }))
479
+ : deliveryTimedOut(request, address).pipe(Effect.andThen(Effect.fail(ActorError.make({
480
+ reason: Timeout.make({ commandId: request.commandId }),
481
+ })))),
482
+ }));
483
+ }, Effect.provideContext(services), Effect.catchIf(SqlError.isSqlError, (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }))), (effect, ...[request, external]) => effect.pipe(Effect.withSpan(SpanNames.admission, { attributes: { ...requestAttributes(request), "admission.external": external } }, { captureStackTrace: false })));
484
+ const leaseForTurns = () => {
485
+ let longest = 0;
486
+ for (const { policy } of registrations.values())
487
+ longest = Math.max(longest, policy.executionMs + policy.lockWaitMs);
488
+ return longest === 0 ? DEFAULT_CLAIM_LEASE_MS : longest + CLAIM_MARGIN_MS;
489
+ };
490
+ const progressTap = yield* ProgressTap;
491
+ const utf8Decoder = new TextDecoder();
492
+ const ownerOf = (ref) => Effect.gen(function* () {
493
+ const make = yield* sharding.makeClient(connectionEntity(ref.actor));
494
+ return make(yield* entityId(ref));
495
+ });
496
+ const fireAndForget = (send) => send.pipe(Effect.timeout(PROGRESS_SEND_TIMEOUT), Effect.ignoreCause, Effect.forkIn(scope));
497
+ const inflight = new Map();
498
+ const deliverProgress = (message) => Effect.flatMap(ownerOf(message.ref), (client) => client.Progress({ ...message, frame: utf8Decoder.decode(message.frame) }, { discard: true }));
499
+ const progressSink = ProgressSink.of({
500
+ wants: (actor, job) => jobRegistrations.get(actor)?.progress.has(job) === true,
501
+ send: (message) => Effect.flatMap(progressTap.send(message), (deliver) => deliver
502
+ ? fireAndForget(deliverProgress(message)).pipe(Effect.flatMap((fiber) => Effect.sync(() => {
503
+ inflight.set(message.jobId, fiber);
504
+ fiber.addObserver(() => {
505
+ if (inflight.get(message.jobId) === fiber)
506
+ inflight.delete(message.jobId);
507
+ });
508
+ })))
509
+ : Effect.void),
510
+ closed: (message) => Effect.flatMap(progressTap.closed(message), (deliver) => deliver
511
+ ? fireAndForget(Effect.suspend(() => {
512
+ const last = inflight.get(message.jobId);
513
+ return last === undefined ? Effect.void : Fiber.await(last);
514
+ }).pipe(Effect.andThen(ownerOf(message.ref)), Effect.flatMap((client) => client.ProgressClosed(message, { discard: true })))).pipe(Effect.asVoid)
515
+ : Effect.void),
516
+ });
517
+ const localSubscriptions = () => [...registrations.values()].flatMap((registration) => registration.subscriptions.map((subscription) => ({
518
+ subscriberType: registration.name,
519
+ subscription,
520
+ })));
521
+ const placements = new Map();
522
+ const placementOf = (actorType) => Effect.gen(function* () {
523
+ const known = registrations.get(actorType)?.placement ??
524
+ queryRegistrations.get(actorType)?.placement ??
525
+ placements.get(actorType);
526
+ if (known !== undefined)
527
+ return known;
528
+ const recorded = yield* recordedPlacement(actorType);
529
+ if (recorded !== undefined)
530
+ placements.set(actorType, recorded);
531
+ return recorded;
532
+ }).pipe(Effect.provideContext(services), Effect.orDie);
533
+ const relayDeliver = (request) => Effect.map(dispatch(request, false), (executed) => executed.outcome);
534
+ const subscriptions = yield* subscriptionRelay({
535
+ deliver: relayDeliver,
536
+ local: localSubscriptions,
537
+ placementOf,
538
+ wake: Effect.suspend(() => relay.wake),
539
+ settings: {
540
+ concurrency: subscriptionConcurrency,
541
+ batch: subscriptionBatch,
542
+ claimLeaseMs: () => claimLeaseMs ?? leaseForTurns(),
543
+ maxBackoffMs: relaySettings.maxBackoffMs,
544
+ retryWindowMs,
545
+ },
546
+ });
547
+ const relay = yield* outboxRelay(relayDeliver, () => [...jobRegistrations.values()].flatMap((registration) => [...registration.jobs].map(([job, registered]) => ({
548
+ actor: registration.name,
549
+ job,
550
+ registered: {
551
+ ...registered,
552
+ execute: (payload, version, context) => registered
553
+ .execute(payload, version, context)
554
+ .pipe(withoutDatabase(registration.services)),
555
+ },
556
+ }))), { ...relaySettings, claimLeaseMs: () => claimLeaseMs ?? leaseForTurns() }, {
557
+ concurrency: subscriptionConcurrency,
558
+ claim: subscriptions.claim,
559
+ decode: subscriptions.decode,
560
+ run: (work, handoff) => subscriptions.run(work, handoff).pipe(Effect.provideContext(services)),
561
+ }, () => new Map(Array.from(registrations.values(), ({ name, cron, policy }) => [
562
+ name,
563
+ { entries: cron, skipMs: policy.cronSkipMs },
564
+ ]))).pipe(Effect.provideService(ProgressSink, progressSink));
565
+ yield* relay.run.pipe(Effect.forkIn(scope));
566
+ let fleetSubscribe;
567
+ if (options.fleet !== undefined && options.fleet.length > 0) {
568
+ if (Option.isSome(yield* Effect.serviceOption(PgliteClient.PgliteClient)))
569
+ return yield* Effect.die(new Error("Fleet.view needs Postgres with wal_level=logical; PGlite has no logical replication"));
570
+ const views = yield* checkFleet(options.fleet, options.rowLevelSecurity?.role).pipe(Effect.provideContext(services), Effect.orDie);
571
+ yield* maintain(views).pipe(Effect.provideContext(services), Effect.forkIn(scope));
572
+ fleetSubscribe = yield* fleetSubscriptions({
573
+ views,
574
+ role: options.rowLevelSecurity?.role,
575
+ permitted,
576
+ reauthorizeMs: (actorType) => registrations.get(actorType)?.policy.reauthorizeMs ?? DEFAULT_REAUTHORIZE_MS,
577
+ }).pipe(Effect.provideContext(services));
578
+ }
579
+ const { cleanup, sweeping, sample } = yield* startSweeps({
580
+ registrations,
581
+ sweepsWorkflows,
582
+ retryWindowMs,
583
+ subscriptions,
584
+ content,
585
+ services,
586
+ frameworkClock,
587
+ refreshPayloadWriters,
588
+ writerWindowMs,
589
+ runtimeId,
590
+ sampleEveryMs,
591
+ sharding,
592
+ scope,
593
+ });
594
+ const routed = (sourceType) => localSubscriptions().flatMap(({ subscriberType, subscription }) => subscription.routed !== undefined && subscription.sourceType === sourceType
595
+ ? [{ ...subscription, subscriberType }]
596
+ : []);
597
+ const outbox = { retryWindowMs, wake: relay.wake, cancelled: relay.cancelled, routed };
598
+ const tenantScope = yield* TenantScope;
599
+ const operators = operatorRuntime({
600
+ services,
601
+ clock: frameworkClock,
602
+ outbox,
603
+ jobOf: (actorType, job) => jobRegistrations.get(actorType)?.jobs.get(job),
604
+ wake: relay.wake,
605
+ tenantScope,
606
+ });
607
+ const seeding = seedRuntime({
608
+ services,
609
+ clock: frameworkClock,
610
+ outbox,
611
+ jobOf: (actorType, job) => jobRegistrations.get(actorType)?.jobs.get(job),
612
+ createdBy: (actorType) => registrations.get(actorType)?.policy.createdBy !== undefined,
613
+ wake: relay.wake,
614
+ tenantScope,
615
+ });
616
+ const internalActors = InternalActors.of({
617
+ fleet: (request) => fleetSubscribe === undefined
618
+ ? ActorError.make({ reason: InvalidInput.make({ code: "unknown_route" }) })
619
+ : fleetSubscribe(request),
620
+ fleetViews: new Set((options.fleet ?? []).map(({ name }) => name)),
621
+ seed: seeding,
622
+ mintActorId: crypto.randomUUIDv7.pipe(Effect.orDie),
623
+ mintChildId: (input) => deriveMintId(input).pipe(Effect.provideService(Crypto.Crypto, crypto)),
624
+ retryWindowMs,
625
+ databaseNow,
626
+ mintCommandId,
627
+ tables: (scope, write) => bindTables(database, scope, write, checked).pipe(Effect.provideService(SqlClient.SqlClient, primary), Effect.provideService(TenantScope, tenantScope)),
628
+ blobs: (scope, write) => bindBlobs(scope, write, contentBinding).pipe(Effect.provideService(SqlClient.SqlClient, primary), Effect.provideService(TenantScope, tenantScope)),
629
+ sweepContent: content === undefined
630
+ ? Effect.succeed(0)
631
+ : content.sweep(true).pipe(Effect.provideContext(services), Effect.orDie),
632
+ registered: (actor) => ({
633
+ commands: registrations.has(actor),
634
+ queries: queryRegistrations.has(actor),
635
+ }),
636
+ declaredBlobs: (actor) => (registrations.get(actor) ?? queryRegistrations.get(actor))?.blobs.map((blob) => blob.name) ?? [],
637
+ ...actorRegistration({
638
+ registrations,
639
+ queryRegistrations,
640
+ jobRegistrations,
641
+ residency,
642
+ diagnostics,
643
+ owners,
644
+ heldTypes,
645
+ heldType,
646
+ sweepsWorkflows,
647
+ checked,
648
+ services,
649
+ frameworkClock,
650
+ content,
651
+ retryWindowMs,
652
+ tableRole: options.rowLevelSecurity?.role,
653
+ adoptionRole: options.adoption?.role,
654
+ enforcedTypes,
655
+ writerDeclarations,
656
+ refreshPayloadWriters,
657
+ subscriptions,
658
+ transport,
659
+ authorize: permitted,
660
+ gate,
661
+ writable,
662
+ defectLog,
663
+ outbox,
664
+ }),
665
+ ...committedReads({
666
+ registrations,
667
+ queryRegistrations,
668
+ services,
669
+ allow,
670
+ primary,
671
+ replica,
672
+ holder,
673
+ }),
674
+ ...eventFeeds({
675
+ registrations,
676
+ services,
677
+ allow,
678
+ sharding,
679
+ entityId,
680
+ frameworkClock,
681
+ transport,
682
+ }),
683
+ deliverProgress: (message) => deliverProgress(message).pipe(Effect.ignoreCause, Effect.provideContext(services)),
684
+ transport,
685
+ holder,
686
+ hibernate: (ref) => Effect.flatMap(entityId(ref), (id) => owners.get(ref.actor)?.hibernate(id) ?? Effect.void).pipe(Effect.provideContext(services)),
687
+ execute: (request) => Effect.gen(function* () {
688
+ const reply = yield* Deferred.make();
689
+ const pending = new Set();
690
+ yield* admission
691
+ .admit(dispatch(request, true, pending).pipe(Effect.tap(observe), Effect.onExit((exit) => [...pending].some((fiber) => fiber.pollUnsafe() === undefined)
692
+ ? Deferred.done(reply, exit)
693
+ : Effect.void), Effect.ensuring(Effect.suspend(() => Effect.forEach(pending, Fiber.await, { discard: true })))))
694
+ .pipe(Effect.onExit((exit) => Deferred.done(reply, exit)), Effect.ignoreCause, Effect.forkIn(scope));
695
+ return yield* Deferred.await(reply);
696
+ }),
697
+ overloaded: admission.full,
698
+ admitRequest: requests.admit,
699
+ deliver: (request) => dispatch(request, false).pipe(Effect.tap(observe), Effect.map((executed) => executed.outcome)),
700
+ observedVersion: () => observed,
701
+ drainOutbox: relay.drain,
702
+ cleanup: cleanup.pipe(Effect.orDie),
703
+ extendOutboxLeases: relay.extendLeases,
704
+ shardId: (ref) => entityId(ref).pipe(Effect.flatMap((id) => commandEntity(ref.actor).getShardId(EntityId.make(id))), Effect.map(String), Effect.provideService(Sharding.Sharding, sharding)),
705
+ });
706
+ const { serving } = yield* servingReadiness({
707
+ sharding,
708
+ services,
709
+ registrations,
710
+ queryRegistrations,
711
+ jobRegistrations,
712
+ });
713
+ const control = runtimeControl({
714
+ gate,
715
+ stopClaims: relay.stop,
716
+ attemptsIdle: relay.attemptsIdle,
717
+ interruptAttempts: relay.interruptAttempts,
718
+ stopBackground: sweeping === undefined ? Effect.void : Fiber.interrupt(sweeping),
719
+ serving,
720
+ scope,
721
+ });
722
+ const toUnavailable = (cause) => Effect.fail(ActorError.make({ reason: ActorUnavailable.make({ cause }) }));
723
+ const configured = Effect.suspend(() => content === undefined
724
+ ? Effect.die(new Error("Content needs the runtime's content.keys"))
725
+ : Effect.succeed(content));
726
+ const contentEntry = Effect.fnUntraced(function* (ref, caller, blob, name, operation) {
727
+ const registration = registrations.get(ref.actor) ?? queryRegistrations.get(ref.actor);
728
+ if (registration === undefined)
729
+ return yield* ActorError.make({
730
+ reason: ActorUnavailable.make({ cause: new Error("Actor not registered") }),
731
+ });
732
+ if (!(yield* permitted({
733
+ caller,
734
+ ref,
735
+ command: `${blob}.${operation}`,
736
+ kind: "content",
737
+ })))
738
+ return yield* ActorError.make({ reason: Unauthorized.make({ code: "access_denied" }) });
739
+ if (!registration.blobs.some((declared) => declared.name === blob && isContent(declared)))
740
+ return Option.none();
741
+ const sql = yield* SqlClient.SqlClient;
742
+ const [found] = yield* sql `
743
+ SELECT hash, size::float8 AS size FROM actor_content_refs
744
+ WHERE routing_key = ${routingKey({ ref, placement: registration.placement })}
745
+ AND tenant_id = ${ref.tenant} AND actor_type = ${ref.actor} AND actor_id = ${ref.id}
746
+ AND blob = ${blob} AND name = ${name}`;
747
+ const timeoutMs = "policy" in registration ? registration.policy.executionMs : registration.timeoutMs;
748
+ return Option.map(Option.fromUndefinedOr(found), (row) => ({ ...row, timeoutMs }));
749
+ }, Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable));
750
+ const contentStore = ContentStore.of({
751
+ uploadBytes: (tenant, bytes) => Effect.flatMap(configured, (store) => store.uploadBytes(tenant, bytes)).pipe(Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable)),
752
+ upload: (tenant, body, limit) => Effect.flatMap(configured, (store) => store.uploadStream(tenant, body, Math.min(limit, MAX_CONTENT_BYTES))).pipe(Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable)),
753
+ grant: (ref, caller, blob, name) => Effect.gen(function* () {
754
+ const store = yield* configured;
755
+ const found = yield* contentEntry(ref, caller, blob, name, "grant");
756
+ if (Option.isNone(found))
757
+ return Option.none();
758
+ return yield* store
759
+ .grant(ref.tenant, found.value.hash, found.value.size)
760
+ .pipe(Effect.provideContext(services), Effect.catchTag("SqlError", toUnavailable));
761
+ }),
762
+ download: (ref, caller, blob, name) => Effect.gen(function* () {
763
+ const store = yield* configured;
764
+ const found = yield* contentEntry(ref, caller, blob, name, "get");
765
+ return Option.map(found, ({ hash, size, timeoutMs }) => ({
766
+ size,
767
+ bytes: store.stream(ref.tenant, hash, size, timeoutMs).pipe(Stream.provideContext(services), Stream.mapError((cause) => ActorError.make({ reason: ActorUnavailable.make({ cause }) }))),
768
+ }));
769
+ }),
770
+ });
771
+ return Context.make(Actors, publicActors).pipe(Context.add(ContentStore, contentStore), Context.add(InternalActors, internalActors), Context.add(RuntimeControl, control), Context.add(DefectLog, defectLog), Context.add(TelemetrySampler, TelemetrySampler.of({ sample })), Context.add(OperatorRuntime, operators));
772
+ }));
773
+ return Layer.unwrap(Effect.gen(function* () {
774
+ const sql = yield* SqlClient.SqlClient;
775
+ const coordination = (yield* Coordination) ?? sql;
776
+ const wiring = Option.getOrUndefined(yield* Effect.serviceOption(RunnerWiring));
777
+ yield* migrate;
778
+ if (options.rowLevelSecurity !== undefined &&
779
+ options.adoption !== undefined &&
780
+ options.rowLevelSecurity.role !== options.adoption.role)
781
+ return yield* Effect.die(new Error(`rowLevelSecurity.role ${options.rowLevelSecurity.role} and adoption.role ${options.adoption.role} must name the same role: a turn takes one role`));
782
+ if (options.rowLevelSecurity !== undefined)
783
+ yield* checkRowLevelSecurity(options.rowLevelSecurity.role);
784
+ yield* sql `INSERT INTO actor_deployment (protocol, retry_window_ms) VALUES (1, ${retryWindowMs}) ON CONFLICT DO NOTHING`;
785
+ const rows = yield* sql `SELECT protocol, retry_window_ms::text AS retry_window_ms FROM actor_deployment`;
786
+ if (rows[0].protocol !== 1 || Number(rows[0].retry_window_ms) !== retryWindowMs) {
787
+ return yield* Effect.die(new Error("Actor command protocol/retry window differs from the deployment; migrate explicitly"));
788
+ }
789
+ const runnerStorage = Option.isSome(yield* Effect.serviceOption(PgliteClient.PgliteClient))
790
+ ? "memory"
791
+ : "sql";
792
+ if (wiring?.production === true && runnerStorage === "memory")
793
+ return yield* Effect.die(new Error("Runner.socket requires Postgres; PGlite cannot share ownership between processes"));
794
+ yield* checkRunnerConfiguration(wiring);
795
+ const sharding = (wiring?.sharding ?? Sharding.layer.pipe(Layer.provide(Runners.layerNoop))).pipe(Layer.merge(Layer.effect(RunnerReadiness, wiring?.production === true
796
+ ? acquiredShards
797
+ : Effect.succeed({ acquired: () => Effect.succeed(true) }))), Layer.provideMerge(directMessages), Layer.provideMerge(mailboxRefusals), Layer.provide([
798
+ runnerStorage === "memory"
799
+ ? Layer.effect(RunnerStorage.RunnerStorage, Effect.map(RunnerStorage.makeMemory, keepAcquiredShards))
800
+ : Layer.effect(RunnerStorage.RunnerStorage, coordinatedRunnerStorage.pipe(Effect.map(wiring?.storage ?? ((storage) => storage)), Effect.map(keepAcquiredShards))).pipe(Layer.orDie),
801
+ RunnerHealth.layerNoop,
802
+ ]), Layer.provideMerge(ShardingConfig.layer({
803
+ shardsPerGroup: 1,
804
+ simulateRemoteSerialization: yield* LocalRequestSerialization,
805
+ maxResidentEntities: maxResidentActors,
806
+ ...wiring?.config,
807
+ ...holderShardGroups(wiring?.config ?? {}),
808
+ })));
809
+ const config = wiring?.config;
810
+ const address = config?.runnerAddress;
811
+ const lease = runnerStorage === "sql" &&
812
+ config?.shardLockDisableAdvisory === true &&
813
+ address !== undefined &&
814
+ Option.isSome(address)
815
+ ? Layer.succeed(ShardLease, tableShardLease({
816
+ sql: coordination,
817
+ address: address.value,
818
+ expiration: Duration.fromInputUnsafe(config.shardLockExpiration ?? ShardingConfig.defaults.shardLockExpiration),
819
+ }))
820
+ : Layer.empty;
821
+ return runtime.pipe(Layer.provide(sharding), Layer.provide(lease), Layer.provide(Layer.succeed(TenantScope, {
822
+ role: options.rowLevelSecurity?.role,
823
+ adoption: options.adoption === undefined
824
+ ? undefined
825
+ : { role: options.adoption.role, enforced: enforcedTypes },
826
+ })));
827
+ }));
828
+ };
829
+ /** Database layers for `Actors.layer`: `postgres` for real deployments, `pglite` for embedded and test use. */
830
+ export const Database = {
831
+ /**
832
+ * A runner holds three primary pools, plus optional replica and coordination
833
+ * pools. Turns lease sessions from the turn pool, `maxConnections` (default
834
+ * 50): a command holds one session until its transaction ends, so a pool
835
+ * smaller than the commands in flight queues callers behind
836
+ * it. Queries read from the query pool, `queryConnections` (default 10),
837
+ * except those of types with owned tables or blobs. Command admission,
838
+ * receipt replays, the relay, migrations, and cluster storage use the
839
+ * off-turn pool, `offTurnConnections` (default 10), unless `coordination`
840
+ * moves Cluster storage and deployment locks to an independent unsharded
841
+ * primary. All runners must designate the same authority. Every pool opens
842
+ * connections only as load needs them, refuses checkouts past its
843
+ * connections plus a bounded waiter allowance, and hands its connections out
844
+ * first come, first served. Keep the sum across runners below the server's
845
+ * `max_connections`.
846
+ *
847
+ * `replica` is this runner's nearest streaming replica of the same primary.
848
+ * Queries read there once it has replayed the commit version their caller
849
+ * last saw, and read the primary when it is behind or fails. Its pool
850
+ * (`maxConnections` default 10) opens connections only as queries need them.
851
+ * Every pool requests server TCP keepalives at 5 seconds idle, 2 seconds
852
+ * between probes, and 3 probes. `startupParameters` overrides these defaults
853
+ * independently on the primary and replica configurations.
854
+ *
855
+ * Registers a `regclass` codec because the pinned driver lacks one and the
856
+ * migrator needs it on restart; remove once Effect #8309 lands.
857
+ */
858
+ postgres: (options) => {
859
+ const types = PgTypes.makeRegistry();
860
+ types.register(2205, {
861
+ encode: (value) => PgTypes.encode(value, PgTypes.OID.oid),
862
+ decode: (bytes) => bytes.length === 4
863
+ ? Result.succeed(new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0))
864
+ : Result.fail(new PgTypes.CodecError({ message: "Invalid regclass value" })),
865
+ });
866
+ const { offTurnConnections, queryConnections, replica, neki, coordination, ...configured } = options;
867
+ const pool = withKeepalives(configured);
868
+ const database = Layer.mergeAll(boundedLayer({ ...pool, maxConnections: offTurnConnections ?? 10, types }), neki === true
869
+ ? turnConnections({ ...pool, maxConnections: pool.maxConnections ?? 50, types })
870
+ : turnGroups.pipe(Layer.provideMerge(turnConnections({ ...pool, maxConnections: pool.maxConnections ?? 50, types }))), queryPoolLayer({ ...pool, maxConnections: queryConnections ?? 10, types }), replicaLayer(replica === undefined ? undefined : { ...withKeepalives(replica), types }), coordinationLayer(coordination === undefined ? undefined : { ...withKeepalives(coordination), types }));
871
+ return neki === undefined
872
+ ? database
873
+ : database.pipe(Layer.provideMerge(Layer.succeed(NekiTurnSessions, neki)));
874
+ },
875
+ pglite,
876
+ };