@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,254 @@
1
+ import { Data, Deferred, Effect } from "effect";
2
+ import { SqlClient, type Statement } from "effect/sql";
3
+ import type { JobFailure, JobRoute, RegisteredJob } from "../members.ts";
4
+ import type { progressPool } from "./progress.ts";
5
+ /** A job row as a claim returned it. */
6
+ export interface ClaimedJob {
7
+ readonly routing_key: string;
8
+ readonly intent_id: string;
9
+ readonly attempts: number;
10
+ readonly last_error: string | null;
11
+ readonly ambiguous: boolean;
12
+ readonly tenant_id: string;
13
+ readonly actor_type: string;
14
+ readonly actor_id: string;
15
+ readonly command: string;
16
+ readonly payload: string;
17
+ readonly payload_version: number;
18
+ readonly caller: string;
19
+ /** The claim's `due_at_ms`: the lease end the claim wrote. */
20
+ readonly claimed_until: string;
21
+ /** Cancelled by a turn: settled with what is known, never attempted again. */
22
+ readonly cancelled: boolean;
23
+ /** An earlier attempt may have applied the call. */
24
+ readonly maybe_applied: boolean;
25
+ /** Its retries ran out, or an attempt's failure was final, before this claim. */
26
+ readonly exhausted: boolean;
27
+ }
28
+ /** One job type of one actor whose attempts run under a per-actor cap. */
29
+ export interface CappedGroup {
30
+ readonly routing_key: string;
31
+ readonly tenant_id: string;
32
+ readonly actor_type: string;
33
+ readonly actor_id: string;
34
+ readonly command: string;
35
+ }
36
+ /** The job rows of `group`, as the outbox row aliased `o`. */
37
+ export declare const groupRow: ({ sql, group, }: {
38
+ readonly sql: SqlClient.SqlClient;
39
+ readonly group: CappedGroup;
40
+ }) => Statement.Statement<import("effect/sql/SqlConnection").Row>;
41
+ /**
42
+ * The actor's shard-local generation row serializes claims and wakes of its
43
+ * capped jobs, and conflicts with an actor turn's own lock on it. The lock
44
+ * is `NO KEY UPDATE` so it does not block the key-share lock a settling
45
+ * attempt's dead-letter insert takes on the row while it holds the job row
46
+ * this claim then waits for; a stronger lock would deadlock the two.
47
+ */
48
+ export declare const groupLock: ({ sql, group, }: {
49
+ readonly sql: SqlClient.SqlClient;
50
+ readonly group: CappedGroup;
51
+ }) => Statement.Statement<import("effect/sql/SqlConnection").Row>;
52
+ /**
53
+ * Makes the oldest waiting row of `group` due now, after one of its attempts
54
+ * settled. It takes the group's lock like a claim, so it never overlaps one:
55
+ * a claim's `SKIP LOCKED` would pass over the row this update holds and start
56
+ * a younger row ahead of it, breaking enqueue order. The lock also means no
57
+ * claim is taking the row while the update reads it. The outer guard refuses
58
+ * a row that is running by the time the update reaches it, so a wake never
59
+ * moves a claimed attempt's lease end to now, which would stop the cap
60
+ * counting an attempt that still runs.
61
+ */
62
+ export declare const wakeWaiting: ({ sql, group, at, }: {
63
+ readonly sql: SqlClient.SqlClient;
64
+ readonly group: CappedGroup;
65
+ readonly at: number;
66
+ }) => Effect.Effect<readonly import("effect/sql/SqlConnection").Row[], import("effect/sql/SqlError").SqlError, never>;
67
+ /**
68
+ * What one claim of a job reported, decided from the executor's exit and the
69
+ * claim alone, before the row is written. `Rejected` is a result the
70
+ * `onSuccess` route cannot accept: the provider applied the call, so it is
71
+ * final and ambiguous. `Interrupted` is an attempt stopped by its
72
+ * cancellation; `Unattempted` a cancelled or exhausted row claimed only to
73
+ * be settled.
74
+ */
75
+ export type Reported = Data.TaggedEnum<{
76
+ Succeeded: {
77
+ readonly success: JobRoute | undefined;
78
+ readonly cancelled: JobRoute | undefined;
79
+ };
80
+ Rejected: {
81
+ readonly failure: JobFailure;
82
+ readonly cancelled: JobRoute | undefined;
83
+ };
84
+ Failed: {
85
+ readonly failure: JobFailure;
86
+ };
87
+ Interrupted: {};
88
+ Unattempted: {};
89
+ }>;
90
+ /** Constructors and matchers for `Reported`. */
91
+ export declare const Reported: {
92
+ readonly $is: <Tag extends "Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted">(tag: Tag) => (u: unknown) => u is Extract<{
93
+ readonly _tag: "Failed";
94
+ readonly failure: JobFailure;
95
+ }, {
96
+ readonly _tag: Tag;
97
+ }> | Extract<{
98
+ readonly _tag: "Interrupted";
99
+ }, {
100
+ readonly _tag: Tag;
101
+ }> | Extract<{
102
+ readonly _tag: "Rejected";
103
+ readonly failure: JobFailure;
104
+ readonly cancelled: JobRoute | undefined;
105
+ }, {
106
+ readonly _tag: Tag;
107
+ }> | Extract<{
108
+ readonly _tag: "Succeeded";
109
+ readonly success: JobRoute | undefined;
110
+ readonly cancelled: JobRoute | undefined;
111
+ }, {
112
+ readonly _tag: Tag;
113
+ }> | Extract<{
114
+ readonly _tag: "Unattempted";
115
+ }, {
116
+ readonly _tag: Tag;
117
+ }>;
118
+ readonly $match: {
119
+ <Cases extends { readonly [Tag in "Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]: (args: Extract<{
120
+ readonly _tag: "Failed";
121
+ readonly failure: JobFailure;
122
+ } | {
123
+ readonly _tag: "Interrupted";
124
+ } | {
125
+ readonly _tag: "Rejected";
126
+ readonly failure: JobFailure;
127
+ readonly cancelled: JobRoute | undefined;
128
+ } | {
129
+ readonly _tag: "Succeeded";
130
+ readonly success: JobRoute | undefined;
131
+ readonly cancelled: JobRoute | undefined;
132
+ } | {
133
+ readonly _tag: "Unattempted";
134
+ }, {
135
+ readonly _tag: Tag;
136
+ }>) => any; }>(cases: Cases): (value: {
137
+ readonly _tag: "Failed";
138
+ readonly failure: JobFailure;
139
+ } | {
140
+ readonly _tag: "Interrupted";
141
+ } | {
142
+ readonly _tag: "Rejected";
143
+ readonly failure: JobFailure;
144
+ readonly cancelled: JobRoute | undefined;
145
+ } | {
146
+ readonly _tag: "Succeeded";
147
+ readonly success: JobRoute | undefined;
148
+ readonly cancelled: JobRoute | undefined;
149
+ } | {
150
+ readonly _tag: "Unattempted";
151
+ }) => import("effect/Unify").Unify<ReturnType<Cases["Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]>>;
152
+ <Cases extends { readonly [Tag in "Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]: (args: Extract<{
153
+ readonly _tag: "Failed";
154
+ readonly failure: JobFailure;
155
+ } | {
156
+ readonly _tag: "Interrupted";
157
+ } | {
158
+ readonly _tag: "Rejected";
159
+ readonly failure: JobFailure;
160
+ readonly cancelled: JobRoute | undefined;
161
+ } | {
162
+ readonly _tag: "Succeeded";
163
+ readonly success: JobRoute | undefined;
164
+ readonly cancelled: JobRoute | undefined;
165
+ } | {
166
+ readonly _tag: "Unattempted";
167
+ }, {
168
+ readonly _tag: Tag;
169
+ }>) => any; }>(value: {
170
+ readonly _tag: "Failed";
171
+ readonly failure: JobFailure;
172
+ } | {
173
+ readonly _tag: "Interrupted";
174
+ } | {
175
+ readonly _tag: "Rejected";
176
+ readonly failure: JobFailure;
177
+ readonly cancelled: JobRoute | undefined;
178
+ } | {
179
+ readonly _tag: "Succeeded";
180
+ readonly success: JobRoute | undefined;
181
+ readonly cancelled: JobRoute | undefined;
182
+ } | {
183
+ readonly _tag: "Unattempted";
184
+ }, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Failed" | "Interrupted" | "Rejected" | "Succeeded" | "Unattempted"]>>;
185
+ };
186
+ readonly Failed: Data.TaggedEnum.ConstructorFrom<{
187
+ readonly _tag: "Failed";
188
+ readonly failure: JobFailure;
189
+ }, "_tag">;
190
+ readonly Interrupted: Data.TaggedEnum.ConstructorFrom<{
191
+ readonly _tag: "Interrupted";
192
+ }, "_tag">;
193
+ readonly Rejected: Data.TaggedEnum.ConstructorFrom<{
194
+ readonly _tag: "Rejected";
195
+ readonly failure: JobFailure;
196
+ readonly cancelled: JobRoute | undefined;
197
+ }, "_tag">;
198
+ readonly Succeeded: Data.TaggedEnum.ConstructorFrom<{
199
+ readonly _tag: "Succeeded";
200
+ readonly success: JobRoute | undefined;
201
+ readonly cancelled: JobRoute | undefined;
202
+ }, "_tag">;
203
+ readonly Unattempted: Data.TaggedEnum.ConstructorFrom<{
204
+ readonly _tag: "Unattempted";
205
+ }, "_tag">;
206
+ };
207
+ /**
208
+ * How a pass handed a claimed row to its attempt: when the claim was sent,
209
+ * the cancellation check current at the claim and a way to read the next one,
210
+ * and the lease end the relay moves with clock jumps.
211
+ */
212
+ interface Claim {
213
+ readonly at: bigint;
214
+ readonly signal: Deferred.Deferred<void>;
215
+ readonly next: () => Deferred.Deferred<void>;
216
+ readonly lease: {
217
+ until: number;
218
+ };
219
+ }
220
+ /**
221
+ * The job attempts of one runner's relay. `run` executes one claimed row and
222
+ * settles it; the returned effect reports whether the row reached a terminal
223
+ * settle, which closes the job's progress.
224
+ *
225
+ * An attempt renews its claim every `renewEveryMs` while it runs, which also
226
+ * picks up a cancellation committed on another runner; `signal` is the local
227
+ * cancellation check. The lease is measured on this runner from when the last
228
+ * claim or renewal was sent, so the database's lease can only end later, and
229
+ * an attempt that outlives it is interrupted, or never started, since another
230
+ * runner may hold the row and a started call can't be undone. A failed
231
+ * renewal retries at the next interval, and a renewal never shortens a
232
+ * deadline. The attempt is raced against its renewals, which are stopped and
233
+ * awaited before any settling write, so a late renewal can't overwrite a
234
+ * failure's backoff with a fresh lease.
235
+ *
236
+ * Settling first classifies the exit as `Reported`, then applies guarded
237
+ * writes in a fixed order until one takes: a success tries the uncancelled
238
+ * row, then the cancelled one, and otherwise is late; a failure is recorded
239
+ * at its attempt, then ends the row when it was final, the last, or
240
+ * cancelled. A failure is recorded before its dead letter, so a failed
241
+ * dead-letter transaction is retried with this attempt's cause and never
242
+ * reruns the provider. A late success marks the dead letter ambiguous, or
243
+ * records an ambiguous one when its cancellation already settled; it never
244
+ * routes a second outcome. A dead letter that loses to a cancellation settles
245
+ * the row as cancelled instead, and an attempt that never started keeps the
246
+ * row as ambiguous as earlier attempts left it (`maybe_applied`).
247
+ */
248
+ export declare const jobAttempts: (options: {
249
+ readonly progress: Effect.Success<ReturnType<typeof progressPool>>;
250
+ readonly leaseMs: number;
251
+ readonly renewEveryMs: number;
252
+ readonly wake: Effect.Effect<void>;
253
+ }) => Effect.Effect<(row: ClaimedJob, registered: RegisteredJob, claim: Claim) => Effect.Effect<boolean, import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>, never, SqlClient.SqlClient>;
254
+ export {};
@@ -0,0 +1,413 @@
1
+ import { Cause, Clock, Data, Deferred, Effect, Option, Result, Schema } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import { ActorRef, principal } from "../../identity/caller.js";
4
+ import { Request } from "../request.js";
5
+ import { count as tally, Metrics } from "../telemetry/metrics.js";
6
+ import { SpanNames } from "../telemetry/spans.js";
7
+ import { databaseTime } from "../turn/admission.js";
8
+ import { TurnHooks } from "../turn/hooks.js";
9
+ import { CallerJson } from "../turn/outbox.js";
10
+ /** The job rows of `group`, as the outbox row aliased `o`. */
11
+ export const groupRow = ({ sql, group, }) => sql `o.routing_key = ${BigInt(group.routing_key)} AND o.tenant_id = ${group.tenant_id}
12
+ AND o.actor_type = ${group.actor_type} AND o.actor_id = ${group.actor_id}
13
+ AND o.command = ${group.command} AND o.kind = 'job'`;
14
+ /**
15
+ * The actor's shard-local generation row serializes claims and wakes of its
16
+ * capped jobs, and conflicts with an actor turn's own lock on it. The lock
17
+ * is `NO KEY UPDATE` so it does not block the key-share lock a settling
18
+ * attempt's dead-letter insert takes on the row while it holds the job row
19
+ * this claim then waits for; a stronger lock would deadlock the two.
20
+ */
21
+ export const groupLock = ({ sql, group, }) => sql `SELECT 1 FROM actor_generations
22
+ WHERE routing_key = ${BigInt(group.routing_key)} AND tenant_id = ${group.tenant_id}
23
+ AND actor_type = ${group.actor_type} AND actor_id = ${group.actor_id}
24
+ FOR NO KEY UPDATE`;
25
+ /**
26
+ * Makes the oldest waiting row of `group` due now, after one of its attempts
27
+ * settled. It takes the group's lock like a claim, so it never overlaps one:
28
+ * a claim's `SKIP LOCKED` would pass over the row this update holds and start
29
+ * a younger row ahead of it, breaking enqueue order. The lock also means no
30
+ * claim is taking the row while the update reads it. The outer guard refuses
31
+ * a row that is running by the time the update reaches it, so a wake never
32
+ * moves a claimed attempt's lease end to now, which would stop the cap
33
+ * counting an attempt that still runs.
34
+ */
35
+ export const wakeWaiting = ({ sql, group, at, }) => sql.withTransaction(Effect.andThen(groupLock({ sql, group }), sql `UPDATE actor_outbox SET due_at_ms = least(due_at_ms, ${at}), waiting = false
36
+ WHERE waiting AND NOT running AND cancelled_at_ms IS NULL
37
+ AND (routing_key, intent_id) IN (
38
+ SELECT o.routing_key, o.intent_id FROM actor_outbox o
39
+ WHERE ${groupRow({ sql, group })} AND o.waiting AND NOT o.running
40
+ AND o.cancelled_at_ms IS NULL
41
+ ORDER BY o.ready_at_ms, o.intent_id LIMIT 1
42
+ FOR UPDATE OF o SKIP LOCKED
43
+ ) RETURNING 1`));
44
+ /** Constructors and matchers for `Reported`. */
45
+ export const Reported = Data.taggedEnum();
46
+ /** What a cancelled job without a result reports: `Failed` only when no attempt can have applied the call. */
47
+ const known = (ambiguous, maybeApplied) => ambiguous || maybeApplied ? "Unknown" : "Failed";
48
+ const cancelledCause = (attempts) => `Cancelled while attempt ${attempts} was running; the provider may have applied it`;
49
+ /**
50
+ * The job attempts of one runner's relay. `run` executes one claimed row and
51
+ * settles it; the returned effect reports whether the row reached a terminal
52
+ * settle, which closes the job's progress.
53
+ *
54
+ * An attempt renews its claim every `renewEveryMs` while it runs, which also
55
+ * picks up a cancellation committed on another runner; `signal` is the local
56
+ * cancellation check. The lease is measured on this runner from when the last
57
+ * claim or renewal was sent, so the database's lease can only end later, and
58
+ * an attempt that outlives it is interrupted, or never started, since another
59
+ * runner may hold the row and a started call can't be undone. A failed
60
+ * renewal retries at the next interval, and a renewal never shortens a
61
+ * deadline. The attempt is raced against its renewals, which are stopped and
62
+ * awaited before any settling write, so a late renewal can't overwrite a
63
+ * failure's backoff with a fresh lease.
64
+ *
65
+ * Settling first classifies the exit as `Reported`, then applies guarded
66
+ * writes in a fixed order until one takes: a success tries the uncancelled
67
+ * row, then the cancelled one, and otherwise is late; a failure is recorded
68
+ * at its attempt, then ends the row when it was final, the last, or
69
+ * cancelled. A failure is recorded before its dead letter, so a failed
70
+ * dead-letter transaction is retried with this attempt's cause and never
71
+ * reruns the provider. A late success marks the dead letter ambiguous, or
72
+ * records an ambiguous one when its cancellation already settled; it never
73
+ * routes a second outcome. A dead letter that loses to a cancellation settles
74
+ * the row as cancelled instead, and an attempt that never started keeps the
75
+ * row as ambiguous as earlier attempts left it (`maybe_applied`).
76
+ */
77
+ export const jobAttempts = Effect.fnUntraced(function* (options) {
78
+ const sql = yield* SqlClient.SqlClient;
79
+ const hooks = yield* TurnHooks;
80
+ const { progress, leaseMs, renewEveryMs } = options;
81
+ const requestOf = (row) => Schema.decodeEffect(CallerJson)(row.caller).pipe(Effect.flatMap((caller) => Schema.decodeEffect(Request)({
82
+ ref: { tenant: row.tenant_id, actor: row.actor_type, id: row.actor_id },
83
+ caller,
84
+ command: row.command,
85
+ commandId: row.intent_id,
86
+ payload: row.payload,
87
+ })));
88
+ const run = Effect.fnUntraced(function* (row, registered, claim) {
89
+ const routingKey = BigInt(row.routing_key);
90
+ const annotate = Effect.annotateLogs({
91
+ actor: row.actor_type,
92
+ id: row.actor_id,
93
+ tenant: row.tenant_id,
94
+ job: row.command,
95
+ jobId: row.intent_id,
96
+ });
97
+ const jobRow = sql `routing_key = ${routingKey} AND intent_id = ${row.intent_id}
98
+ AND kind = 'job'`;
99
+ const guardOf = (attempt, cancelled) => sql `${jobRow} ${attempt === undefined ? sql.literal("") : sql `AND attempts = ${attempt}`}
100
+ AND cancelled_at_ms IS ${sql.literal(cancelled ? "NOT NULL" : "NULL")}`;
101
+ const write = (route, guard) => Effect.gen(function* () {
102
+ const at = yield* databaseTime;
103
+ const settled = route === undefined
104
+ ? yield* sql `DELETE FROM actor_outbox WHERE ${guard} RETURNING 1`
105
+ : yield* sql `UPDATE actor_outbox SET kind = 'intent', command = ${route.command},
106
+ payload = ${route.payload}, payload_version = 0, due_at_ms = ${at},
107
+ scheduled_at_ms = ${at}, attempts = 0, last_error = NULL, ambiguous = false,
108
+ running = false, timer_key = NULL
109
+ WHERE ${guard} RETURNING 1`;
110
+ return settled.length > 0;
111
+ });
112
+ /** A capped success retries while a newer attempt's lease is live and the row is still there. */
113
+ const writeSuccess = (route, guard, after) => Effect.gen(function* () {
114
+ while (true) {
115
+ const newer = (at) => sql `(attempts > ${after} AND running AND due_at_ms > ${at})`;
116
+ if (yield* write(route, sql `${guard} AND NOT ${newer(yield* databaseTime)}`))
117
+ return true;
118
+ const held = yield* sql `SELECT ${newer(yield* databaseTime)} AS live FROM actor_outbox WHERE ${guard}`;
119
+ if (held.length === 0)
120
+ return false;
121
+ if (held[0].live)
122
+ yield* Effect.sleep(renewEveryMs);
123
+ }
124
+ });
125
+ const apply = (terminal, after = row.attempts) => Effect.gen(function* () {
126
+ const guard = guardOf(terminal.attempt, terminal.cancelled);
127
+ if (terminal.letter === undefined)
128
+ return terminal.attempt === undefined && registered.perActor !== undefined
129
+ ? yield* writeSuccess(terminal.route, guard, after)
130
+ : yield* write(terminal.route, guard);
131
+ const letter = terminal.letter;
132
+ return yield* sql.withTransaction(Effect.gen(function* () {
133
+ if (!(yield* write(terminal.route, guard)))
134
+ return false;
135
+ yield* Effect.logWarning("Job dead-lettered after its last attempt", letter.cause).pipe(annotate);
136
+ yield* tally(Metrics.deadLetters, { actor_type: row.actor_type, job: row.command }, 1);
137
+ yield* sql `INSERT INTO actor_dead_letters (routing_key, job_id, tenant_id, actor_type,
138
+ actor_id, job, payload, payload_version, attempts, cause, ambiguous, dead_at_ms)
139
+ VALUES (${routingKey}, ${row.intent_id}, ${row.tenant_id}, ${row.actor_type},
140
+ ${row.actor_id}, ${row.command}, ${row.payload}, ${row.payload_version},
141
+ ${letter.attempts}, ${letter.cause}, ${letter.ambiguous}, ${yield* databaseTime})`;
142
+ const request = yield* requestOf(row).pipe(Effect.option);
143
+ if (Option.isSome(request))
144
+ yield* hooks.at("beforeDeadLetterCommit", request.value);
145
+ return true;
146
+ }));
147
+ }).pipe(Effect.tap((settled) => settled && terminal.route !== undefined ? options.wake : Effect.void));
148
+ const deadLetter = (attempts, cause, ambiguous, cancelled) => Effect.gen(function* () {
149
+ const letter = { jobId: row.intent_id, attempts, cause, ambiguous };
150
+ return yield* apply({
151
+ route: yield* registered.deadLetter(row.payload, row.payload_version, letter),
152
+ attempt: attempts,
153
+ cancelled,
154
+ letter,
155
+ });
156
+ });
157
+ /**
158
+ * Settles a cancelled job that has no result. Without an `onCancelled`
159
+ * route, an unknown outcome is dead-lettered as ambiguous and a failed
160
+ * one is dropped with a log line.
161
+ */
162
+ const settleCancelled = (attempts, outcome, cause) => Effect.gen(function* () {
163
+ const ambiguous = outcome === "Unknown";
164
+ if (registered.routesCancelled) {
165
+ const route = yield* registered.cancelled(row.payload, row.payload_version, {
166
+ jobId: row.intent_id,
167
+ attempts,
168
+ outcome: { _tag: outcome, cause },
169
+ ambiguous,
170
+ });
171
+ if (route !== undefined)
172
+ return yield* apply({ route, attempt: attempts, cancelled: true });
173
+ }
174
+ if (ambiguous)
175
+ return yield* deadLetter(attempts, cause, true, true);
176
+ const dropped = yield* apply({ route: undefined, attempt: attempts, cancelled: true });
177
+ if (dropped)
178
+ yield* Effect.logInfo("Cancelled job dropped after a failed attempt", cause).pipe(Effect.annotateLogs({ attempt: attempts }), annotate);
179
+ return dropped;
180
+ });
181
+ /** Dead-letters the row at `attempts` unless a cancellation took it first, which then settles it. */
182
+ const exhaust = (attempts, cause, ambiguous) => Effect.gen(function* () {
183
+ if (yield* deadLetter(attempts, cause, ambiguous, false))
184
+ return true;
185
+ const [cancelled] = yield* sql `SELECT maybe_applied
186
+ FROM actor_outbox WHERE ${guardOf(attempts, true)}`;
187
+ return cancelled === undefined
188
+ ? false
189
+ : yield* settleCancelled(attempts, known(ambiguous, cancelled.maybe_applied), cause);
190
+ });
191
+ const warnAttempt = (message) => Effect.logWarning(message).pipe(Effect.annotateLogs({ attempt: row.attempts }), annotate);
192
+ /**
193
+ * A success no settle matched: the row already ended. It marks the dead
194
+ * letter ambiguous, or records an ambiguous one when the cancellation's
195
+ * route already committed; it never routes a second outcome.
196
+ */
197
+ const late = (cancelledRoute) => Effect.gen(function* () {
198
+ const marked = yield* sql `UPDATE actor_dead_letters SET ambiguous = true
199
+ WHERE routing_key = ${routingKey} AND job_id = ${row.intent_id} RETURNING 1`;
200
+ if (marked.length > 0)
201
+ return yield* warnAttempt("Job succeeded after it was dead-lettered");
202
+ const reported = cancelledRoute?.command;
203
+ if (!registered.routesCancelled || reported === undefined)
204
+ return;
205
+ const recorded = yield* sql `INSERT INTO actor_dead_letters (routing_key, job_id,
206
+ tenant_id, actor_type, actor_id, job, payload, payload_version, attempts, cause,
207
+ ambiguous, dead_at_ms)
208
+ SELECT ${routingKey}, ${row.intent_id}, ${row.tenant_id}, ${row.actor_type},
209
+ ${row.actor_id}, ${row.command}, ${row.payload}, ${row.payload_version}, ${row.attempts},
210
+ 'Succeeded after it was cancelled', true, ${yield* databaseTime}
211
+ WHERE EXISTS (
212
+ SELECT 1 FROM actor_outbox WHERE routing_key = ${routingKey}
213
+ AND intent_id = ${row.intent_id} AND kind = 'intent' AND command = ${reported}
214
+ UNION ALL
215
+ SELECT 1 FROM actor_receipts WHERE routing_key = ${routingKey}
216
+ AND tenant_id = ${row.tenant_id} AND actor_type = ${row.actor_type}
217
+ AND actor_id = ${row.actor_id} AND command_id = ${row.intent_id}
218
+ AND command = ${reported}
219
+ )
220
+ ON CONFLICT (routing_key, job_id) DO UPDATE SET ambiguous = true
221
+ RETURNING 1`;
222
+ if (recorded.length > 0)
223
+ yield* warnAttempt("Job succeeded after its cancellation settled");
224
+ });
225
+ /** Records a failure at its attempt; undefined when a newer attempt or a settle took the row. */
226
+ const record = (failure) => Effect.gen(function* () {
227
+ const attempt = row.attempts;
228
+ const { baseMs, maxMs } = registered.backoff;
229
+ const [recorded] = yield* sql `UPDATE actor_outbox
230
+ SET last_error = ${failure.cause},
231
+ ambiguous = ${failure.notStarted === true ? sql `maybe_applied` : sql `${failure.ambiguous}`},
232
+ running = false, final_failure = ${failure.final === true},
233
+ due_at_ms = ${(yield* databaseTime) + Math.min(baseMs * 2 ** (attempt - 1), maxMs)}
234
+ WHERE ${jobRow} AND attempts = ${attempt}
235
+ RETURNING cancelled_at_ms IS NOT NULL AS cancelled, maybe_applied, ambiguous`;
236
+ return recorded;
237
+ });
238
+ /**
239
+ * Records a failure, then ends the row when it was cancelled, final, or the
240
+ * last attempt. A `rejected` result succeeded at the provider, so it goes to
241
+ * `onCancelled` when the row was cancelled, and is late when no row took it.
242
+ */
243
+ const failed = (failure, cancelledRoute, rejected) => Effect.gen(function* () {
244
+ const attempt = row.attempts;
245
+ const routesResult = cancelledRoute !== undefined && registered.routesCancelled;
246
+ if (routesResult &&
247
+ (yield* apply({ route: cancelledRoute, attempt: undefined, cancelled: true })))
248
+ return true;
249
+ const recorded = yield* record(failure);
250
+ if (recorded === undefined) {
251
+ if (rejected)
252
+ yield* late(cancelledRoute);
253
+ else
254
+ yield* warnAttempt("Job attempt failed after a newer attempt or a settle took its row");
255
+ return false;
256
+ }
257
+ if (recorded.cancelled) {
258
+ if (routesResult && (yield* apply({ route: cancelledRoute, attempt, cancelled: true })))
259
+ return true;
260
+ return yield* settleCancelled(attempt, known(recorded.ambiguous, recorded.maybe_applied), failure.cause);
261
+ }
262
+ if (failure.final === true || attempt >= registered.attempts)
263
+ return yield* exhaust(attempt, failure.cause, recorded.ambiguous);
264
+ yield* Effect.logWarning("Job attempt failed; retrying with backoff", failure.cause).pipe(Effect.annotateLogs({ attempt, ambiguous: recorded.ambiguous }), annotate);
265
+ yield* tally(Metrics.relayRetried, { kind: "job" }, 1);
266
+ return false;
267
+ });
268
+ const settle = Reported.$match({
269
+ Unattempted: () => {
270
+ const attempt = row.attempts;
271
+ if (row.cancelled && attempt === 0)
272
+ return apply({ route: undefined, attempt: 0, cancelled: true });
273
+ if (row.cancelled)
274
+ return settleCancelled(attempt, known(row.ambiguous, row.maybe_applied), row.last_error ??
275
+ (row.ambiguous || row.maybe_applied
276
+ ? cancelledCause(attempt)
277
+ : "Failed before it was cancelled"));
278
+ return exhaust(attempt, row.last_error ?? "No attempt reported", row.ambiguous);
279
+ },
280
+ Interrupted: () => Effect.logInfo("Job attempt interrupted by its cancellation").pipe(Effect.annotateLogs({ attempt: row.attempts }), annotate, Effect.andThen(settleCancelled(row.attempts, "Unknown", cancelledCause(row.attempts)))),
281
+ Succeeded: ({ success, cancelled }) => Effect.gen(function* () {
282
+ if (yield* apply({ route: success, attempt: undefined, cancelled: false })) {
283
+ yield* tally(Metrics.relayDelivered, { kind: "job" }, 1);
284
+ return true;
285
+ }
286
+ const route = registered.routesCancelled ? cancelled : success;
287
+ if (yield* apply({ route, attempt: undefined, cancelled: true }))
288
+ return true;
289
+ yield* late(cancelled);
290
+ return false;
291
+ }),
292
+ Rejected: ({ failure, cancelled }) => failed(failure, cancelled, true),
293
+ Failed: ({ failure }) => failed(failure, undefined, false),
294
+ });
295
+ if (row.cancelled || row.exhausted)
296
+ return yield* settle(Reported.Unattempted());
297
+ const attempt = row.attempts;
298
+ const request = yield* requestOf(row).pipe(Effect.orDie);
299
+ const ref = ActorRef.make(request.ref);
300
+ const leaseNanos = BigInt(leaseMs) * 1000000n;
301
+ let confirmed = claim.at;
302
+ yield* hooks.at("afterClaim", request);
303
+ yield* hooks.at("beforeExecute", request);
304
+ if ((yield* Clock.currentTimeNanos) - confirmed >= leaseNanos) {
305
+ yield* warnAttempt("Job attempt outlived its lease before it started");
306
+ return false;
307
+ }
308
+ let signal = claim.signal;
309
+ const renewals = Effect.gen(function* () {
310
+ while (true) {
311
+ yield* Deferred.await(signal).pipe(Effect.timeoutOrElse({ duration: renewEveryMs, orElse: () => Effect.void }));
312
+ signal = claim.next();
313
+ const sent = yield* Clock.currentTimeNanos;
314
+ const renewed = yield* Effect.gen(function* () {
315
+ yield* hooks.at("beforeRenew", request);
316
+ return yield* sql `UPDATE actor_outbox
317
+ SET due_at_ms = greatest(due_at_ms, ${(yield* databaseTime) + leaseMs})
318
+ WHERE ${jobRow} AND attempts = ${attempt}
319
+ RETURNING cancelled_at_ms IS NOT NULL AS cancelled, due_at_ms::text AS due_at_ms`.pipe(Effect.uninterruptible);
320
+ }).pipe(Effect.catchCause((cause) => Cause.hasInterruptsOnly(cause)
321
+ ? Effect.interrupt
322
+ : Effect.logWarning("Job lease renewal failed", cause).pipe(annotate, Effect.as(undefined))));
323
+ if (renewed === undefined)
324
+ continue;
325
+ if (renewed.length === 0)
326
+ return "lost";
327
+ confirmed = sent;
328
+ claim.lease.until = Number(renewed[0].due_at_ms);
329
+ if (renewed[0].cancelled)
330
+ return "cancelled";
331
+ }
332
+ });
333
+ const deadline = Effect.gen(function* () {
334
+ while (true) {
335
+ const left = confirmed + leaseNanos - (yield* Clock.currentTimeNanos);
336
+ if (left <= 0n)
337
+ return "deadline";
338
+ yield* Effect.sleep(Number(left / 1000000n) + 1);
339
+ }
340
+ });
341
+ const slot = yield* progress.open({
342
+ ref,
343
+ jobId: row.intent_id,
344
+ job: row.command,
345
+ attempt,
346
+ everyMs: registered.progressEveryMs,
347
+ leaseUntil: () => claim.lease.until,
348
+ });
349
+ return yield* Effect.gen(function* () {
350
+ const outcome = yield* registered
351
+ .execute(row.payload, row.payload_version, {
352
+ jobId: row.intent_id,
353
+ attempt,
354
+ principal: principal(request.caller),
355
+ ref,
356
+ reporting: slot.active,
357
+ report: slot.offer,
358
+ })
359
+ .pipe(Effect.withSpan(SpanNames.job(row.actor_type, row.command), {
360
+ kind: "client",
361
+ attributes: {
362
+ "actor.type": row.actor_type,
363
+ "actor.tenant": row.tenant_id,
364
+ "actor.id": row.actor_id,
365
+ "job.name": row.command,
366
+ "job.id": row.intent_id,
367
+ "job.attempt": attempt,
368
+ },
369
+ }, { captureStackTrace: false }), Effect.result, Effect.raceFirst(renewals), Effect.raceFirst(deadline), Effect.ensuring(slot.close));
370
+ if (outcome === "lost") {
371
+ yield* warnAttempt("Job attempt lost its lease");
372
+ return false;
373
+ }
374
+ if (outcome === "deadline") {
375
+ yield* warnAttempt("Job attempt outlived its lease; interrupted");
376
+ return false;
377
+ }
378
+ if (outcome === "cancelled")
379
+ return yield* settle(Reported.Interrupted());
380
+ if (Result.isFailure(outcome))
381
+ return yield* settle(Reported.Failed({ failure: outcome.failure }));
382
+ const { success, cancelled, rejected } = outcome.success;
383
+ if (rejected === undefined || registered.routesCancelled)
384
+ yield* hooks.at("afterExecute", request);
385
+ return yield* settle(rejected === undefined
386
+ ? Reported.Succeeded({ success, cancelled })
387
+ : Reported.Rejected({ failure: rejected, cancelled }));
388
+ }).pipe(Effect.ensuring(progress.forget(row.intent_id)));
389
+ });
390
+ /**
391
+ * Runs one claimed row and settles it. A terminal settle closes the job's
392
+ * progress; a retryable one leaves it open. A settled attempt of a capped
393
+ * job wakes the oldest waiting row of its actor.
394
+ */
395
+ return (row, registered, claim) => {
396
+ const attempt = run(row, registered, claim).pipe(Effect.tap((terminal) => terminal
397
+ ? requestOf(row).pipe(Effect.flatMap((request) => progress.closed({
398
+ ref: ActorRef.make(request.ref),
399
+ jobId: row.intent_id,
400
+ job: row.command,
401
+ attempt: row.attempts,
402
+ everyMs: registered.progressEveryMs,
403
+ })), Effect.ignore)
404
+ : Effect.void));
405
+ return registered.perActor === undefined
406
+ ? attempt
407
+ : attempt.pipe(Effect.ensuring(Effect.gen(function* () {
408
+ const woke = yield* wakeWaiting({ sql, group: row, at: yield* databaseTime });
409
+ if (woke.length > 0)
410
+ yield* options.wake;
411
+ }).pipe(Effect.ignore)));
412
+ };
413
+ });