effect-mq 0.4.2 → 0.6.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 (64) hide show
  1. package/README.md +85 -17
  2. package/dist/Flow.d.ts +381 -0
  3. package/dist/Flow.d.ts.map +1 -0
  4. package/dist/Flow.js +340 -0
  5. package/dist/Flow.js.map +1 -0
  6. package/dist/Job.d.ts +37 -6
  7. package/dist/Job.d.ts.map +1 -1
  8. package/dist/Job.js +17 -2
  9. package/dist/Job.js.map +1 -1
  10. package/dist/JobSchedules.d.ts +112 -0
  11. package/dist/JobSchedules.d.ts.map +1 -0
  12. package/dist/JobSchedules.js +106 -0
  13. package/dist/JobSchedules.js.map +1 -0
  14. package/dist/JobStore.d.ts +320 -10
  15. package/dist/JobStore.d.ts.map +1 -1
  16. package/dist/JobStore.js.map +1 -1
  17. package/dist/MemoryJobStore.d.ts.map +1 -1
  18. package/dist/MemoryJobStore.js +336 -8
  19. package/dist/MemoryJobStore.js.map +1 -1
  20. package/dist/Metrics.d.ts +31 -0
  21. package/dist/Metrics.d.ts.map +1 -1
  22. package/dist/Metrics.js +39 -0
  23. package/dist/Metrics.js.map +1 -1
  24. package/dist/Worker.d.ts +120 -11
  25. package/dist/Worker.d.ts.map +1 -1
  26. package/dist/Worker.js +452 -26
  27. package/dist/Worker.js.map +1 -1
  28. package/dist/drizzle-postgres/DrizzleJobStore.d.ts +19 -1
  29. package/dist/drizzle-postgres/DrizzleJobStore.d.ts.map +1 -1
  30. package/dist/drizzle-postgres/DrizzleJobStore.js +662 -81
  31. package/dist/drizzle-postgres/DrizzleJobStore.js.map +1 -1
  32. package/dist/drizzle-postgres/schema.d.ts +310 -3
  33. package/dist/drizzle-postgres/schema.d.ts.map +1 -1
  34. package/dist/drizzle-postgres/schema.js +68 -1
  35. package/dist/drizzle-postgres/schema.js.map +1 -1
  36. package/dist/index.d.ts +14 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +14 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/redis/RedisJobStore.d.ts.map +1 -1
  41. package/dist/redis/RedisJobStore.js +221 -19
  42. package/dist/redis/RedisJobStore.js.map +1 -1
  43. package/dist/redis/scripts.d.ts +118 -11
  44. package/dist/redis/scripts.d.ts.map +1 -1
  45. package/dist/redis/scripts.js +497 -28
  46. package/dist/redis/scripts.js.map +1 -1
  47. package/dist/testing/conformance.d.ts +6 -0
  48. package/dist/testing/conformance.d.ts.map +1 -1
  49. package/dist/testing/conformance.js +765 -1
  50. package/dist/testing/conformance.js.map +1 -1
  51. package/package.json +1 -1
  52. package/src/Flow.ts +778 -0
  53. package/src/Job.ts +42 -11
  54. package/src/JobSchedules.ts +223 -0
  55. package/src/JobStore.ts +347 -9
  56. package/src/MemoryJobStore.ts +372 -8
  57. package/src/Metrics.ts +43 -0
  58. package/src/Worker.ts +726 -37
  59. package/src/drizzle-postgres/DrizzleJobStore.ts +827 -82
  60. package/src/drizzle-postgres/schema.ts +94 -0
  61. package/src/index.ts +16 -0
  62. package/src/redis/RedisJobStore.ts +291 -8
  63. package/src/redis/scripts.ts +529 -26
  64. package/src/testing/conformance.ts +989 -1
package/README.md CHANGED
@@ -51,7 +51,7 @@ const producer = Effect.gen(function*() {
51
51
  // 3. Run. Workers are layers — deploy them in the same process or across
52
52
  // machines against shared storage.
53
53
  const RunnerLive = SendEmail.toLayer(
54
- (payload, ctx) => Effect.succeed(`message-${ctx.jobId}`),
54
+ (payload) => Effect.map(Worker.CurrentJob, ({ jobId }) => `message-${jobId}`),
55
55
  { concurrency: 5 }
56
56
  ).pipe(
57
57
  Layer.provideMerge(Worker.layer()),
@@ -144,6 +144,49 @@ occurrences, missed slots collapse into one run (the next sweep enqueues the
144
144
  overdue slot once, then advances past `now`). Options mirror `enqueue`:
145
145
  `metadata`, `priority`, `attempts`, `backoff`, `keep`, `timeout`.
146
146
 
147
+ ## Parent-child flows
148
+
149
+ A flow fans a parent job out into N children, parks the parent until every
150
+ child settles, then resumes it with their typed results. Children can live
151
+ on a **different store** than the parent (a cron parent in Postgres fanning
152
+ out 10k idempotent sends into Redis, collecting the outcomes back):
153
+
154
+ ```ts
155
+ import { Flow } from "effect-mq"
156
+
157
+ const DigestFlow = Flow.make("daily-digest", {
158
+ parent: SendDigest, // Postgres
159
+ children: [SendEmail], // Redis
160
+ onChildFailure: "continue" // or "fail": first failure settles the flow
161
+ })
162
+
163
+ // The parent worker runs two phases (requires parent AND child stores):
164
+ const DigestWorker = DigestFlow.toLayer({
165
+ fanOut: (payload) =>
166
+ Effect.map(Users.active, (users) =>
167
+ Flow.children(SendEmail, users.map((user) => ({
168
+ key: user.id, // unique in the flow = idempotency
169
+ payload: { userId: user.id }
170
+ })))),
171
+ collect: (payload, results) =>
172
+ Effect.succeed({ sent: results.counts.completed, failed: results.counts.failed })
173
+ })
174
+
175
+ // Workers that run the children declare the flow so their relay can push
176
+ // results to the parent store the moment each child acks:
177
+ Worker.layer({ store: EmailStore, flows: [DigestFlow] })
178
+ ```
179
+
180
+ The parent's store owns the flow (manifest, per-child results, outcome
181
+ counters), so "settle exactly once" is single-store atomic. Cross-store,
182
+ every terminal child transition appends its report to the child store's
183
+ **outbox** in the same atomic operation; worker relays push those in
184
+ batches (children keep completing through parent-store outages) and a
185
+ reconciliation sweeper repairs anything the push path misses, from storage
186
+ alone. Flows nest (a child can be another flow's parent), and `collect`
187
+ reads results as plain `counts`, materialized buckets, or a paged `Stream`.
188
+ Docs: [Parent-child flows](https://www.effect-mq.com/guide/flows).
189
+
147
190
  ## Timeouts, cancellation, and unrecoverable errors
148
191
 
149
192
  Because handlers are Effect fibers, the runtime can *actually stop them* —
@@ -357,16 +400,26 @@ migrations** — no library-run DDL, no parallel migration system:
357
400
 
358
401
  ```ts
359
402
  // db/schema.ts
360
- import { mqDedupe, mqJobAttempts, mqJobs, mqQueueControl, mqSchedules } from "effect-mq/drizzle-postgres"
403
+ import {
404
+ mqDedupe,
405
+ mqFlowChildren,
406
+ mqFlowOutbox,
407
+ mqJobAttempts,
408
+ mqJobs,
409
+ mqQueueControl,
410
+ mqSchedules
411
+ } from "effect-mq/drizzle-postgres"
361
412
 
362
413
  // The `name` column is typed to your job tags (derived, not hand-written):
363
414
  type JobNames = typeof GenerateInvoice._tag | typeof SendEmail._tag
364
415
 
365
- export const jobs = mqJobs<JobNames>() // default table: effect_mq_jobs
366
- export const jobAttempts = mqJobAttempts(jobs) // default: effect_mq_job_attempts
367
- export const jobSchedules = mqSchedules() // default: effect_mq_schedules
368
- export const jobQueues = mqQueueControl() // default: effect_mq_queue_control
369
- export const jobDedupe = mqDedupe() // default: effect_mq_dedupe
416
+ export const jobs = mqJobs<JobNames>() // default table: effect_mq_jobs
417
+ export const jobAttempts = mqJobAttempts(jobs) // default: effect_mq_job_attempts
418
+ export const jobSchedules = mqSchedules() // default: effect_mq_schedules
419
+ export const jobQueues = mqQueueControl() // default: effect_mq_queue_control
420
+ export const jobDedupe = mqDedupe() // default: effect_mq_dedupe
421
+ export const jobFlowChildren = mqFlowChildren() // default: effect_mq_flow_children
422
+ export const jobFlowOutbox = mqFlowOutbox() // default: effect_mq_flow_outbox
370
423
  ```
371
424
 
372
425
  Need more indexes (the built-ins cover claiming, listing, metadata
@@ -390,7 +443,7 @@ table; at enqueue the store fills each extended column from the job's
390
443
  `metadata: (payload) => ...` is your creation-time hook), NULL when absent:
391
444
 
392
445
  ```ts
393
- class SyncBenefits extends Job.make("sync-benefits", {
446
+ class SyncPayments extends Job.make("sync-payments", {
394
447
  payload: { companyId: Schema.String, objectId: Schema.String },
395
448
  metadata: ({ companyId, objectId }) => ({ companyId, objectId })
396
449
  }) {}
@@ -427,14 +480,24 @@ When a future effect-mq version changes the layout, the factory changes and
427
480
  import { DrizzleJobStore } from "effect-mq/drizzle-postgres"
428
481
  import { PgClient } from "@effect/sql-pg"
429
482
  import { Layer, Redacted } from "effect"
430
- import { jobAttempts, jobDedupe, jobQueues, jobs, jobSchedules } from "./db/schema.ts"
483
+ import {
484
+ jobAttempts,
485
+ jobDedupe,
486
+ jobFlowChildren,
487
+ jobFlowOutbox,
488
+ jobQueues,
489
+ jobs,
490
+ jobSchedules
491
+ } from "./db/schema.ts"
431
492
 
432
493
  const JobStoreLive = DrizzleJobStore.layer({
433
494
  jobs,
434
495
  attempts: jobAttempts,
435
496
  schedules: jobSchedules,
436
497
  queues: jobQueues,
437
- dedupe: jobDedupe
498
+ dedupe: jobDedupe,
499
+ flowChildren: jobFlowChildren,
500
+ flowOutbox: jobFlowOutbox
438
501
  }).pipe(
439
502
  Layer.provide(PgClient.layer({ url: Redacted.make(process.env.DATABASE_URL!) }))
440
503
  )
@@ -593,6 +656,9 @@ ledger), `retry`, `cancel`, `cancelByKey` (by dedup key, idempotent),
593
656
  | `queueMetricsInterval` | off | sample `store.counts()` per queue into the depth gauge |
594
657
  | `handlerSpanName` | `` `${name}.run` `` | name of the span wrapping each handler run |
595
658
  | `traceLinking` | `auto` | parent for immediate jobs, causal link for delayed ones (`parent`/`link`/`none` force a mode) |
659
+ | `onJobFailure` | — | callback after each failed run is acked; runs isolated |
660
+ | `flows` | — | flows whose children this worker runs (lets its relay push results) |
661
+ | `flowSweepInterval` | 30s | flow sweeper cadence + the relay's fallback drain cadence |
596
662
  | `id` | random | identifier used in lock tokens |
597
663
 
598
664
  **Store construction** — every driver accepts `idGenerator`, `historyTtl`,
@@ -629,12 +695,14 @@ plain Effect, so it works with any test runner.
629
695
 
630
696
  ## Writing a storage driver
631
697
 
632
- Implement the `JobStore` service (one atomic seam: `enqueue`, `claim`, `ack`,
633
- `release`, `extendLocks`, `recoverStalled`, `awaitWake`, `getJob`,
634
- `getAttempts`, `list`, `retry`, `counts`, `remove`, `cancel`, `promote`,
635
- `pause`/`resume`/`pausedQueues`, `cancelByDedupe`, and the schedule ops
636
- `upsertSchedule`/`removeSchedule`/`listSchedules`/`dueSchedules`/`advanceSchedule`)
637
- and run the conformance suite against it:
698
+ Implement the `JobStore` service (one atomic seam: `enqueue`/`enqueueMany`,
699
+ `claim`, `ack`, `release`, `extendLocks`, `recoverStalled`, `awaitWake`,
700
+ `getJob`, `getAttempts`, `list`, `retry`, `counts`, `remove`, `cancel`,
701
+ `promote`, `pause`/`resume`/`pausedQueues`, `cancelByDedupe`, the schedule
702
+ ops `upsertSchedule`/`removeSchedule`/`listSchedules`/`dueSchedules`/
703
+ `tickSchedule`/`advanceSchedule`, and the flow ops `recordChildResults`/
704
+ `listChildResults`/`flowSweepWork`/`markChildrenCascaded`/`peekOutbox`/
705
+ `deleteOutbox`) and run the conformance suite against it:
638
706
 
639
707
  ```ts
640
708
  import { jobStoreConformance } from "effect-mq/testing"
@@ -652,7 +720,7 @@ suite in this repo runs the same conformance tests against a real database.
652
720
 
653
721
  Next up: drizzle schema customization (column renames, native id and
654
722
  timestamp column types, a typed queue registry), a cross-process event
655
- stream, and parent-child fan-out. Full prioritized list:
723
+ stream, and global queue concurrency/rate limits. Full prioritized list:
656
724
  [ROADMAP.md](https://github.com/TeamWarp/effect-mq/blob/main/ROADMAP.md);
657
725
  release history:
658
726
  [CHANGELOG.md](https://github.com/TeamWarp/effect-mq/blob/main/CHANGELOG.md).
package/dist/Flow.d.ts ADDED
@@ -0,0 +1,381 @@
1
+ /**
2
+ * Cross-store parent-child flows.
3
+ *
4
+ * A flow's PARENT job fans out N child jobs, parks in `waiting-children`
5
+ * until every child settles, then resumes with their typed results. The
6
+ * children may live on a **different store** than the parent — a
7
+ * cron-scheduled parent in Postgres can fan out thousands of idempotent
8
+ * sends into Redis and collect the outcomes back in Postgres.
9
+ *
10
+ * ```ts
11
+ * const DigestFlow = Flow.make("daily-digest", {
12
+ * parent: SendDigest, // a Job bound to the Postgres store
13
+ * children: [SendEmail], // Jobs, each bound to their own store
14
+ * onChildFailure: "continue" // default; "fail" settles on first failure
15
+ * })
16
+ *
17
+ * // the parent worker runs both phases (requires the parent AND child stores)
18
+ * const DigestWorker = DigestFlow.toLayer({
19
+ * fanOut: (payload) =>
20
+ * Effect.gen(function*() {
21
+ * const users = yield* Users.active
22
+ * return Flow.children(SendEmail, users.map((user) => ({
23
+ * key: user.id,
24
+ * payload: { userId: user.id }
25
+ * })))
26
+ * }),
27
+ * collect: (payload, results) =>
28
+ * Effect.succeed({ sent: results.counts.completed, failed: results.counts.failed })
29
+ * // or: yield* results.all (materialized buckets), results.stream (paged)
30
+ * })
31
+ *
32
+ * // workers that run the CHILDREN list the flow so results push instantly:
33
+ * // Worker.layer({ store: EmailStore, flows: [DigestFlow] })
34
+ * ```
35
+ *
36
+ * Architecture (see `designs/parent-child-flows.md`): the parent's store
37
+ * owns the flow — child manifest, per-child results, outcome counters — so
38
+ * "the flow settles exactly once" is single-store atomic. Cross-store needs
39
+ * only two at-least-once idempotent mechanisms: every terminal child
40
+ * transition atomically appends its report to the CHILD store's outbox,
41
+ * which worker relays *push* into the parent store in batches (children
42
+ * keep completing even while the parent store is down); and the parent
43
+ * worker's flow sweeper *reconciles* from child-store state (repairs
44
+ * everything the push path can miss: crashes mid-enqueue, dropped outbox
45
+ * entries, children terminal on stores no relay reaches).
46
+ *
47
+ * Flows nest: a child may itself be another flow's parent, reporting upward
48
+ * through the same machinery when it settles. Depth is capped (8) so a
49
+ * cyclic definition surfaces as an unrecoverable failure instead of an
50
+ * unbounded chain.
51
+ *
52
+ * Flow children bypass the child definition's `idempotencyKey`/`dedupe` —
53
+ * the child `key` (unique within the flow) IS the idempotency mechanism,
54
+ * carried in the deterministic job id. Handlers should be idempotent, as
55
+ * everywhere under at-least-once.
56
+ *
57
+ * @since 0.6.0
58
+ */
59
+ import { Cause, Context, Effect, Layer, Schema, Stream } from "effect";
60
+ import { type AnyStructSchema, type JobOptions, type ResolvedDefaults } from "./Job.ts";
61
+ import { JobId, type QueueName, type Service as StoreService } from "./JobStore.ts";
62
+ import { type CurrentJob, type RegisterOptions, Worker } from "./Worker.ts";
63
+ /**
64
+ * The structural view of a `Job.make` class a flow needs from its members.
65
+ * Contravariant callback members are typed with `never` parameters so every
66
+ * concrete job satisfies the constraint; the runtime only ever passes a
67
+ * job's own payload back into them.
68
+ *
69
+ * @since 0.6.0
70
+ */
71
+ export interface MemberJob {
72
+ readonly _tag: string;
73
+ readonly queue: QueueName;
74
+ readonly store: Context.Key<any, StoreService>;
75
+ readonly payloadSchema: AnyStructSchema;
76
+ readonly payloadJsonSchema: Schema.Top;
77
+ readonly successSchema: Schema.Top;
78
+ readonly errorSchema: Schema.Top;
79
+ readonly exitSchema: Schema.Top;
80
+ readonly defaults: ResolvedDefaults;
81
+ readonly metadata: ((payload: never) => Readonly<Record<string, string>>) | undefined;
82
+ readonly retryable: ((error: never) => boolean) | undefined;
83
+ }
84
+ /**
85
+ * The structural view of the parent job: a `MemberJob` plus the producer
86
+ * surface the flow delegates (`Flow.enqueue` IS the parent's `enqueue`).
87
+ *
88
+ * @since 0.6.0
89
+ */
90
+ export interface ParentJob extends MemberJob {
91
+ readonly enqueue: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
92
+ readonly enqueueMany: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
93
+ readonly execute: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
94
+ readonly poll: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
95
+ readonly attempts: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
96
+ readonly awaitResult: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
97
+ readonly retry: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
98
+ readonly cancel: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
99
+ readonly promote: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
100
+ readonly schedule: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
101
+ readonly unschedule: (...args: ReadonlyArray<never>) => Effect.Effect<any, any, any>;
102
+ }
103
+ type NameOf<J> = J extends {
104
+ readonly _tag: infer N extends string;
105
+ } ? N : never;
106
+ type PayloadMakeIn<J> = J extends {
107
+ readonly payloadSchema: infer P extends AnyStructSchema;
108
+ } ? P["~type.make.in"] : never;
109
+ type PayloadType<J> = J extends {
110
+ readonly payloadSchema: infer P extends AnyStructSchema;
111
+ } ? P["Type"] : never;
112
+ type PayloadEncodingServices<J> = J extends {
113
+ readonly payloadSchema: infer P extends AnyStructSchema;
114
+ } ? P["EncodingServices"] : never;
115
+ type SuccessValue<J> = J extends {
116
+ readonly successSchema: infer S extends Schema.Top;
117
+ } ? S["Type"] : never;
118
+ type SuccessDecodingServices<J> = J extends {
119
+ readonly successSchema: infer S extends Schema.Top;
120
+ } ? S["DecodingServices"] : never;
121
+ type SuccessEncodingServices<J> = J extends {
122
+ readonly successSchema: infer S extends Schema.Top;
123
+ } ? S["EncodingServices"] : never;
124
+ type ErrorValue<J> = J extends {
125
+ readonly errorSchema: infer E extends Schema.Top;
126
+ } ? E["Type"] : never;
127
+ type ErrorDecodingServices<J> = J extends {
128
+ readonly errorSchema: infer E extends Schema.Top;
129
+ } ? E["DecodingServices"] : never;
130
+ type ErrorEncodingServices<J> = J extends {
131
+ readonly errorSchema: infer E extends Schema.Top;
132
+ } ? E["EncodingServices"] : never;
133
+ type PayloadDecodingServices<J> = J extends {
134
+ readonly payloadSchema: infer P extends AnyStructSchema;
135
+ } ? P["DecodingServices"] : never;
136
+ /**
137
+ * The StoreIds of a flow's members — what `toLayer` requires so the parent
138
+ * worker is guaranteed able to reconcile and cascade into every child store.
139
+ *
140
+ * @since 0.6.0
141
+ */
142
+ export type MemberStores<J> = J extends {
143
+ readonly store: Context.Key<infer Id, StoreService>;
144
+ } ? Id : never;
145
+ /**
146
+ * Per-child options accepted by `Flow.children` items — the shared
147
+ * `JobOptions` minus `delay` (flow children run immediately), plus
148
+ * `metadata` merged over the child definition's callback.
149
+ *
150
+ * @since 0.6.0
151
+ */
152
+ export type ChildOptions = Omit<JobOptions, "delay"> & {
153
+ readonly metadata?: Readonly<Record<string, string>> | undefined;
154
+ };
155
+ /**
156
+ * One child to fan out: its flow-unique `key` (the idempotency mechanism —
157
+ * re-runs of `fanOut` re-produce the same child, never a second one), the
158
+ * payload, and optional per-child options.
159
+ *
160
+ * @since 0.6.0
161
+ */
162
+ export interface ChildItem<PayloadInput> {
163
+ readonly key: string;
164
+ readonly payload: PayloadInput;
165
+ readonly options?: ChildOptions | undefined;
166
+ }
167
+ /**
168
+ * A group of children of one member type, built by `Flow.children`. A
169
+ * `fanOut` handler returns one group or an array of them.
170
+ *
171
+ * @since 0.6.0
172
+ */
173
+ export interface ChildGroup<out J extends MemberJob = MemberJob> {
174
+ readonly job: J;
175
+ readonly items: ReadonlyArray<ChildItem<PayloadMakeIn<J>>>;
176
+ }
177
+ /**
178
+ * A naked-parameter distribution of `ChildGroup` over a union of members,
179
+ * so a group literal must pair a member's `job` with THAT member's payloads
180
+ * (the undistributed `ChildGroup<A | B>` would accept `A`'s job with `B`'s
181
+ * items).
182
+ *
183
+ * @since 0.6.0
184
+ */
185
+ export type GroupsOf<J> = J extends MemberJob ? ChildGroup<J> : never;
186
+ /**
187
+ * What `fanOut` returns: children of any of the flow's member types.
188
+ *
189
+ * @since 0.6.0
190
+ */
191
+ export type ChildrenInput<J extends MemberJob> = GroupsOf<J> | ReadonlyArray<GroupsOf<J>>;
192
+ /**
193
+ * The deterministic id of a flow child. Every component is an arbitrary
194
+ * string (store keys, ids, and child keys may all contain "/"), so the two
195
+ * variable-length boundaries are pinned by a length prefix — distinct
196
+ * (storeKey, flowId, childKey) triples can never alias.
197
+ *
198
+ * @internal
199
+ */
200
+ export declare const childJobId: (parentStoreKey: string, flowId: string, childKey: string) => string;
201
+ /**
202
+ * Declare children of one member type. Payloads are validated through the
203
+ * child's schema when the specs are built; duplicate keys (across ALL
204
+ * groups) fail the fan-out unrecoverably.
205
+ *
206
+ * @since 0.6.0
207
+ */
208
+ export declare const children: <J extends MemberJob>(job: J, items: ReadonlyArray<ChildItem<PayloadMakeIn<J>>>) => ChildGroup<J>;
209
+ /**
210
+ * A child that completed, with its decoded success value.
211
+ *
212
+ * @since 0.6.0
213
+ */
214
+ export interface CompletedChild<Name extends string, A> {
215
+ readonly key: string;
216
+ readonly name: Name;
217
+ readonly value: A;
218
+ }
219
+ /**
220
+ * A child that failed terminally. `cause` carries the decoded typed failure
221
+ * — or a die for store-side failures that never produced an exit (stall
222
+ * exhaustion, a nested parent's fail-fast settle).
223
+ *
224
+ * @since 0.6.0
225
+ */
226
+ export interface FailedChild<Name extends string, E> {
227
+ readonly key: string;
228
+ readonly name: Name;
229
+ readonly cause: Cause.Cause<E>;
230
+ }
231
+ /**
232
+ * A child that was cancelled — directly in its store, or by a flow settle
233
+ * (fail-fast, or a cancel of the waiting parent).
234
+ *
235
+ * @since 0.6.0
236
+ */
237
+ export interface CancelledChild<Name extends string> {
238
+ readonly key: string;
239
+ readonly name: Name;
240
+ }
241
+ type CompletedOf<J> = J extends MemberJob ? CompletedChild<NameOf<J>, SuccessValue<J>> : never;
242
+ type FailedOf<J> = J extends MemberJob ? FailedChild<NameOf<J>, ErrorValue<J>> : never;
243
+ type CancelledOf<J> = J extends MemberJob ? CancelledChild<NameOf<J>> : never;
244
+ /**
245
+ * Per-outcome tallies, read straight off the parent's persisted `FlowState`
246
+ * — no dependency-row reads. When `collect` runs, `pending` is 0.
247
+ *
248
+ * @since 0.6.0
249
+ */
250
+ export interface ChildCounts {
251
+ readonly pending: number;
252
+ readonly completed: number;
253
+ readonly failed: number;
254
+ readonly cancelled: number;
255
+ }
256
+ /**
257
+ * One settled child, discriminated by `outcome` (and by `name` across
258
+ * member types), decoded through its member's schemas.
259
+ *
260
+ * @since 0.6.0
261
+ */
262
+ export type SettledChild<J extends MemberJob> = ({
263
+ readonly outcome: "completed";
264
+ } & CompletedOf<J>) | ({
265
+ readonly outcome: "failed";
266
+ } & FailedOf<J>) | ({
267
+ readonly outcome: "cancelled";
268
+ } & CancelledOf<J>);
269
+ /**
270
+ * Every settled child, materialized into outcome buckets.
271
+ *
272
+ * @since 0.6.0
273
+ */
274
+ export interface SettledChildren<J extends MemberJob> {
275
+ readonly completed: ReadonlyArray<Extract<SettledChild<J>, {
276
+ readonly outcome: "completed";
277
+ }>>;
278
+ readonly failed: ReadonlyArray<Extract<SettledChild<J>, {
279
+ readonly outcome: "failed";
280
+ }>>;
281
+ readonly cancelled: ReadonlyArray<Extract<SettledChild<J>, {
282
+ readonly outcome: "cancelled";
283
+ }>>;
284
+ }
285
+ /**
286
+ * What `collect` (and `Flow.childResults`) receives: `counts` for free,
287
+ * `all` to materialize the outcome buckets (one array — fine into the
288
+ * tens of thousands), and `stream` to fold huge flows one page at a time.
289
+ *
290
+ * @since 0.6.0
291
+ */
292
+ export interface ChildResults<J extends MemberJob> {
293
+ readonly counts: ChildCounts;
294
+ readonly all: Effect.Effect<SettledChildren<J>>;
295
+ readonly stream: Stream.Stream<SettledChild<J>>;
296
+ }
297
+ /**
298
+ * The two-phase flow handler. `fanOut` runs once per flow (persisted phase
299
+ * dispatch — a resumed parent can never fan out twice) and returns the
300
+ * children; `collect` runs after every child settled, with their results.
301
+ * Both draw on the PARENT's attempt budget: a failing `fanOut` retries
302
+ * against it until the manifest lands, a failing `collect` retries with
303
+ * what remains.
304
+ *
305
+ * @since 0.6.0
306
+ */
307
+ export interface FlowHandlers<Parent extends ParentJob, Children extends ReadonlyArray<MemberJob>, R1, R2> {
308
+ readonly fanOut: (payload: PayloadType<Parent>) => Effect.Effect<ChildrenInput<Children[number]>, ErrorValue<Parent>, R1>;
309
+ readonly collect: (payload: PayloadType<Parent>, results: ChildResults<Children[number]>) => Effect.Effect<SuccessValue<Parent>, ErrorValue<Parent>, R2>;
310
+ }
311
+ /**
312
+ * A flow definition. The producer surface (`enqueue`, `execute`, `poll`,
313
+ * `awaitResult`, `schedule`, ...) IS the parent job's — a flow parent is a
314
+ * real job row in the parent store, and a scheduled parent needs no flow
315
+ * awareness in its schedule row.
316
+ *
317
+ * Note on fail-fast (`onChildFailure: "fail"`): the first failed child
318
+ * settles the parent terminally `failed` store-side (`failedReason` names
319
+ * the child; there is no parent exit, so `awaitResult` dies — like stall
320
+ * exhaustion) and the remaining children are cancelled. The failed child's
321
+ * own exit stays inspectable via `childResults`. An admin `retry` of the
322
+ * parent re-enters `collect` with the mixed results.
323
+ *
324
+ * @since 0.6.0
325
+ */
326
+ export interface Flow<Name extends string, Parent extends ParentJob, Children extends ReadonlyArray<MemberJob>> {
327
+ readonly name: Name;
328
+ readonly parent: Parent;
329
+ readonly children: Children;
330
+ /** True when `onChildFailure` is `"fail"`. */
331
+ readonly failFast: boolean;
332
+ readonly enqueue: Parent["enqueue"];
333
+ readonly enqueueMany: Parent["enqueueMany"];
334
+ readonly execute: Parent["execute"];
335
+ readonly poll: Parent["poll"];
336
+ readonly attempts: Parent["attempts"];
337
+ readonly awaitResult: Parent["awaitResult"];
338
+ readonly retry: Parent["retry"];
339
+ readonly cancel: Parent["cancel"];
340
+ readonly promote: Parent["promote"];
341
+ readonly schedule: Parent["schedule"];
342
+ readonly unschedule: Parent["unschedule"];
343
+ /**
344
+ * The flow's recorded child results, in any parent state: live `counts`
345
+ * plus the `all`/`stream` accessors — children still pending are absent
346
+ * from both.
347
+ */
348
+ readonly childResults: (flowId: JobId) => Effect.Effect<ChildResults<Children[number]>, never, MemberStores<Parent> | SuccessDecodingServices<Children[number]> | ErrorDecodingServices<Children[number]>>;
349
+ /**
350
+ * Register the parent's two phases on a worker (bound to the parent's
351
+ * store). Requires every member store — this is what makes the parent
352
+ * worker the one process guaranteed capable of reconciling and cascading
353
+ * across the whole flow.
354
+ */
355
+ readonly toLayer: <R1, R2>(handlers: FlowHandlers<Parent, Children, R1, R2>, options?: RegisterOptions | undefined) => Layer.Layer<never, never, Worker | Exclude<R1, CurrentJob> | Exclude<R2, CurrentJob> | MemberStores<Parent> | MemberStores<Children[number]> | PayloadDecodingServices<Parent> | SuccessEncodingServices<Parent> | ErrorEncodingServices<Parent> | PayloadEncodingServices<Children[number]> | SuccessDecodingServices<Children[number]> | ErrorDecodingServices<Children[number]>>;
356
+ }
357
+ /**
358
+ * Define a flow over existing job definitions.
359
+ *
360
+ * Throws (synchronously, at definition time) on duplicate child names or a
361
+ * parent listed among its own children (direct self-recursion). Nesting
362
+ * across DIFFERENT flows is supported — see the module docs.
363
+ *
364
+ * @since 0.6.0
365
+ */
366
+ export declare const make: <const Name extends string, Parent extends ParentJob, const Children extends ReadonlyArray<MemberJob>>(name: Name, options: {
367
+ /** The parent job: its store owns the flow. */
368
+ readonly parent: Parent;
369
+ /** The closed set of member definitions `fanOut` may produce. */
370
+ readonly children: Children;
371
+ /**
372
+ * What a failed child does to the flow:
373
+ * - `"continue"` (default): every child settles; `collect` sees the
374
+ * failures in `results.failed`.
375
+ * - `"fail"`: the first failed child settles the parent as `failed`
376
+ * and cancels the remaining children (see the `Flow` docs).
377
+ */
378
+ readonly onChildFailure?: "continue" | "fail" | undefined;
379
+ }) => Flow<Name, Parent, Children>;
380
+ export {};
381
+ //# sourceMappingURL=Flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Flow.d.ts","sourceRoot":"","sources":["../src/Flow.ts"],"names":[],"mappings":"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"}