@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,31 @@
1
+ import { Context, Effect } from "effect";
2
+ import { Migrator, SqlClient } from "effect/sql";
3
+ import type { SqlConnection, SqlError } from "effect/sql";
4
+ import type { Scope } from "effect";
5
+ import { ShardingConfig } from "effect/cluster";
6
+ /** Holds startup coordination before even the history table is created, on one leased session. */
7
+ export declare const withMigrationCoordination: <A, E>(effect: Effect.Effect<A, E, SqlClient.SqlClient | Scope.Scope>) => Effect.Effect<A, E | SqlError.SqlError, SqlClient.SqlClient>;
8
+ /** Propagation must finish before a later statement uses the changed schema. */
9
+ export declare const MigrationBarrier: Context.Reference<(connection: SqlConnection.Connection) => Effect.Effect<unknown, SqlError.SqlError>>;
10
+ /** A reserved session owns coordination across autocommit DDL and progress writes. */
11
+ export declare const MigrationCoordination: Context.Reference<(connection: SqlConnection.Connection) => Effect.Effect<unknown, SqlError.SqlError, Scope.Scope>>;
12
+ /** Failure injection runs after a durable boundary, never in place of the database operation. */
13
+ export declare const MigrationBoundary: Context.Reference<(point: string) => Effect.Effect<void>>;
14
+ /** A preflight is already satisfied when this migration has started changing its schema. */
15
+ export declare const MigrationResuming: Context.Reference<boolean>;
16
+ /**
17
+ * Cluster creates its tables outside migration history. Creating its default schema
18
+ * under startup coordination first prevents concurrent CREATE races without lending
19
+ * Cluster a migration-scoped SQL client or consuming a third off-turn connection.
20
+ */
21
+ export declare const prepareRunnerStorage: Effect.Effect<void, SqlError.SqlError, ShardingConfig.ShardingConfig | SqlClient.SqlClient>;
22
+ /**
23
+ * DDL and its propagation run without BEGIN. A durable statement journal closes the
24
+ * crash gap between applying DDL and recording it; replay touches only an unfinished
25
+ * step, so a later drop/recreate cannot make an earlier create run again. Existing
26
+ * data rewrites set fixed values and are replayable, never increments or external work.
27
+ */
28
+ export declare const nekiMigrator: ({ record, refuseSkipped, }: {
29
+ readonly record: Record<string, Effect.Effect<void, never, SqlClient.SqlClient>>;
30
+ readonly refuseSkipped: Effect.Effect<void, Migrator.MigrationError | SqlError.SqlError, SqlClient.SqlClient>;
31
+ }) => Effect.Effect<(readonly [number, string])[], Migrator.MigrationError | SqlError.SqlError, SqlClient.SqlClient>;
@@ -0,0 +1,276 @@
1
+ import { PgClient } from "@effect/sql-pg";
2
+ import { Context, Effect } from "effect";
3
+ import { Migrator, SqlClient } from "effect/sql";
4
+ import { Reactivity } from "effect/reactivity";
5
+ import { ShardingConfig } from "effect/cluster";
6
+ import { NekiTurnSessions } from "./session.js";
7
+ /** Holds startup coordination before even the history table is created, on one leased session. */
8
+ export const withMigrationCoordination = (effect) => Effect.scoped(Effect.gen(function* () {
9
+ const source = yield* SqlClient.SqlClient;
10
+ const connection = yield* source.reserve;
11
+ yield* (yield* MigrationCoordination)(connection);
12
+ const reactivity = yield* Reactivity.make;
13
+ const client = yield* SqlClient.make({
14
+ acquirer: Effect.succeed(connection),
15
+ compiler: PgClient.makeCompiler(),
16
+ spanAttributes: [],
17
+ }).pipe(Effect.provideService(Reactivity.Reactivity, reactivity));
18
+ return yield* Effect.provideService(effect, SqlClient.SqlClient, client);
19
+ }));
20
+ /** Propagation must finish before a later statement uses the changed schema. */
21
+ export const MigrationBarrier = Context.Reference("akter/MigrationBarrier", {
22
+ defaultValue: () => (connection) => connection.execute("SELECT __neki.wait_for_ddl()", [], undefined),
23
+ });
24
+ /** A reserved session owns coordination across autocommit DDL and progress writes. */
25
+ export const MigrationCoordination = Context.Reference("akter/MigrationCoordination", {
26
+ defaultValue: () => (connection) => Effect.acquireRelease(connection.execute("SELECT pg_advisory_lock(1935764837, 487)", [], undefined), () => connection
27
+ .execute("SELECT pg_advisory_unlock(1935764837, 487)", [], undefined)
28
+ .pipe(Effect.orDie)),
29
+ });
30
+ /** Failure injection runs after a durable boundary, never in place of the database operation. */
31
+ export const MigrationBoundary = Context.Reference("akter/MigrationBoundary", { defaultValue: () => () => Effect.void });
32
+ /** A preflight is already satisfied when this migration has started changing its schema. */
33
+ export const MigrationResuming = Context.Reference("akter/MigrationResuming", {
34
+ defaultValue: () => false,
35
+ });
36
+ /**
37
+ * Cluster creates its tables outside migration history. Creating its default schema
38
+ * under startup coordination first prevents concurrent CREATE races without lending
39
+ * Cluster a migration-scoped SQL client or consuming a third off-turn connection.
40
+ */
41
+ export const prepareRunnerStorage = Effect.gen(function* () {
42
+ const config = yield* ShardingConfig.ShardingConfig;
43
+ const neki = yield* NekiTurnSessions;
44
+ return yield* withMigrationCoordination(Effect.gen(function* () {
45
+ const sql = yield* SqlClient.SqlClient;
46
+ const connection = yield* sql.reserve;
47
+ const boundary = yield* MigrationBoundary;
48
+ const barrier = yield* MigrationBarrier;
49
+ if (neki)
50
+ yield* barrier(connection);
51
+ yield* sql `CREATE TABLE IF NOT EXISTS cluster_runners (
52
+ machine_id SERIAL PRIMARY KEY,
53
+ address VARCHAR(255) NOT NULL,
54
+ runner TEXT NOT NULL,
55
+ healthy BOOLEAN NOT NULL DEFAULT TRUE,
56
+ last_heartbeat TIMESTAMP NOT NULL DEFAULT NOW(),
57
+ UNIQUE(address)
58
+ )`;
59
+ yield* boundary("cluster:runners:ddl");
60
+ if (neki)
61
+ yield* barrier(connection);
62
+ yield* boundary("cluster:runners:propagated");
63
+ if (config.shardLockDisableAdvisory) {
64
+ yield* sql `CREATE TABLE IF NOT EXISTS cluster_locks (
65
+ shard_id VARCHAR(50) PRIMARY KEY,
66
+ address VARCHAR(255) NOT NULL,
67
+ acquired_at TIMESTAMP NOT NULL
68
+ )`;
69
+ yield* boundary("cluster:locks:ddl");
70
+ if (neki)
71
+ yield* barrier(connection);
72
+ yield* boundary("cluster:locks:propagated");
73
+ }
74
+ }));
75
+ });
76
+ /** ALTER actions split only at commas outside quoted identifiers, literals and expressions. */
77
+ const alterActions = (text) => {
78
+ const actions = [];
79
+ let start = 0;
80
+ let depth = 0;
81
+ let quote = "";
82
+ for (let i = 0; i < text.length; i++) {
83
+ const character = text[i];
84
+ if (quote !== "") {
85
+ if (character === quote) {
86
+ if (text[i + 1] === quote)
87
+ i++;
88
+ else
89
+ quote = "";
90
+ }
91
+ }
92
+ else if (character === "'" || character === '"')
93
+ quote = character;
94
+ else if (character === "(")
95
+ depth++;
96
+ else if (character === ")")
97
+ depth--;
98
+ else if (character === "," && depth === 0) {
99
+ actions.push(text.slice(start, i).trim());
100
+ start = i + 1;
101
+ }
102
+ }
103
+ actions.push(text.slice(start).trim());
104
+ return actions;
105
+ };
106
+ const identifier = '(?:"(?:[^"]|"")+"|[a-z_][a-z_0-9]*)(?:\\.(?:"(?:[^"]|"")+"|[a-z_][a-z_0-9]*))?';
107
+ const alter = new RegExp(`^ALTER TABLE (${identifier})\\s+([\\s\\S]+)$`, "i");
108
+ const unquote = (name) => name.replace(/^"|"$/g, "").replaceAll('""', '"');
109
+ /**
110
+ * Resumption rewrites only the framework's audited DDL forms; an unknown form fails closed.
111
+ * A statement that already carries its own existence guard is replayed unchanged.
112
+ */
113
+ const replayDdl = (sql, text) => Effect.gen(function* () {
114
+ if (/^CREATE (?:UNIQUE )?(?:TABLE|INDEX|SCHEMA) /i.test(text))
115
+ return text.replace(/^(CREATE (?:UNIQUE )?(?:TABLE|INDEX|SCHEMA)) (?!IF NOT EXISTS )/i, "$1 IF NOT EXISTS ");
116
+ if (/^DROP (?:TABLE|INDEX|VIEW) /i.test(text))
117
+ return text.replace(/^(DROP (?:TABLE|INDEX|VIEW)) (?!IF EXISTS )/i, "$1 IF EXISTS ");
118
+ if (/^CREATE (?:OR REPLACE )?(?:VIEW|FUNCTION) /i.test(text))
119
+ return text.replace(/^CREATE (?:OR REPLACE )?/i, "CREATE OR REPLACE ");
120
+ const policy = new RegExp(`^CREATE POLICY (${identifier}) ON (${identifier})`, "i").exec(text);
121
+ if (policy !== null) {
122
+ const [row] = yield* sql `SELECT EXISTS (
123
+ SELECT 1 FROM pg_policy WHERE polrelid = to_regclass(${policy[2]})
124
+ AND polname = ${unquote(policy[1])}) AS exists`;
125
+ return row?.exists === true ? undefined : text;
126
+ }
127
+ const match = alter.exec(text);
128
+ if (match !== null) {
129
+ const table = match[1];
130
+ const action = match[2];
131
+ if (/^ADD COLUMN /i.test(action))
132
+ return `ALTER TABLE ${table} ${action.replace(/^ADD COLUMN (?!IF NOT EXISTS )/i, "ADD COLUMN IF NOT EXISTS ")}`;
133
+ if (/^DROP CONSTRAINT /i.test(action))
134
+ return `ALTER TABLE ${table} ${action.replace(/^DROP CONSTRAINT (?!IF EXISTS )/i, "DROP CONSTRAINT IF EXISTS ")}`;
135
+ if (/^ENABLE ROW LEVEL SECURITY$/i.test(action))
136
+ return text;
137
+ const constraint = new RegExp(`^ADD CONSTRAINT (${identifier})\\s+`, "i").exec(action);
138
+ if (constraint !== null) {
139
+ const [row] = yield* sql `SELECT EXISTS (
140
+ SELECT 1 FROM pg_constraint WHERE conrelid = to_regclass(${table})
141
+ AND conname = ${unquote(constraint[1])}) AS exists`;
142
+ return row?.exists === true ? undefined : text;
143
+ }
144
+ const rename = new RegExp(`^RENAME COLUMN (${identifier}) TO (${identifier})$`, "i").exec(action);
145
+ if (rename !== null) {
146
+ const rows = yield* sql `SELECT attname AS name FROM pg_attribute
147
+ WHERE attrelid = to_regclass(${table}) AND NOT attisdropped
148
+ AND attname IN (${unquote(rename[1])}, ${unquote(rename[2])})`;
149
+ if (rows.some(({ name }) => name === unquote(rename[1])))
150
+ return text;
151
+ if (rows.some(({ name }) => name === unquote(rename[2])))
152
+ return undefined;
153
+ }
154
+ }
155
+ return yield* new Migrator.MigrationError({
156
+ kind: "BadState",
157
+ message: `No replay rule for migration DDL: ${text}`,
158
+ });
159
+ });
160
+ /**
161
+ * DDL and its propagation run without BEGIN. A durable statement journal closes the
162
+ * crash gap between applying DDL and recording it; replay touches only an unfinished
163
+ * step, so a later drop/recreate cannot make an earlier create run again. Existing
164
+ * data rewrites set fixed values and are replayable, never increments or external work.
165
+ */
166
+ export const nekiMigrator = ({ record, refuseSkipped, }) => Effect.scoped(Effect.gen(function* () {
167
+ const source = yield* SqlClient.SqlClient;
168
+ const connection = yield* source.reserve;
169
+ const barrier = yield* MigrationBarrier;
170
+ const boundary = yield* MigrationBoundary;
171
+ const reactivity = yield* Reactivity.make;
172
+ const direct = yield* SqlClient.make({
173
+ acquirer: Effect.succeed(connection),
174
+ compiler: PgClient.makeCompiler(),
175
+ spanAttributes: [],
176
+ }).pipe(Effect.provideService(Reactivity.Reactivity, reactivity));
177
+ for (const [name, ddl] of [
178
+ [
179
+ "history",
180
+ "CREATE TABLE IF NOT EXISTS actor_migrations (migration_id integer PRIMARY KEY, created_at timestamptz NOT NULL DEFAULT now(), name text NOT NULL)",
181
+ ],
182
+ [
183
+ "journal",
184
+ "CREATE TABLE IF NOT EXISTS actor_migration_steps (migration_id integer NOT NULL, step integer NOT NULL, statement text NOT NULL, completed boolean NOT NULL DEFAULT false, PRIMARY KEY (migration_id, step))",
185
+ ],
186
+ ]) {
187
+ yield* barrier(connection);
188
+ yield* direct.unsafe(ddl);
189
+ yield* boundary(`bootstrap:${name}:ddl`);
190
+ yield* barrier(connection);
191
+ yield* boundary(`bootstrap:${name}:propagated`);
192
+ }
193
+ yield* Effect.provideService(refuseSkipped, SqlClient.SqlClient, direct);
194
+ const rows = yield* direct `SELECT migration_id::int AS id FROM actor_migrations`;
195
+ const latest = Math.max(0, ...rows.map(({ id }) => id));
196
+ const loaded = yield* Migrator.fromRecord(record);
197
+ if (new Set(loaded.map(([id]) => id)).size !== loaded.length)
198
+ return yield* new Migrator.MigrationError({
199
+ kind: "Duplicates",
200
+ message: "Found duplicate migration ids",
201
+ });
202
+ const applied = [];
203
+ for (const [id, name] of loaded) {
204
+ if (id <= latest)
205
+ continue;
206
+ const [progress] = yield* direct `SELECT EXISTS (
207
+ SELECT 1 FROM actor_migration_steps WHERE migration_id = ${id}) AS started`;
208
+ let step = 0;
209
+ const execute = (text, parameters, transform) => Effect.gen(function* () {
210
+ if (/^SELECT\b/i.test(text.trim()))
211
+ return yield* connection.execute(text, parameters, transform);
212
+ const mutation = text.trim();
213
+ const ddl = /^(CREATE|ALTER|DROP)\b/i.test(mutation);
214
+ if (!ddl && !(id === 26 && /^UPDATE\b/i.test(mutation)))
215
+ return yield* Effect.die(new Migrator.MigrationError({
216
+ kind: "BadState",
217
+ message: `Migration ${id} has no replayable data step: ${mutation}`,
218
+ }));
219
+ const alteration = alter.exec(mutation);
220
+ const statements = alteration !== null
221
+ ? alterActions(alteration[2]).map((action) => `ALTER TABLE ${alteration[1]} ${action}`)
222
+ : [mutation];
223
+ for (const statement of statements) {
224
+ const position = ++step;
225
+ const point = `${id}:${position}`;
226
+ const [saved] = yield* direct `SELECT statement, completed
227
+ FROM actor_migration_steps WHERE migration_id = ${id} AND step = ${position}`;
228
+ if (saved !== undefined && saved.statement !== statement)
229
+ return yield* Effect.die(new Migrator.MigrationError({
230
+ kind: "BadState",
231
+ message: `Migration ${point} changed after it started`,
232
+ }));
233
+ if (saved?.completed === true)
234
+ continue;
235
+ if (saved === undefined) {
236
+ yield* direct `INSERT INTO actor_migration_steps (migration_id, step, statement) VALUES (${id}, ${position}, ${statement})`;
237
+ yield* boundary(`${point}:pending`);
238
+ }
239
+ if (ddl)
240
+ yield* barrier(connection);
241
+ const replay = ddl
242
+ ? yield* replayDdl(direct, statement).pipe(Effect.orDie)
243
+ : statement;
244
+ if (replay !== undefined)
245
+ yield* connection.execute(replay, parameters, transform);
246
+ yield* boundary(`${point}:applied`);
247
+ if (ddl) {
248
+ yield* barrier(connection);
249
+ yield* boundary(`${point}:propagated`);
250
+ }
251
+ yield* direct `UPDATE actor_migration_steps SET completed = true WHERE migration_id = ${id} AND step = ${position}`;
252
+ yield* boundary(`${point}:completed`);
253
+ }
254
+ return [];
255
+ });
256
+ const client = yield* SqlClient.make({
257
+ acquirer: Effect.succeed({ ...connection, execute }),
258
+ compiler: PgClient.makeCompiler(),
259
+ spanAttributes: [],
260
+ }).pipe(Effect.provideService(Reactivity.Reactivity, reactivity));
261
+ yield* record[Object.keys(record).find((key) => Number(key.split("_")[0]) === id)].pipe(Effect.provideService(SqlClient.SqlClient, client), Effect.provideService(MigrationResuming, progress?.started === true));
262
+ const [removed] = yield* direct `SELECT EXISTS (
263
+ SELECT 1 FROM actor_migration_steps WHERE migration_id = ${id} AND step > ${step}
264
+ ) AS exists`;
265
+ if (removed?.exists === true)
266
+ return yield* new Migrator.MigrationError({
267
+ kind: "BadState",
268
+ message: `Migration ${id} removed steps after it started`,
269
+ });
270
+ yield* direct `INSERT INTO actor_migrations (migration_id, name) VALUES (${id}, ${name})`;
271
+ yield* boundary(`${id}:recorded`);
272
+ applied.push([id, name]);
273
+ }
274
+ yield* Effect.provideService(refuseSkipped, SqlClient.SqlClient, direct);
275
+ return applied;
276
+ }));
@@ -0,0 +1,23 @@
1
+ import type { PgConnection, PgPool } from "@effect/sql-pg";
2
+ import { Context, Effect } from "effect";
3
+ import type { Scope } from "effect";
4
+ import type { SqlError } from "effect/sql";
5
+ /**
6
+ * Whether the database is a Neki router. Turn sessions then run
7
+ * `NEKI_SESSION_SETTINGS`; nothing sets this outside the Neki conformance
8
+ * backend until Neki is a supported database.
9
+ */
10
+ export declare const NekiTurnSessions: Context.Reference<boolean>;
11
+ /**
12
+ * Session settings a turn connection needs on Neki, in the order they are set.
13
+ * The router reads the transaction mode when `BEGIN` arrives, so both are set
14
+ * on the session before any turn opens a transaction, never inside one.
15
+ */
16
+ export declare const NEKI_SESSION_SETTINGS: ReadonlyArray<string>;
17
+ /**
18
+ * `pool.get` with `NEKI_SESSION_SETTINGS` run once on each session, on its
19
+ * first lease, so a turn that reaches a second shard fails instead of
20
+ * committing on one shard and not the other. A session whose settings fail is
21
+ * dropped from the pool: a turn must never run on one that lacks them.
22
+ */
23
+ export declare const nekiLease: (pool: PgPool.PgPool) => Effect.Effect<PgConnection.PgConnection, SqlError.SqlError, Scope.Scope>;
@@ -0,0 +1,31 @@
1
+ import { Context, Effect } from "effect";
2
+ /**
3
+ * Whether the database is a Neki router. Turn sessions then run
4
+ * `NEKI_SESSION_SETTINGS`; nothing sets this outside the Neki conformance
5
+ * backend until Neki is a supported database.
6
+ */
7
+ export const NekiTurnSessions = Context.Reference("akter/NekiTurnSessions", {
8
+ defaultValue: () => false,
9
+ });
10
+ /**
11
+ * Session settings a turn connection needs on Neki, in the order they are set.
12
+ * The router reads the transaction mode when `BEGIN` arrives, so both are set
13
+ * on the session before any turn opens a transaction, never inside one.
14
+ */
15
+ export const NEKI_SESSION_SETTINGS = [
16
+ "SET __neki.tx_mode = 'single'",
17
+ "SET __neki.fanout = 'single'",
18
+ ];
19
+ /**
20
+ * `pool.get` with `NEKI_SESSION_SETTINGS` run once on each session, on its
21
+ * first lease, so a turn that reaches a second shard fails instead of
22
+ * committing on one shard and not the other. A session whose settings fail is
23
+ * dropped from the pool: a turn must never run on one that lacks them.
24
+ */
25
+ export const nekiLease = (pool) => {
26
+ const configured = new WeakSet();
27
+ const configure = (connection) => Effect.forEach(NEKI_SESSION_SETTINGS, (setting) => connection.query(setting, [], false), {
28
+ discard: true,
29
+ }).pipe(Effect.tap(() => Effect.sync(() => configured.add(connection))), Effect.tapCause(() => pool.invalidate(connection)));
30
+ return Effect.tap(pool.get, (connection) => configured.has(connection) ? Effect.void : configure(connection));
31
+ };
@@ -0,0 +1,21 @@
1
+ import { PgliteClient } from "@effect/sql-pglite";
2
+ import { DataDirLocked, DataDirVersion } from "../../errors/database.ts";
3
+ /**
4
+ * The Postgres major the pinned PGlite embeds. Postgres cannot open a data
5
+ * directory another major wrote, so a PGlite upgrade across a major must
6
+ * change this, and a test checks it against what a fresh directory records.
7
+ */
8
+ export declare const POSTGRES_MAJOR = "18";
9
+ /** The lock file inside a data directory; the kernel drops its lock when the holder dies. */
10
+ export declare const LOCK_FILE = ".akter.lock";
11
+ /**
12
+ * A PGlite client layer that owns fresh instances; a borrowed `liveClient`
13
+ * keeps its original methods and lifetime. A file-backed instance holds its
14
+ * data directory's lock from before it opens until after it closes, refuses a
15
+ * directory another Postgres major wrote, and refuses `relaxedDurability`
16
+ * because it acknowledges a commit before its WAL is written, so a crash
17
+ * could lose a turn whose receipt the caller already has. Closing waits for
18
+ * in-flight queries: interrupted SQL fibers can leave protocol exchanges
19
+ * running, and closing PGlite during one deadlocks its single connection.
20
+ */
21
+ export declare const pglite: (config?: PgliteClient.PgliteClientConfig) => import("effect/Layer").Layer<PgliteClient.PgliteClient | import("effect/sql/SqlClient").SqlClient, DataDirLocked | DataDirVersion | import("effect/sql/SqlError").SqlError, never>;
@@ -0,0 +1,74 @@
1
+ import { PGlite } from "@electric-sql/pglite";
2
+ import { PgliteClient } from "@effect/sql-pglite";
3
+ import { Effect } from "effect";
4
+ import { DataDirLocked, DataDirVersion } from "../../errors/database.js";
5
+ import { flockExclusive } from "./flock.js";
6
+ /**
7
+ * The Postgres major the pinned PGlite embeds. Postgres cannot open a data
8
+ * directory another major wrote, so a PGlite upgrade across a major must
9
+ * change this, and a test checks it against what a fresh directory records.
10
+ */
11
+ export const POSTGRES_MAJOR = "18";
12
+ /** The lock file inside a data directory; the kernel drops its lock when the holder dies. */
13
+ export const LOCK_FILE = ".akter.lock";
14
+ /** A filesystem data directory, or undefined for an in-memory database. */
15
+ const directoryOf = (dataDir) => {
16
+ if (dataDir === undefined || dataDir.startsWith("memory://"))
17
+ return undefined;
18
+ return dataDir.startsWith("file://") ? dataDir.slice("file://".length) : dataDir;
19
+ };
20
+ /** Holds an exclusive lock on the directory's lock file for the scope, so a second instance, in this process or another, never opens PGlite. */
21
+ const lockDataDir = (directory) => Effect.gen(function* () {
22
+ if (!(yield* flockExclusive(`${directory}/${LOCK_FILE}`)))
23
+ return yield* DataDirLocked.make({ dataDir: directory });
24
+ });
25
+ /** Refuses a directory another Postgres major wrote before PGlite fails on it opaquely. */
26
+ const checkVersion = (directory) => Effect.gen(function* () {
27
+ const found = yield* Effect.promise(() => import("node:fs/promises").then(({ readFile }) => readFile(`${directory}/PG_VERSION`, "utf8").then((text) => text.trim(), (error) => {
28
+ if (error.code === "ENOENT")
29
+ return undefined;
30
+ throw error;
31
+ })));
32
+ if (found !== undefined && found !== POSTGRES_MAJOR)
33
+ return yield* DataDirVersion.make({ dataDir: directory, found, expected: POSTGRES_MAJOR });
34
+ });
35
+ /**
36
+ * A PGlite client layer that owns fresh instances; a borrowed `liveClient`
37
+ * keeps its original methods and lifetime. A file-backed instance holds its
38
+ * data directory's lock from before it opens until after it closes, refuses a
39
+ * directory another Postgres major wrote, and refuses `relaxedDurability`
40
+ * because it acknowledges a commit before its WAL is written, so a crash
41
+ * could lose a turn whose receipt the caller already has. Closing waits for
42
+ * in-flight queries: interrupted SQL fibers can leave protocol exchanges
43
+ * running, and closing PGlite during one deadlocks its single connection.
44
+ */
45
+ export const pglite = (config = {}) => {
46
+ if ("liveClient" in config)
47
+ return PgliteClient.layer(config);
48
+ const directory = directoryOf(config.dataDir);
49
+ return PgliteClient.layerFrom(Effect.gen(function* () {
50
+ if (directory !== undefined) {
51
+ if (config.relaxedDurability === true)
52
+ return yield* Effect.die(new Error("A file-backed PGlite database refuses relaxedDurability"));
53
+ yield* lockDataDir(directory);
54
+ yield* checkVersion(directory);
55
+ }
56
+ const pending = new Set();
57
+ const database = yield* Effect.acquireRelease(Effect.sync(() => {
58
+ const database = new PGlite(config);
59
+ const query = database.query.bind(database);
60
+ database.query = (...args) => {
61
+ const promise = query(...args);
62
+ pending.add(promise);
63
+ return promise.finally(() => pending.delete(promise));
64
+ };
65
+ return database;
66
+ }), (database) => Effect.gen(function* () {
67
+ while (pending.size > 0)
68
+ yield* Effect.promise(() => Promise.allSettled(pending));
69
+ yield* Effect.promise(() => database.close());
70
+ }));
71
+ yield* Effect.promise(() => database.waitReady);
72
+ return yield* PgliteClient.make({ ...config, liveClient: database });
73
+ }));
74
+ };
@@ -0,0 +1,41 @@
1
+ import { PgClient } from "@effect/sql-pg";
2
+ import { Context, Effect, Layer } from "effect";
3
+ import type { SqlClient } from "effect/sql";
4
+ /**
5
+ * The primary's WAL insert position as a decimal string, and the database
6
+ * clock in epoch milliseconds. Read on a turn's session after its `COMMIT` or
7
+ * `ROLLBACK`, the position is at least the end of every commit record that
8
+ * session could have observed, so a replica that has replayed this far sees
9
+ * the turn's writes. An LSN cannot be known inside the transaction that
10
+ * writes it, which is why nothing stores it. The clock is read after the
11
+ * transaction ended, in the same flight, so an external caller's expiry
12
+ * recheck before its reply costs no round trip of its own.
13
+ */
14
+ export declare const COMMIT_VERSION = "SELECT (pg_current_wal_insert_lsn() - '0/0')::text AS version,\n floor(extract(epoch FROM clock_timestamp()) * 1000)::text AS now";
15
+ /**
16
+ * This runner's streaming replica, if it has one. A query that carries a
17
+ * version reads there only once the replica has replayed past it, and
18
+ * otherwise reads the primary.
19
+ */
20
+ export declare const ReadReplica: Context.Reference<SqlClient.SqlClient | undefined>;
21
+ /** Provides `ReadReplica` as a client for `options`, or none when no replica is configured. */
22
+ export declare const replicaLayer: (options: PgClient.PgPoolConfig | undefined) => Layer.Layer<never, import("effect/sql/SqlError").SqlError, never>;
23
+ /**
24
+ * The primary's pool for queries, apart from the off-turn pool. Command
25
+ * admission and the receipt replay it serves then never queue behind a burst
26
+ * of readers, nor readers behind admission. Queries of types with owned
27
+ * tables or blobs stay on the off-turn pool, because the owned-rows binding
28
+ * is built on that client.
29
+ */
30
+ export declare const QueryPool: Context.Reference<SqlClient.SqlClient | undefined>;
31
+ /** Provides `QueryPool` as a bounded, first-come, first-served pool for `options`. */
32
+ export declare const queryPoolLayer: (options: PgClient.PgPoolConfig) => Layer.Layer<never, import("effect/sql/SqlError").SqlError, never>;
33
+ /**
34
+ * Whether the replica has replayed WAL through `version`. A server not in
35
+ * recovery reports no replay position, so it never counts as caught up.
36
+ *
37
+ * This runs as its own statement before the query's reads: a statement's
38
+ * snapshot is taken before its functions run, so a check in the same statement
39
+ * could pass after a snapshot that predates the replayed commit.
40
+ */
41
+ export declare const caughtUp: (replica: SqlClient.SqlClient, version: string) => Effect.Effect<boolean, import("effect/sql/SqlError").SqlError, never>;
@@ -0,0 +1,51 @@
1
+ import { PgClient } from "@effect/sql-pg";
2
+ import { Context, Effect, Layer } from "effect";
3
+ import { Reactivity } from "effect/reactivity";
4
+ import { boundedPool } from "./bounded.js";
5
+ /**
6
+ * The primary's WAL insert position as a decimal string, and the database
7
+ * clock in epoch milliseconds. Read on a turn's session after its `COMMIT` or
8
+ * `ROLLBACK`, the position is at least the end of every commit record that
9
+ * session could have observed, so a replica that has replayed this far sees
10
+ * the turn's writes. An LSN cannot be known inside the transaction that
11
+ * writes it, which is why nothing stores it. The clock is read after the
12
+ * transaction ended, in the same flight, so an external caller's expiry
13
+ * recheck before its reply costs no round trip of its own.
14
+ */
15
+ export const COMMIT_VERSION = `SELECT (pg_current_wal_insert_lsn() - '0/0')::text AS version,
16
+ floor(extract(epoch FROM clock_timestamp()) * 1000)::text AS now`;
17
+ /**
18
+ * This runner's streaming replica, if it has one. A query that carries a
19
+ * version reads there only once the replica has replayed past it, and
20
+ * otherwise reads the primary.
21
+ */
22
+ export const ReadReplica = Context.Reference("@rikalabs/akter/runtime/database/replica/ReadReplica", { defaultValue: () => undefined });
23
+ /** Provides `ReadReplica` as a client for `options`, or none when no replica is configured. */
24
+ export const replicaLayer = (options) => Layer.effect(ReadReplica, Effect.gen(function* () {
25
+ if (options === undefined)
26
+ return undefined;
27
+ return yield* boundedPool(options);
28
+ })).pipe(Layer.provide(Reactivity.layer));
29
+ /**
30
+ * The primary's pool for queries, apart from the off-turn pool. Command
31
+ * admission and the receipt replay it serves then never queue behind a burst
32
+ * of readers, nor readers behind admission. Queries of types with owned
33
+ * tables or blobs stay on the off-turn pool, because the owned-rows binding
34
+ * is built on that client.
35
+ */
36
+ export const QueryPool = Context.Reference("@rikalabs/akter/runtime/database/replica/QueryPool", { defaultValue: () => undefined });
37
+ /** Provides `QueryPool` as a bounded, first-come, first-served pool for `options`. */
38
+ export const queryPoolLayer = (options) => Layer.effect(QueryPool, boundedPool(options)).pipe(Layer.provide(Reactivity.layer));
39
+ /**
40
+ * Whether the replica has replayed WAL through `version`. A server not in
41
+ * recovery reports no replay position, so it never counts as caught up.
42
+ *
43
+ * This runs as its own statement before the query's reads: a statement's
44
+ * snapshot is taken before its functions run, so a check in the same statement
45
+ * could pass after a snapshot that predates the replayed commit.
46
+ */
47
+ export const caughtUp = Effect.fnUntraced(function* (replica, version) {
48
+ const rows = yield* replica `
49
+ SELECT coalesce(pg_last_wal_replay_lsn() - '0/0' >= ${version}::numeric, false) AS ready`;
50
+ return rows[0]?.ready === true;
51
+ });
@@ -0,0 +1,21 @@
1
+ import { Context, Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ /** One inclusive bucket range on one database shard, independent of actor compute ownership. */
4
+ export interface BucketRange {
5
+ readonly first: number;
6
+ readonly last: number;
7
+ /** Neki's shard UID; absent on an ordinary single database. */
8
+ readonly shard?: string | undefined;
9
+ }
10
+ /** The data ranges this runner may scan; ordinary databases have one range and no session setting. */
11
+ export declare const ShardMap: Context.Reference<readonly BucketRange[]>;
12
+ /**
13
+ * Gives each targeted range its own session for the lifetime of the caller's
14
+ * scope. A shard setting cannot leak into the shared off-turn pool, and a
15
+ * failed setup closes the session instead of returning it to another user.
16
+ * Untargeted ranges reuse the existing client without a setting or a lease.
17
+ */
18
+ export declare const shardClients: Effect.Effect<{
19
+ range: BucketRange;
20
+ sql: SqlClient.SqlClient;
21
+ }[], import("effect/sql/SqlError").SqlError, import("effect/Scope").Scope | SqlClient.SqlClient>;
@@ -0,0 +1,37 @@
1
+ import { PgClient } from "@effect/sql-pg";
2
+ import { Context, Effect, Layer } from "effect";
3
+ import { SqlClient } from "effect/sql";
4
+ import { BUCKETS } from "../turn/outbox.js";
5
+ /** The data ranges this runner may scan; ordinary databases have one range and no session setting. */
6
+ export const ShardMap = Context.Reference("akter/ShardMap", {
7
+ defaultValue: () => [BUCKETS],
8
+ });
9
+ /**
10
+ * Gives each targeted range its own session for the lifetime of the caller's
11
+ * scope. A shard setting cannot leak into the shared off-turn pool, and a
12
+ * failed setup closes the session instead of returning it to another user.
13
+ * Untargeted ranges reuse the existing client without a setting or a lease.
14
+ */
15
+ export const shardClients = Effect.gen(function* () {
16
+ const sql = yield* SqlClient.SqlClient;
17
+ const ranges = yield* ShardMap;
18
+ const sorted = [...ranges].sort((a, b) => a.first - b.first);
19
+ for (const [index, range] of sorted.entries()) {
20
+ if (!Number.isInteger(range.first) ||
21
+ !Number.isInteger(range.last) ||
22
+ range.first < BUCKETS.first ||
23
+ range.last > BUCKETS.last ||
24
+ range.first > range.last ||
25
+ (index > 0 && sorted[index - 1].last >= range.first) ||
26
+ range.shard === "")
27
+ return yield* Effect.die(new Error("Invalid or overlapping shard bucket ranges"));
28
+ }
29
+ return yield* Effect.forEach(ranges, (range) => Effect.gen(function* () {
30
+ if (range.shard === undefined)
31
+ return { range, sql };
32
+ const postgres = yield* PgClient.PgClient;
33
+ const client = Context.get(yield* Layer.build(PgClient.layerFrom(PgClient.makeClient(postgres.config))), SqlClient.SqlClient);
34
+ yield* client `SET __neki.shard = ${client.literal(`'${range.shard.replaceAll("'", "''")}'`)}`;
35
+ return { range, sql: client };
36
+ }));
37
+ });
@@ -0,0 +1,7 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ /**
4
+ * Runs `effect` in a read-only, repeatable-read transaction, so every read in
5
+ * it sees one snapshot and Postgres refuses any write it could attempt.
6
+ */
7
+ export declare const inReadOnlySnapshot: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | import("effect/sql/SqlError").SqlError, R | SqlClient.SqlClient>;
@@ -0,0 +1,7 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ /**
4
+ * Runs `effect` in a read-only, repeatable-read transaction, so every read in
5
+ * it sees one snapshot and Postgres refuses any write it could attempt.
6
+ */
7
+ export const inReadOnlySnapshot = (effect) => Effect.flatMap(SqlClient.SqlClient, (sql) => sql.withTransaction(sql `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ ONLY`.pipe(Effect.andThen(effect))));