gemi 0.117.0 → 0.118.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 (225) hide show
  1. package/dist/ai/index.js +2 -2
  2. package/dist/ai/index.js.map +1 -1
  3. package/dist/app/index.js +1 -1
  4. package/dist/bun/plugin.js +1 -1
  5. package/dist/bun/preload.js +1 -1
  6. package/dist/{chunk-6y4nk9f1.js → chunk-01ehxca0.js} +2 -2
  7. package/dist/{chunk-6y4nk9f1.js.map → chunk-01ehxca0.js.map} +1 -1
  8. package/dist/chunk-0gtyects.js +10 -0
  9. package/dist/{chunk-2czfefn2.js.map → chunk-0gtyects.js.map} +3 -3
  10. package/dist/{chunk-gn7kne7r.js → chunk-1m3hvy3q.js} +2 -2
  11. package/dist/{chunk-gn7kne7r.js.map → chunk-1m3hvy3q.js.map} +1 -1
  12. package/dist/{chunk-1ckha5dt.js → chunk-1z1rj2zq.js} +2 -2
  13. package/dist/{chunk-1ckha5dt.js.map → chunk-1z1rj2zq.js.map} +1 -1
  14. package/dist/{chunk-n9jyjp4a.js → chunk-30xxc6r7.js} +2 -2
  15. package/dist/{chunk-n9jyjp4a.js.map → chunk-30xxc6r7.js.map} +1 -1
  16. package/dist/{chunk-077rea02.js → chunk-33s2xqv1.js} +1 -1
  17. package/dist/{chunk-5m8vvtvn.js → chunk-39kyz4k6.js} +2 -2
  18. package/dist/{chunk-5m8vvtvn.js.map → chunk-39kyz4k6.js.map} +1 -1
  19. package/dist/chunk-3nf95j9e.js +5 -0
  20. package/dist/{chunk-63ewmmhc.js.map → chunk-3nf95j9e.js.map} +1 -1
  21. package/dist/{chunk-kpn7f58a.js → chunk-3zxfd7pn.js} +3 -3
  22. package/dist/{chunk-kpn7f58a.js.map → chunk-3zxfd7pn.js.map} +1 -1
  23. package/dist/{chunk-62jw0vsf.js → chunk-453rmkpm.js} +2 -2
  24. package/dist/{chunk-62jw0vsf.js.map → chunk-453rmkpm.js.map} +1 -1
  25. package/dist/{chunk-mhteg4yz.js → chunk-47h12eme.js} +5 -5
  26. package/dist/{chunk-mhteg4yz.js.map → chunk-47h12eme.js.map} +1 -1
  27. package/dist/{chunk-x84as3vy.js → chunk-490sbcma.js} +2 -2
  28. package/dist/{chunk-x84as3vy.js.map → chunk-490sbcma.js.map} +1 -1
  29. package/dist/{chunk-stnd9qht.js → chunk-4c1kdd8p.js} +2 -2
  30. package/dist/{chunk-stnd9qht.js.map → chunk-4c1kdd8p.js.map} +1 -1
  31. package/dist/{chunk-j1453bn1.js → chunk-5cgq9c43.js} +2 -2
  32. package/dist/{chunk-j1453bn1.js.map → chunk-5cgq9c43.js.map} +1 -1
  33. package/dist/{chunk-hr61ekcr.js → chunk-5dbpgyrx.js} +2 -2
  34. package/dist/{chunk-hr61ekcr.js.map → chunk-5dbpgyrx.js.map} +1 -1
  35. package/dist/{chunk-wzzrz612.js → chunk-5ses4tcz.js} +2 -2
  36. package/dist/{chunk-wzzrz612.js.map → chunk-5ses4tcz.js.map} +1 -1
  37. package/dist/{chunk-pepzecrm.js → chunk-675kzd7z.js} +2 -2
  38. package/dist/{chunk-pepzecrm.js.map → chunk-675kzd7z.js.map} +1 -1
  39. package/dist/{chunk-yhp6bvhj.js → chunk-76p0rf4d.js} +3 -3
  40. package/dist/{chunk-yhp6bvhj.js.map → chunk-76p0rf4d.js.map} +1 -1
  41. package/dist/{chunk-bvqae0px.js → chunk-8t6dwwz6.js} +1 -1
  42. package/dist/{chunk-a32wfzdq.js → chunk-8wcpxm41.js} +2 -2
  43. package/dist/{chunk-a32wfzdq.js.map → chunk-8wcpxm41.js.map} +1 -1
  44. package/dist/{chunk-ntxsdchf.js → chunk-9pkj7sk6.js} +2 -2
  45. package/dist/{chunk-ntxsdchf.js.map → chunk-9pkj7sk6.js.map} +1 -1
  46. package/dist/{chunk-w4e480he.js → chunk-a1qt8aky.js} +2 -2
  47. package/dist/{chunk-w4e480he.js.map → chunk-a1qt8aky.js.map} +1 -1
  48. package/dist/{chunk-e7ezmag9.js → chunk-aedkrck1.js} +1 -1
  49. package/dist/{chunk-arwmvgrz.js → chunk-aqpaw4jq.js} +2 -2
  50. package/dist/{chunk-arwmvgrz.js.map → chunk-aqpaw4jq.js.map} +1 -1
  51. package/dist/{chunk-hvpn18bb.js → chunk-bgwtdbfw.js} +3 -3
  52. package/dist/{chunk-hvpn18bb.js.map → chunk-bgwtdbfw.js.map} +1 -1
  53. package/dist/{chunk-gjy2qjcr.js → chunk-bz8xssrc.js} +2 -2
  54. package/dist/{chunk-gjy2qjcr.js.map → chunk-bz8xssrc.js.map} +1 -1
  55. package/dist/{chunk-yvtmygrk.js → chunk-cte6ysqd.js} +4 -4
  56. package/dist/{chunk-yvtmygrk.js.map → chunk-cte6ysqd.js.map} +1 -1
  57. package/dist/{chunk-3w4hk6q2.js → chunk-cvfg88cx.js} +3 -3
  58. package/dist/{chunk-3w4hk6q2.js.map → chunk-cvfg88cx.js.map} +1 -1
  59. package/dist/{chunk-wk1tp1f1.js → chunk-d806cy7p.js} +2 -2
  60. package/dist/{chunk-wk1tp1f1.js.map → chunk-d806cy7p.js.map} +1 -1
  61. package/dist/{chunk-zkjs3m5m.js → chunk-dwpn6fze.js} +2 -2
  62. package/dist/{chunk-zkjs3m5m.js.map → chunk-dwpn6fze.js.map} +1 -1
  63. package/dist/{chunk-nb2gggba.js → chunk-ebret82e.js} +3 -3
  64. package/dist/{chunk-nb2gggba.js.map → chunk-ebret82e.js.map} +1 -1
  65. package/dist/{chunk-g2wncay4.js → chunk-eke2frrm.js} +3 -3
  66. package/dist/{chunk-g2wncay4.js.map → chunk-eke2frrm.js.map} +1 -1
  67. package/dist/{chunk-ffgmqwzy.js → chunk-fsj5k511.js} +2 -2
  68. package/dist/{chunk-ffgmqwzy.js.map → chunk-fsj5k511.js.map} +1 -1
  69. package/dist/{chunk-076jezzg.js → chunk-g5ppst76.js} +3 -3
  70. package/dist/{chunk-076jezzg.js.map → chunk-g5ppst76.js.map} +1 -1
  71. package/dist/{chunk-37pk2cjg.js → chunk-g9hhdcax.js} +2 -2
  72. package/dist/{chunk-37pk2cjg.js.map → chunk-g9hhdcax.js.map} +1 -1
  73. package/dist/{chunk-dz99g58c.js → chunk-gqfqnv3f.js} +2 -2
  74. package/dist/{chunk-dz99g58c.js.map → chunk-gqfqnv3f.js.map} +1 -1
  75. package/dist/{chunk-51w202vr.js → chunk-hkf2k2eq.js} +3 -3
  76. package/dist/{chunk-51w202vr.js.map → chunk-hkf2k2eq.js.map} +1 -1
  77. package/dist/{chunk-dcgvq79a.js → chunk-hm9cjxy2.js} +2 -2
  78. package/dist/{chunk-dcgvq79a.js.map → chunk-hm9cjxy2.js.map} +1 -1
  79. package/dist/{chunk-5w6kyxsj.js → chunk-hr1r3g0d.js} +2 -2
  80. package/dist/{chunk-5w6kyxsj.js.map → chunk-hr1r3g0d.js.map} +1 -1
  81. package/dist/{chunk-fnwbbmnk.js → chunk-hzepfrzy.js} +2 -2
  82. package/dist/{chunk-fnwbbmnk.js.map → chunk-hzepfrzy.js.map} +1 -1
  83. package/dist/{chunk-pgy3mfxw.js → chunk-j5858bz7.js} +2 -2
  84. package/dist/{chunk-pgy3mfxw.js.map → chunk-j5858bz7.js.map} +1 -1
  85. package/dist/{chunk-c2n6zdyd.js → chunk-jf6qqzat.js} +2 -2
  86. package/dist/{chunk-c2n6zdyd.js.map → chunk-jf6qqzat.js.map} +1 -1
  87. package/dist/{chunk-8gtc3s1y.js → chunk-jg79n382.js} +2 -2
  88. package/dist/{chunk-8gtc3s1y.js.map → chunk-jg79n382.js.map} +1 -1
  89. package/dist/{chunk-00n3gwr8.js → chunk-k31qfe7a.js} +3 -3
  90. package/dist/{chunk-00n3gwr8.js.map → chunk-k31qfe7a.js.map} +1 -1
  91. package/dist/{chunk-t65074mw.js → chunk-kkte8nze.js} +3 -3
  92. package/dist/{chunk-t65074mw.js.map → chunk-kkte8nze.js.map} +1 -1
  93. package/dist/{chunk-x7qwx07b.js → chunk-m4kmetpb.js} +2 -2
  94. package/dist/{chunk-x7qwx07b.js.map → chunk-m4kmetpb.js.map} +1 -1
  95. package/dist/{chunk-ge9xjwgq.js → chunk-n4sdm0jn.js} +3 -3
  96. package/dist/{chunk-ge9xjwgq.js.map → chunk-n4sdm0jn.js.map} +1 -1
  97. package/dist/chunk-nang3847.js +416 -0
  98. package/dist/chunk-nang3847.js.map +24 -0
  99. package/dist/{chunk-vj5necm0.js → chunk-nrezmscd.js} +1 -1
  100. package/dist/{chunk-v8vnxkvp.js → chunk-p83erprx.js} +2 -2
  101. package/dist/{chunk-v8vnxkvp.js.map → chunk-p83erprx.js.map} +1 -1
  102. package/dist/{chunk-sj4f7x4p.js → chunk-pkr5dsbk.js} +2 -2
  103. package/dist/{chunk-sj4f7x4p.js.map → chunk-pkr5dsbk.js.map} +1 -1
  104. package/dist/{chunk-f8vcwzgd.js → chunk-pqc16rrx.js} +2 -2
  105. package/dist/{chunk-f8vcwzgd.js.map → chunk-pqc16rrx.js.map} +1 -1
  106. package/dist/{chunk-hvgmqt6z.js → chunk-pvz90a49.js} +2 -2
  107. package/dist/{chunk-hvgmqt6z.js.map → chunk-pvz90a49.js.map} +1 -1
  108. package/dist/{chunk-s4f56035.js → chunk-q290tgza.js} +2 -2
  109. package/dist/{chunk-s4f56035.js.map → chunk-q290tgza.js.map} +1 -1
  110. package/dist/{chunk-wgb79ysr.js → chunk-qf4bmee9.js} +2 -2
  111. package/dist/{chunk-wgb79ysr.js.map → chunk-qf4bmee9.js.map} +1 -1
  112. package/dist/{chunk-a7r39713.js → chunk-qkxnvpaj.js} +2 -2
  113. package/dist/{chunk-a7r39713.js.map → chunk-qkxnvpaj.js.map} +1 -1
  114. package/dist/chunk-r1favzz4.js +19 -0
  115. package/dist/{chunk-rhmpphhc.js.map → chunk-r1favzz4.js.map} +5 -4
  116. package/dist/{chunk-veq07rp8.js → chunk-razjfecn.js} +1 -1
  117. package/dist/{chunk-a77586gv.js → chunk-scc0j5k9.js} +2 -2
  118. package/dist/{chunk-a77586gv.js.map → chunk-scc0j5k9.js.map} +1 -1
  119. package/dist/{chunk-cytss9mb.js → chunk-sce5jes2.js} +2 -2
  120. package/dist/{chunk-cytss9mb.js.map → chunk-sce5jes2.js.map} +1 -1
  121. package/dist/{chunk-t87w4h84.js → chunk-sd02ktf2.js} +2 -2
  122. package/dist/{chunk-t87w4h84.js.map → chunk-sd02ktf2.js.map} +1 -1
  123. package/dist/{chunk-1zzd39qg.js → chunk-sn04cyw0.js} +2 -2
  124. package/dist/{chunk-1zzd39qg.js.map → chunk-sn04cyw0.js.map} +1 -1
  125. package/dist/{chunk-wwdbgshx.js → chunk-tfdmvxza.js} +2 -2
  126. package/dist/{chunk-wwdbgshx.js.map → chunk-tfdmvxza.js.map} +1 -1
  127. package/dist/{chunk-jqrs16g2.js → chunk-tzdenj0n.js} +3 -3
  128. package/dist/{chunk-jqrs16g2.js.map → chunk-tzdenj0n.js.map} +1 -1
  129. package/dist/{chunk-qhw0hej0.js → chunk-x6v2zex2.js} +2 -2
  130. package/dist/{chunk-qhw0hej0.js.map → chunk-x6v2zex2.js.map} +1 -1
  131. package/dist/{chunk-yfwrbfnw.js → chunk-xfw8zyvn.js} +2 -2
  132. package/dist/{chunk-yfwrbfnw.js.map → chunk-xfw8zyvn.js.map} +1 -1
  133. package/dist/{chunk-sksmnjkn.js → chunk-xtzn0qfh.js} +2 -2
  134. package/dist/{chunk-sksmnjkn.js.map → chunk-xtzn0qfh.js.map} +1 -1
  135. package/dist/{chunk-jpetnpzn.js → chunk-xx3zvc3g.js} +2 -2
  136. package/dist/{chunk-jpetnpzn.js.map → chunk-xx3zvc3g.js.map} +1 -1
  137. package/dist/{chunk-fk6nxhxn.js → chunk-xzn2nmny.js} +2 -2
  138. package/dist/{chunk-fk6nxhxn.js.map → chunk-xzn2nmny.js.map} +1 -1
  139. package/dist/{chunk-vtc23xpk.js → chunk-xzyy896s.js} +2 -2
  140. package/dist/{chunk-vtc23xpk.js.map → chunk-xzyy896s.js.map} +1 -1
  141. package/dist/{chunk-fa37qzm3.js → chunk-y09r0wsw.js} +3 -3
  142. package/dist/{chunk-fa37qzm3.js.map → chunk-y09r0wsw.js.map} +1 -1
  143. package/dist/{chunk-5p4z1fgc.js → chunk-ygf0z7kk.js} +2 -2
  144. package/dist/{chunk-5p4z1fgc.js.map → chunk-ygf0z7kk.js.map} +1 -1
  145. package/dist/{chunk-zw6843j3.js → chunk-z759yah5.js} +2 -2
  146. package/dist/{chunk-zw6843j3.js.map → chunk-z759yah5.js.map} +1 -1
  147. package/dist/config/index.js +1 -1
  148. package/dist/console/run.js +2 -2
  149. package/dist/console/run.js.map +1 -1
  150. package/dist/container/index.js +2 -2
  151. package/dist/container/index.js.map +1 -1
  152. package/dist/database/index.js +2 -2
  153. package/dist/database/index.js.map +1 -1
  154. package/dist/email/index.js +2 -2
  155. package/dist/email/index.js.map +1 -1
  156. package/dist/facades/index.js +2 -2
  157. package/dist/facades/index.js.map +1 -1
  158. package/dist/foundation/index.js +2 -2
  159. package/dist/foundation/index.js.map +1 -1
  160. package/dist/http/index.js +2 -2
  161. package/dist/http/index.js.map +1 -1
  162. package/dist/i18n/dictionaryRuntime.js +2 -2
  163. package/dist/i18n/dictionaryRuntime.js.map +1 -1
  164. package/dist/i18n/index.js +2 -2
  165. package/dist/i18n/index.js.map +1 -1
  166. package/dist/kernel/index.js +2 -2
  167. package/dist/kernel/index.js.map +1 -1
  168. package/dist/orm/index.js +2 -2
  169. package/dist/orm/index.js.map +1 -1
  170. package/dist/server/index.js +2 -2
  171. package/dist/server/index.js.map +1 -1
  172. package/dist/services/discovery.d.ts +8 -0
  173. package/dist/services/discovery.d.ts.map +1 -1
  174. package/dist/services/index.d.ts +8 -1
  175. package/dist/services/index.d.ts.map +1 -1
  176. package/dist/services/index.js +3 -3
  177. package/dist/services/index.js.map +2 -2
  178. package/dist/services/queue/DatabaseQueueDriver.d.ts +23 -2
  179. package/dist/services/queue/DatabaseQueueDriver.d.ts.map +1 -1
  180. package/dist/services/queue/Job.d.ts +3 -0
  181. package/dist/services/queue/Job.d.ts.map +1 -1
  182. package/dist/services/queue/MemoryQueueDriver.d.ts +10 -0
  183. package/dist/services/queue/MemoryQueueDriver.d.ts.map +1 -1
  184. package/dist/services/queue/QueueDriver.d.ts +9 -0
  185. package/dist/services/queue/QueueDriver.d.ts.map +1 -1
  186. package/dist/services/queue/QueueManager.d.ts +33 -7
  187. package/dist/services/queue/QueueManager.d.ts.map +1 -1
  188. package/dist/services/queue/QueueServiceProvider.d.ts.map +1 -1
  189. package/dist/services/queue/backoff.d.ts +6 -0
  190. package/dist/services/queue/backoff.d.ts.map +1 -0
  191. package/dist/services/queue/config.d.ts +9 -0
  192. package/dist/services/queue/config.d.ts.map +1 -1
  193. package/dist/services/queue/work.js +2 -2
  194. package/dist/services/queue/work.js.map +1 -1
  195. package/dist/services/queue/workflow/DatabaseWorkflowStore.d.ts +89 -0
  196. package/dist/services/queue/workflow/DatabaseWorkflowStore.d.ts.map +1 -0
  197. package/dist/services/queue/workflow/MemoryWorkflowStore.d.ts +43 -0
  198. package/dist/services/queue/workflow/MemoryWorkflowStore.d.ts.map +1 -0
  199. package/dist/services/queue/workflow/Step.d.ts +202 -0
  200. package/dist/services/queue/workflow/Step.d.ts.map +1 -0
  201. package/dist/services/queue/workflow/Workflow.d.ts +124 -0
  202. package/dist/services/queue/workflow/Workflow.d.ts.map +1 -0
  203. package/dist/services/queue/workflow/WorkflowRuntime.d.ts +60 -0
  204. package/dist/services/queue/workflow/WorkflowRuntime.d.ts.map +1 -0
  205. package/dist/services/queue/workflow/WorkflowStore.d.ts +184 -0
  206. package/dist/services/queue/workflow/WorkflowStore.d.ts.map +1 -0
  207. package/dist/services/queue/workflow/duration.d.ts +8 -0
  208. package/dist/services/queue/workflow/duration.d.ts.map +1 -0
  209. package/dist/services/queue/workflow/workflowContract.d.ts +30 -0
  210. package/dist/services/queue/workflow/workflowContract.d.ts.map +1 -0
  211. package/dist/stats/route-table.js +1 -1
  212. package/dist/support/index.js +2 -2
  213. package/dist/support/index.js.map +1 -1
  214. package/dist/vitest/index.js +1 -1
  215. package/package.json +1 -1
  216. package/dist/chunk-2czfefn2.js +0 -10
  217. package/dist/chunk-63ewmmhc.js +0 -5
  218. package/dist/chunk-rhmpphhc.js +0 -19
  219. package/dist/chunk-y0en07zh.js +0 -302
  220. package/dist/chunk-y0en07zh.js.map +0 -17
  221. /package/dist/{chunk-077rea02.js.map → chunk-33s2xqv1.js.map} +0 -0
  222. /package/dist/{chunk-bvqae0px.js.map → chunk-8t6dwwz6.js.map} +0 -0
  223. /package/dist/{chunk-e7ezmag9.js.map → chunk-aedkrck1.js.map} +0 -0
  224. /package/dist/{chunk-vj5necm0.js.map → chunk-nrezmscd.js.map} +0 -0
  225. /package/dist/{chunk-veq07rp8.js.map → chunk-razjfecn.js.map} +0 -0
@@ -0,0 +1,202 @@
1
+ import { type BatchStatus } from "../batch";
2
+ import type { EnqueueBatch } from "../QueueDriver";
3
+ import type { Job } from "../Job";
4
+ import { type Duration } from "./duration";
5
+ import { type StepRecord, type WorkflowStore } from "./WorkflowStore";
6
+ /** What a `step.run` function is handed. */
7
+ export type StepContext = {
8
+ /**
9
+ * `<workflow id>:<step key>`: the same on every attempt of this step, and
10
+ * different for every other step. Pass it to a payment provider, say, so
11
+ * that an attempt repeated after a crash is not charged twice.
12
+ */
13
+ idempotencyKey: string;
14
+ /** Which attempt this is, counting from 1. */
15
+ attempt: number;
16
+ /**
17
+ * Aborted when the step's `timeout` passes or the workflow is cancelled.
18
+ * Pass it to `fetch` and friends. The workflow stops waiting for the step
19
+ * at that moment, whether or not the function notices.
20
+ */
21
+ signal: AbortSignal;
22
+ };
23
+ export type StepRunOptions = {
24
+ /** How many attempts the step gets, counting the first. Default 3. */
25
+ attempts?: number;
26
+ /**
27
+ * Milliseconds to wait before each retry: one number for every retry, or
28
+ * one per retry with the last repeated, as `Job.backoff`. Default 0. A
29
+ * retry with a delay suspends the workflow until it is due.
30
+ */
31
+ backoff?: number | number[];
32
+ /** How long one attempt may take before it counts as failed. */
33
+ timeout?: Duration;
34
+ };
35
+ export type StepWaitOptions = {
36
+ /**
37
+ * How long to wait for the signal. Past it, `waitFor` throws a
38
+ * `WaitTimeoutError`. Without it, the workflow waits until it is signalled
39
+ * or cancelled.
40
+ */
41
+ timeout?: Duration;
42
+ };
43
+ export type StepBatchOptions = {
44
+ /** A label kept with the batch. Default `workflow:<id>:<key>`. */
45
+ name?: string;
46
+ /**
47
+ * Whether a failed job leaves the rest running. Default `false`: the first
48
+ * dead-lettered job cancels the batch and `step.batch` throws a
49
+ * `StepFailedError`. With `true`, `step.batch` returns the status, failed
50
+ * jobs and all.
51
+ */
52
+ allowFailures?: boolean;
53
+ };
54
+ /** A step that ran out of attempts, or a batch that failed. */
55
+ export declare class StepFailedError extends Error {
56
+ /** The step's key. */
57
+ readonly step: string;
58
+ /** The batch's final status, for a `step.batch` that failed. */
59
+ readonly batch?: BatchStatus;
60
+ constructor(
61
+ /** The step's key. */
62
+ step: string, message: string,
63
+ /** The batch's final status, for a `step.batch` that failed. */
64
+ batch?: BatchStatus);
65
+ }
66
+ /** A `step.waitFor` whose `timeout` passed before the signal arrived. */
67
+ export declare class WaitTimeoutError extends Error {
68
+ readonly step: string;
69
+ constructor(step: string);
70
+ }
71
+ /** Why a step's `ctx.signal` was aborted by its `timeout`. */
72
+ export declare class StepTimeoutError extends Error {
73
+ constructor(step: string, timeoutMs: number);
74
+ }
75
+ /** Why a step's `ctx.signal` was aborted by `Workflow.cancel`. */
76
+ export declare class WorkflowCancelledError extends Error {
77
+ constructor(id: string);
78
+ }
79
+ /**
80
+ * Thrown through the workflow's code when a step cannot finish in this tick
81
+ * (a sleep, a wait, a batch, a retry with a delay), so the tick can end and
82
+ * the workflow resume later. Not exported: code that catches everything
83
+ * should rethrow what it does not know, and the tick treats the workflow as
84
+ * suspended even if this is swallowed.
85
+ */
86
+ export declare class WorkflowSuspended extends Error {
87
+ constructor();
88
+ }
89
+ /** What the runtime gives the steps of one tick. */
90
+ export type StepTick = {
91
+ workflowId: string;
92
+ /** The tick's hold on the workflow; every write is fenced by it. */
93
+ owner: string;
94
+ store: WorkflowStore;
95
+ /** The steps as they were when the tick took the workflow. */
96
+ steps: StepRecord[];
97
+ /** This tick runs `onCancel`, not `run`. */
98
+ cancelling: boolean;
99
+ findBatch(id: string): Promise<BatchStatus | null>;
100
+ buildBatch(job: new () => Job, args: ReadonlyArray<ReadonlyArray<unknown>>, options: {
101
+ name: string;
102
+ allowFailures: boolean;
103
+ }): EnqueueBatch;
104
+ /** Jobs were recorded: wake the queue. */
105
+ scheduled(): void;
106
+ /** How often a running step checks whether the workflow was cancelled. */
107
+ cancelCheckMs: number;
108
+ };
109
+ /** Why a tick stopped where it did. */
110
+ export type Suspension = {
111
+ status: "sleeping" | "waiting";
112
+ /** When a tick is needed to continue; none for a wait on a signal or batch. */
113
+ wakes: number[];
114
+ };
115
+ /**
116
+ * What `run` receives as its first argument. Every method takes a **key**,
117
+ * unique within the workflow and the same on every pass: a step whose key has
118
+ * a stored result returns it without running again, which is how a workflow
119
+ * resumes where it stopped. Code outside the steps runs again on every pass.
120
+ */
121
+ export declare class Step {
122
+ private readonly tick;
123
+ /** The workflow's id. */
124
+ readonly workflowId: string;
125
+ private readonly steps;
126
+ private readonly seen;
127
+ private readonly pending;
128
+ /** @internal Why the tick stopped, once a step suspended it. */
129
+ suspension: Suspension | undefined;
130
+ /** @internal The tick lost its hold on the workflow. */
131
+ lost: boolean;
132
+ /** The workflow was cancelled during this tick. */
133
+ private cancelled;
134
+ /** @internal The step the workflow is on, for its status. */
135
+ current: string | null;
136
+ /** @internal Built by the workflow runtime, once per tick. */
137
+ constructor(tick: StepTick);
138
+ /**
139
+ * Runs `fn` once and stores what it returns, as JSON; on every later pass
140
+ * the stored value is returned without running it again. A throw is retried
141
+ * up to `attempts`, after which the step fails and this throws a
142
+ * `StepFailedError`, which the workflow may catch. The value comes back as
143
+ * JSON makes it, the first time too: a `Date` becomes a string.
144
+ *
145
+ * At least once: a process that dies after `fn` and before its result is
146
+ * stored runs it again. Use `ctx.idempotencyKey` for anything that must not
147
+ * happen twice, or `attempts: 1`.
148
+ */
149
+ run<T>(key: string, fn: (ctx: StepContext) => T | Promise<T>, options?: StepRunOptions): Promise<Awaited<T>>;
150
+ /** Suspends the workflow for `duration`, without holding a process. */
151
+ sleep(key: string, duration: Duration): Promise<void>;
152
+ /**
153
+ * Suspends the workflow until `Workflow.signal(id, key, payload)` and
154
+ * returns the payload. A signal that arrives before the workflow gets here
155
+ * is kept, and returned at once.
156
+ */
157
+ waitFor<T = unknown>(key: string, options?: StepWaitOptions): Promise<T>;
158
+ /**
159
+ * Dispatches `job` once per argument tuple as a batch (`Job.dispatchBatch`)
160
+ * and suspends the workflow until every job has ended; then returns the
161
+ * batch's status. The step is recorded and the batch dispatched in one
162
+ * atomic write, so a crash cannot dispatch it twice.
163
+ */
164
+ batch<J extends Job>(key: string, job: new () => J, args: ReadonlyArray<Readonly<Parameters<J["run"]>>>, options?: StepBatchOptions): Promise<BatchStatus>;
165
+ /**
166
+ * Sets the workflow's `progress`, 0 to 1. Not a step: it writes on every
167
+ * pass that reaches it.
168
+ */
169
+ progress(value: number): Promise<void>;
170
+ /** @internal Waits for every step this tick started, however each ended. */
171
+ settled(): Promise<void>;
172
+ private track;
173
+ private remember;
174
+ /** Once suspended, nothing else may start in this tick. */
175
+ private assertRunning;
176
+ private suspend;
177
+ /**
178
+ * One atomic write, fenced by the tick's hold. A workflow that is being
179
+ * cancelled takes no new work from `run`: the write is skipped and the
180
+ * tick suspended, so `onCancel` runs next.
181
+ */
182
+ private write;
183
+ private record;
184
+ private mismatch;
185
+ private runStep;
186
+ /**
187
+ * One attempt of a `step.run` function, abandoned when its timeout passes
188
+ * or the workflow is cancelled meanwhile.
189
+ */
190
+ private execute;
191
+ private sleepStep;
192
+ private waitStep;
193
+ private batchStep;
194
+ }
195
+ /**
196
+ * A value as stored: JSON, or `null` for `undefined`. Refused past
197
+ * `WORKFLOW_OUTPUT_LIMIT`, and for what JSON cannot carry.
198
+ */
199
+ export declare function encode(value: unknown, what: string): string | null;
200
+ export declare function decode(output: string | null): unknown;
201
+ export declare function describe(error: unknown): string;
202
+ //# sourceMappingURL=Step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Step.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/Step.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import type { Step } from "./Step";
2
+ import type { StepRunStatus, WorkflowRunStatus } from "./WorkflowStore";
3
+ /** The arguments `start` takes: `run`'s, after `step`. */
4
+ export type WorkflowArgs<T extends Workflow> = Parameters<T["run"]> extends [
5
+ any,
6
+ ...infer Rest
7
+ ] ? Rest : never;
8
+ /** What `Workflow.find` resolves to. Times are epoch milliseconds. */
9
+ export type WorkflowStatus = {
10
+ id: string;
11
+ /** The workflow class's `static name`. */
12
+ name: string;
13
+ status: WorkflowRunStatus;
14
+ /** The `run` arguments after `step`. */
15
+ args: unknown[];
16
+ /** The key of the step it is on, or `null`. */
17
+ currentStep: string | null;
18
+ /** 0 to 1, as `step.progress` last set it; 1 once completed. */
19
+ progress: number;
20
+ /** What `run` returned, once completed. */
21
+ result: unknown;
22
+ /** Why it failed; for a cancelled one, why `onCancel` failed. */
23
+ error: string | null;
24
+ /** Every step recorded so far, in the order they were first reached. */
25
+ steps: WorkflowStepStatus[];
26
+ createdAt: number;
27
+ updatedAt: number;
28
+ };
29
+ export type WorkflowStepStatus = {
30
+ key: string;
31
+ status: StepRunStatus;
32
+ /** Attempts started; `step.run` only. */
33
+ attempt: number;
34
+ error: string | null;
35
+ /** The batch a `step.batch` dispatched. */
36
+ batchId: string | null;
37
+ /** The batch's progress, 0 to 1, for a `step.batch`. */
38
+ progress?: number;
39
+ /** When a sleep ends, a wait times out, or a retry is due. */
40
+ wakeAt: number | null;
41
+ startedAt: number | null;
42
+ finishedAt: number | null;
43
+ };
44
+ /**
45
+ * A durable workflow (#846): a `run` method made of steps, which survives
46
+ * restarts and deploys, sleeps and waits without holding a process, and can
47
+ * be cancelled.
48
+ *
49
+ * ```ts
50
+ * export class ImportSiteWorkflow extends Workflow {
51
+ * static name = "ImportSiteWorkflow";
52
+ *
53
+ * async run(step: Step, importId: string) {
54
+ * const pages = await step.run("discover", () => crawl(importId));
55
+ * const chosen = await step.waitFor<string[]>("pages-chosen", { timeout: "7d" });
56
+ * await step.run("charge", (ctx) => charge(importId, ctx.idempotencyKey), { attempts: 1 });
57
+ * const builds = await step.batch("build", BuildPageJob,
58
+ * chosen.map((id) => [id, importId] as const), { allowFailures: true });
59
+ * await step.sleep("settle", "30s");
60
+ * return step.run("report", () => report(importId, builds.failedJobIds));
61
+ * }
62
+ *
63
+ * async onCancel(step: Step, importId: string) {
64
+ * await step.run("refund", () => refundUnbuilt(importId));
65
+ * }
66
+ * }
67
+ * ```
68
+ *
69
+ * ### How it runs
70
+ *
71
+ * Each pass calls `run` from the top, inside an internal queue job (a
72
+ * *tick*), so leases, heartbeats and crash recovery are the queue's. A step
73
+ * whose result is stored returns it without running; the first one without
74
+ * one runs and its result is stored before the code goes on. A step that
75
+ * cannot finish now (a sleep, a wait, a batch, a retry with a delay) ends the
76
+ * pass, and a later tick picks it up. **Code outside the steps runs again on
77
+ * every pass**, so it must be cheap and give the same answer each time: put
78
+ * anything with a side effect, anything slow and anything random or
79
+ * time-dependent inside `step.run`.
80
+ *
81
+ * Step keys are the identity of a step: unique within the workflow, and the
82
+ * same on every pass. Adding or removing a step between deploys is safe; a
83
+ * renamed step runs again.
84
+ */
85
+ export declare class Workflow {
86
+ static name: string;
87
+ /**
88
+ * The workflow's body. Its return value, as JSON, is the workflow's
89
+ * `result`. A throw that escapes it fails the workflow.
90
+ */
91
+ run(_step: Step, ..._args: any[]): unknown;
92
+ /**
93
+ * Runs once after `Workflow.cancel`, in place of `run`, with the same
94
+ * arguments: the place to undo what the steps did. Its steps are memoized
95
+ * like `run`'s (use keys of their own), so it may sleep or retry too.
96
+ */
97
+ onCancel(_step: Step, ..._args: any[]): unknown;
98
+ /**
99
+ * Starts a workflow and resolves to its id. The workflow and its first tick
100
+ * are recorded in one atomic write. Inside an ORM transaction it belongs to
101
+ * the transaction, as a dispatch does: recorded with it, or held until it
102
+ * commits and dropped if it rolls back.
103
+ */
104
+ static start<T extends Workflow>(this: new () => T, ...args: WorkflowArgs<T>): Promise<string>;
105
+ /**
106
+ * Delivers `payload` to the workflow's `step.waitFor(key)`, and resolves to
107
+ * whether it was taken: `false` for an unknown or ended workflow, and for a
108
+ * key that was already signalled. A signal that arrives before the workflow
109
+ * reaches its `waitFor` is kept until it does.
110
+ */
111
+ static signal(id: string, key: string, payload?: unknown): Promise<boolean>;
112
+ /** The workflow's status, or `null` for an unknown id. */
113
+ static find(id: string): Promise<WorkflowStatus | null>;
114
+ /**
115
+ * Cancels a workflow that has not ended, and resolves to whether it did.
116
+ * A running `step.batch` is cancelled with it, a running `step.run` is told
117
+ * through `ctx.signal`, and `onCancel` then runs once.
118
+ */
119
+ static cancel(id: string): Promise<boolean>;
120
+ }
121
+ export type WorkflowClass = (new () => Workflow) & {
122
+ name: string;
123
+ };
124
+ //# sourceMappingURL=Workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Workflow.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/Workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAExE,0DAA0D;AAC1D,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,QAAQ,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS;IAC1E,GAAG;IACH,GAAG,MAAM,IAAI;CACd,GACG,IAAI,GACJ,KAAK,CAAC;AAEV,sEAAsE;AACtE,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,wCAAwC;IACxC,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,MAAM,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wEAAwE;IACxE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,aAAa,CAAC;IACtB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,QAAQ;IACnB,MAAM,CAAC,IAAI,SAAW;IAEtB;;;OAGG;IACH,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO;IAI1C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO;IAI/C;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,EAC7B,IAAI,EAAE,UAAU,CAAC,EACjB,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,MAAM,CAAC;IAIlB;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3E,0DAA0D;IAC1D,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAIvD;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG5C;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,UAAU,QAAQ,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { Job } from "../Job";
2
+ import type { QueueManager } from "../QueueManager";
3
+ import type { WorkflowClass, WorkflowStatus } from "./Workflow";
4
+ import { type WorkflowStore } from "./WorkflowStore";
5
+ /**
6
+ * The queue's half of workflows: the registry of workflow classes, what
7
+ * `Workflow.start`, `signal`, `find` and `cancel` do, and the tick.
8
+ *
9
+ * ### The tick
10
+ *
11
+ * A workflow advances only inside its tick job, which takes the workflow
12
+ * from the store for a lease (the queue's `visibilityTimeout`, renewed while
13
+ * it runs), runs one pass of `run`, and lets go with the outcome written in
14
+ * the same step. Every write of the pass is fenced by that hold, so a tick
15
+ * that lost it (it was too slow and another took over) changes nothing.
16
+ *
17
+ * A tick that finds the workflow held by another is dropped, after marking
18
+ * the workflow so the holder enqueues a fresh tick when it lets go: a signal
19
+ * that lands mid-pass is never lost, and two passes of one workflow never
20
+ * overlap. A tick that failed or died holds the workflow under its job's id,
21
+ * so its own retry takes it straight back.
22
+ */
23
+ export declare class WorkflowRuntime {
24
+ private readonly queue;
25
+ private registry;
26
+ private storeInstance;
27
+ private tickClass;
28
+ private readonly reportedNames;
29
+ constructor(queue: QueueManager);
30
+ /** The workflow classes this process can run, by `static name`. */
31
+ get workflows(): Readonly<Record<string, WorkflowClass>>;
32
+ /** Replaces the registry. The first class to claim a name wins. */
33
+ use(workflows: readonly WorkflowClass[]): void;
34
+ /** The internal job a workflow's passes run in, one class per manager. */
35
+ get tickJob(): new () => Job;
36
+ get store(): WorkflowStore;
37
+ start(workflow: WorkflowClass, args: unknown[]): Promise<string>;
38
+ signal(id: string, key: string, payload?: unknown): Promise<boolean>;
39
+ cancel(id: string): Promise<boolean>;
40
+ find(id: string): Promise<WorkflowStatus | null>;
41
+ /** One pass of the workflow `id`, run by its tick job. */
42
+ tick(id: string, job: Job): Promise<void>;
43
+ /** The tick's last write: the pass's outcome, and letting go. */
44
+ private finish;
45
+ /**
46
+ * A tick for a workflow this process has no class for. During a
47
+ * blue/green ramp that is usually one only the other release has, so on a
48
+ * shared driver it goes back for another replica until `unknownJobGrace`
49
+ * has passed since the workflow started; then it fails.
50
+ */
51
+ private unknown;
52
+ /**
53
+ * The tick job ran out of attempts, which only a store that stayed
54
+ * unreachable causes. Fails the workflow if it still can, so it does not
55
+ * sit in `running` with nothing left to advance it.
56
+ */
57
+ /** @internal */
58
+ tickDeadLettered(id: string, error: Error): void;
59
+ }
60
+ //# sourceMappingURL=WorkflowRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowRuntime.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/WorkflowRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAQpD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAYzB;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,eAAe;IAMd,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;gBAEtB,KAAK,EAAE,YAAY;IAEhD,mEAAmE;IACnE,IAAI,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAEvD;IAED,mEAAmE;IACnE,GAAG,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE;IAoBvC,0EAA0E;IAC1E,IAAI,OAAO,IAAI,UAAU,GAAG,CAG3B;IAED,IAAI,KAAK,IAAI,aAAa,CAYzB;IAED,KAAK,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAoC1D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAuCpE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBpC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAuCtD,0DAA0D;IACpD,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA0G/C,iEAAiE;IACjE,OAAO,CAAC,MAAM;IA4Dd;;;;;OAKG;YACW,OAAO;IAgCrB;;;;OAIG;IACH,gBAAgB;IAChB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAiB1C"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Where workflows are kept (#846), and the one atomic operation everything a
3
+ * workflow does is built from.
4
+ *
5
+ * A store belongs to a queue driver (`QueueDriver.workflowStore`), because a
6
+ * workflow's writes and the jobs they schedule must commit together: a step
7
+ * that sleeps records the sleep and enqueues the tick that wakes it in one
8
+ * step, and `step.batch` records the step and dispatches the batch in one
9
+ * step, so a crash between the two can neither lose the wake-up nor fan out
10
+ * twice. The memory driver does each change synchronously; the database driver
11
+ * does it in a transaction that locks the workflow's row first.
12
+ *
13
+ * A store only keeps records. What a change means (when a step is done, when
14
+ * a workflow sleeps) is decided by the runtime, in the `decide` callback of
15
+ * `update`, while the store holds the workflow exclusively.
16
+ */
17
+ import type { EnqueueBatch } from "../QueueDriver";
18
+ /** The registered name the internal tick job runs under. */
19
+ export declare const WORKFLOW_TICK_JOB = "gemi.WorkflowTick";
20
+ /**
21
+ * The most a step's output, a signal's payload or a workflow's result may be,
22
+ * as JSON, in bytes. Store an id for anything larger.
23
+ */
24
+ export declare const WORKFLOW_OUTPUT_LIMIT: number;
25
+ /**
26
+ * Where a workflow stands.
27
+ *
28
+ * - `running`: a tick is running it, or one is queued to.
29
+ * - `sleeping`: waiting for a `step.sleep` or a step's retry backoff.
30
+ * - `waiting`: waiting for a signal (`step.waitFor`) or a batch (`step.batch`).
31
+ * - `cancelling`: `cancel` was accepted, and `onCancel` has not finished yet.
32
+ * - `completed`, `failed`, `cancelled`: final.
33
+ */
34
+ export type WorkflowRunStatus = "running" | "sleeping" | "waiting" | "completed" | "failed" | "cancelling" | "cancelled";
35
+ /**
36
+ * Where one step stands. `signalled` is a signal that arrived before its
37
+ * `step.waitFor`, kept until the workflow gets there.
38
+ */
39
+ export type StepRunStatus = "running" | "retrying" | "completed" | "failed" | "sleeping" | "waiting" | "signalled" | "timed_out" | "batching";
40
+ /** A workflow's row. Times are epoch milliseconds. */
41
+ export type WorkflowRecord = {
42
+ id: string;
43
+ /** The workflow class's `static name`. */
44
+ name: string;
45
+ /** The `run` arguments after `step`, as JSON. */
46
+ args: string;
47
+ status: WorkflowRunStatus;
48
+ /** The key of the step it is on, or `null`. */
49
+ currentStep: string | null;
50
+ /** 0 to 1, as `step.progress` last set it; 1 once completed. */
51
+ progress: number;
52
+ /** What `run` returned, as JSON, once completed. `null` for `undefined`. */
53
+ result: string | null;
54
+ error: string | null;
55
+ /** When the next tick that was scheduled for a wake-up is due, or `null`. */
56
+ wakeAt: number | null;
57
+ /** The tick holding the workflow, and until when (on the store's clock). */
58
+ lockedBy: string | null;
59
+ lockedUntil: number | null;
60
+ /** Another tick arrived while one held the workflow; see `update`'s `unlock`. */
61
+ retick: boolean;
62
+ createdAt: number;
63
+ updatedAt: number;
64
+ };
65
+ /** A step's row, unique per workflow and key. */
66
+ export type StepRecord = {
67
+ workflowId: string;
68
+ key: string;
69
+ status: StepRunStatus;
70
+ /** Attempts started, counting from 1. */
71
+ attempt: number;
72
+ /** The step's result or the signal's payload, as JSON. `null` for `undefined`. */
73
+ output: string | null;
74
+ error: string | null;
75
+ /** The batch a `step.batch` dispatched. */
76
+ batchId: string | null;
77
+ /** When a sleep ends, a wait times out, or a retry is due. */
78
+ wakeAt: number | null;
79
+ startedAt: number | null;
80
+ finishedAt: number | null;
81
+ createdAt: number;
82
+ updatedAt: number;
83
+ };
84
+ /** A workflow and its steps, in the order the steps were first recorded. */
85
+ export type WorkflowState = {
86
+ workflow: WorkflowRecord;
87
+ steps: StepRecord[];
88
+ };
89
+ export type AcquireResult = {
90
+ kind: "missing";
91
+ }
92
+ /** Another tick holds it; `retick` is set, so that tick runs it again. */
93
+ | {
94
+ kind: "busy";
95
+ } | ({
96
+ kind: "acquired";
97
+ } & WorkflowState);
98
+ /** What `update`'s `decide` sees, read while the workflow is held. */
99
+ export type WorkflowSnapshot = {
100
+ workflow: WorkflowRecord;
101
+ /** The step `key` names, or `null` when there is none (or no key was given). */
102
+ step: StepRecord | null;
103
+ /** Every step, when `allSteps` was asked for; otherwise empty. */
104
+ steps: StepRecord[];
105
+ /** This process's clock, for the wake-up times the runtime computes. */
106
+ now: number;
107
+ };
108
+ /** What `decide` wants written, all in the same atomic step. */
109
+ export type WorkflowChange<T> = {
110
+ /** What `update` resolves to. */
111
+ result: T;
112
+ workflow?: Partial<Pick<WorkflowRecord, "status" | "currentStep" | "progress" | "result" | "error" | "wakeAt">>;
113
+ /** The step's new row: inserted, or replacing the one under its key. */
114
+ step?: StepRecord;
115
+ /** A batch to dispatch, as `QueueDriver.enqueueBatch` would. */
116
+ batch?: EnqueueBatch;
117
+ /** Batches to cancel, as `QueueDriver.cancelBatch` would. */
118
+ cancelBatches?: string[];
119
+ /** Enqueue a tick for this workflow, claimable after `delayMs`. */
120
+ tick?: {
121
+ delayMs: number;
122
+ };
123
+ /**
124
+ * Release the tick's hold on the workflow. When another tick arrived while
125
+ * it was held (`retick`), a new tick is enqueued in the same step, so a
126
+ * signal that landed mid-tick is never lost.
127
+ */
128
+ unlock?: boolean;
129
+ };
130
+ /**
131
+ * Whether two holds are attempts of the same tick job. A tick holds the
132
+ * workflow as `<tick job id>:<attempt>`, so a retry of a tick that failed or
133
+ * died takes the workflow straight back instead of waiting out the lease,
134
+ * and the earlier attempt's writes are refused from then on.
135
+ */
136
+ export declare function sameTick(a: string, b: string): boolean;
137
+ export declare class WorkflowLeaseLostError extends Error {
138
+ constructor(id: string);
139
+ }
140
+ export interface WorkflowStore {
141
+ /**
142
+ * Records a new workflow and enqueues its first tick, in one atomic step.
143
+ * Like `QueueDriver.enqueue`, a store that answers `joinsTransaction`
144
+ * writes on the caller's ORM transaction.
145
+ */
146
+ create(workflow: {
147
+ id: string;
148
+ name: string;
149
+ args: string;
150
+ }): Promise<void>;
151
+ /** Whether `create` would write on the caller's open ORM transaction. */
152
+ joinsTransaction?(): boolean;
153
+ /** The workflow, and its steps unless `steps: false`, or `null`. */
154
+ find(id: string, options?: {
155
+ steps?: boolean;
156
+ }): Promise<WorkflowState | null>;
157
+ /**
158
+ * Takes the workflow for one tick, for `leaseMs` on the store's clock, and
159
+ * returns its state. A workflow another tick holds under a live lease is
160
+ * `busy`, and is marked to be ticked again when that tick lets go; one held
161
+ * by an earlier attempt of the same tick job (see `sameTick`) is taken over.
162
+ */
163
+ acquire(id: string, owner: string, leaseMs: number): Promise<AcquireResult>;
164
+ /** Extends the tick's lease, and resolves to whether it still held it. */
165
+ renew(id: string, owner: string, leaseMs: number): Promise<boolean>;
166
+ /**
167
+ * Reads the workflow (and the step `key`, or every step with `allSteps`)
168
+ * while holding it exclusively, calls `decide`, and writes what it returns,
169
+ * all in one atomic step. With `owner`, the write is refused with a
170
+ * `WorkflowLeaseLostError` unless that tick still holds the workflow.
171
+ * Resolves to `undefined` for an unknown workflow.
172
+ */
173
+ update<T>(id: string, options: {
174
+ owner?: string;
175
+ key?: string;
176
+ allSteps?: boolean;
177
+ }, decide: (snapshot: WorkflowSnapshot) => WorkflowChange<T>): Promise<T | undefined>;
178
+ /**
179
+ * Deletes workflows that ended (completed, failed or cancelled) more than
180
+ * `olderThanMs` ago, with their steps, and resolves to how many.
181
+ */
182
+ prune?(olderThanMs: number): Promise<number>;
183
+ }
184
+ //# sourceMappingURL=WorkflowStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowStore.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/WorkflowStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A length of time: milliseconds as a number, or a number and a unit, such as
3
+ * `"500ms"`, `"30s"`, `"5m"`, `"2h"`, `"7d"` or `"1w"`.
4
+ */
5
+ export type Duration = number | `${number}${"ms" | "s" | "m" | "h" | "d" | "w"}`;
6
+ /** A `Duration` in milliseconds. Throws for anything else, on the caller's stack. */
7
+ export declare function toMilliseconds(duration: Duration): number;
8
+ //# sourceMappingURL=duration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/duration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAWjF,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAezD"}
@@ -0,0 +1,30 @@
1
+ import type { QueueDriver } from "../QueueDriver";
2
+ /**
3
+ * What workflows promise on every driver that keeps them, as a suite a
4
+ * driver's test file runs against itself:
5
+ *
6
+ * workflowContract("MemoryQueueDriver", async () => {
7
+ * const driver = new MemoryQueueDriver();
8
+ * return { driver: () => driver, dispose: async () => {} };
9
+ * });
10
+ *
11
+ * `storage` makes fresh, empty storage for one test. Its `driver()` returns
12
+ * a driver over it, a new one per call where the storage is shared (a
13
+ * database), so that two managers on two drivers are two processes. The
14
+ * workflows run end to end, through `QueueManager`s that claim the ticks.
15
+ *
16
+ * Not a `*.test.ts` file, so vitest never runs it on its own.
17
+ */
18
+ export declare function workflowContract(name: string, storage: () => Promise<{
19
+ driver(): QueueDriver;
20
+ dispose(): Promise<void>;
21
+ }>, features?: {
22
+ /**
23
+ * Runs the test with two managers ticking the same workflows. Off for
24
+ * SQLite files: two clients in one thread are not two processes there,
25
+ * because SQLite's busy handler sleeps the very thread the lock holder
26
+ * needs to finish its transaction.
27
+ */
28
+ concurrentWorkers?: boolean;
29
+ }): void;
30
+ //# sourceMappingURL=workflowContract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflowContract.d.ts","sourceRoot":"","sources":["../../../../services/queue/workflow/workflowContract.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMlD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,OAAO,CAAC;IAAE,MAAM,IAAI,WAAW,CAAC;IAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,EAC3E,QAAQ,GAAE;IACR;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACC,QAogBhC"}
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import"../chunk-dcgvq79a.js";import M from"path";import{writeFileSync as Q}from"fs";var L=new Set(["FILE","REDIRECT"]);function H(j){return j.run(()=>{let x=[];for(let{group:z,view:D}of j.domains().viewGroups())for(let[G,B]of Object.entries(D.flatViewRoutes)){let C=D.routeManifest[G]??B.segments.map((K)=>K.viewPath);if(C.length===0||L.has(C.at(-1)))continue;x.push({path:G,group:z,views:C,...B.static?{static:B.static.layout?{layout:B.static.layout}:{}}:{}})}return x})}var J=process.argv[2];async function U(){if(!J)throw Error("usage: route-table <out.json>");let j=M.resolve(process.cwd(),"app/kernel/Kernel.ts"),x=await import(j);if(typeof x.default!=="function")throw Error(`${j} has no default export (the Kernel subclass).`);let z=new x.default;z.boot();try{Q(J,JSON.stringify(H(z)))}finally{z.destroy()}}U().then(()=>process.exit(0),(j)=>{console.error(j?.stack??String(j)),process.exit(1)});
2
+ import"../chunk-hm9cjxy2.js";import M from"path";import{writeFileSync as Q}from"fs";var L=new Set(["FILE","REDIRECT"]);function H(j){return j.run(()=>{let x=[];for(let{group:z,view:D}of j.domains().viewGroups())for(let[G,B]of Object.entries(D.flatViewRoutes)){let C=D.routeManifest[G]??B.segments.map((K)=>K.viewPath);if(C.length===0||L.has(C.at(-1)))continue;x.push({path:G,group:z,views:C,...B.static?{static:B.static.layout?{layout:B.static.layout}:{}}:{}})}return x})}var J=process.argv[2];async function U(){if(!J)throw Error("usage: route-table <out.json>");let j=M.resolve(process.cwd(),"app/kernel/Kernel.ts"),x=await import(j);if(typeof x.default!=="function")throw Error(`${j} has no default export (the Kernel subclass).`);let z=new x.default;z.boot();try{Q(J,JSON.stringify(H(z)))}finally{z.destroy()}}U().then(()=>process.exit(0),(j)=>{console.error(j?.stack??String(j)),process.exit(1)});
3
3
 
4
4
  //# debugId=2C354352EBF6475164756E2164756E21