monday-cli 0.3.0 → 0.4.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.
- package/CHANGELOG.md +351 -0
- package/README.md +130 -36
- package/dist/api/assets.d.ts +326 -0
- package/dist/api/assets.d.ts.map +1 -0
- package/dist/api/assets.js +519 -0
- package/dist/api/assets.js.map +1 -0
- package/dist/api/column-types.d.ts +11 -7
- package/dist/api/column-types.d.ts.map +1 -1
- package/dist/api/column-types.js +5 -3
- package/dist/api/column-types.js.map +1 -1
- package/dist/api/column-values.d.ts +7 -1
- package/dist/api/column-values.d.ts.map +1 -1
- package/dist/api/column-values.js +15 -6
- package/dist/api/column-values.js.map +1 -1
- package/dist/api/documents.d.ts +519 -0
- package/dist/api/documents.d.ts.map +1 -0
- package/dist/api/documents.js +586 -0
- package/dist/api/documents.js.map +1 -0
- package/dist/api/item-watch.d.ts +263 -0
- package/dist/api/item-watch.d.ts.map +1 -0
- package/dist/api/item-watch.js +709 -0
- package/dist/api/item-watch.js.map +1 -0
- package/dist/api/multipart-transport.d.ts +223 -0
- package/dist/api/multipart-transport.d.ts.map +1 -0
- package/dist/api/multipart-transport.js +274 -0
- package/dist/api/multipart-transport.js.map +1 -0
- package/dist/api/parallel-dispatch.d.ts +155 -0
- package/dist/api/parallel-dispatch.d.ts.map +1 -0
- package/dist/api/parallel-dispatch.js +243 -0
- package/dist/api/parallel-dispatch.js.map +1 -0
- package/dist/api/partial-success-bulk.d.ts +118 -60
- package/dist/api/partial-success-bulk.d.ts.map +1 -1
- package/dist/api/partial-success-bulk.js +137 -79
- package/dist/api/partial-success-bulk.js.map +1 -1
- package/dist/api/partial-success-mutation.d.ts +13 -1
- package/dist/api/partial-success-mutation.d.ts.map +1 -1
- package/dist/api/partial-success-mutation.js +5 -1
- package/dist/api/partial-success-mutation.js.map +1 -1
- package/dist/api/raw-write.d.ts +12 -4
- package/dist/api/raw-write.d.ts.map +1 -1
- package/dist/api/raw-write.js +21 -11
- package/dist/api/raw-write.js.map +1 -1
- package/dist/api/resolve-client.d.ts +11 -0
- package/dist/api/resolve-client.d.ts.map +1 -1
- package/dist/api/resolve-client.js +9 -1
- package/dist/api/resolve-client.js.map +1 -1
- package/dist/cli/run.d.ts +20 -0
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +1 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/commands/board/column-create.d.ts +6 -5
- package/dist/commands/board/column-create.d.ts.map +1 -1
- package/dist/commands/board/column-create.js +9 -6
- package/dist/commands/board/column-create.js.map +1 -1
- package/dist/commands/completion.d.ts +188 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +418 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/doc/get.d.ts +46 -0
- package/dist/commands/doc/get.d.ts.map +1 -0
- package/dist/commands/doc/get.js +95 -0
- package/dist/commands/doc/get.js.map +1 -0
- package/dist/commands/doc/list.d.ts +83 -0
- package/dist/commands/doc/list.d.ts.map +1 -0
- package/dist/commands/doc/list.js +248 -0
- package/dist/commands/doc/list.js.map +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +46 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/item/create.js +2 -2
- package/dist/commands/item/update.d.ts +1 -0
- package/dist/commands/item/update.d.ts.map +1 -1
- package/dist/commands/item/update.js +61 -0
- package/dist/commands/item/update.js.map +1 -1
- package/dist/commands/item/upload.d.ts +108 -0
- package/dist/commands/item/upload.d.ts.map +1 -0
- package/dist/commands/item/upload.js +370 -0
- package/dist/commands/item/upload.js.map +1 -0
- package/dist/commands/item/watch.d.ts +90 -0
- package/dist/commands/item/watch.d.ts.map +1 -0
- package/dist/commands/item/watch.js +342 -0
- package/dist/commands/item/watch.js.map +1 -0
- package/dist/commands/update/upload.d.ts +69 -0
- package/dist/commands/update/upload.d.ts.map +1 -0
- package/dist/commands/update/upload.js +235 -0
- package/dist/commands/update/upload.js.map +1 -0
- package/dist/types/ids.d.ts +2 -0
- package/dist/types/ids.d.ts.map +1 -1
- package/dist/types/ids.js +9 -2
- package/dist/types/ids.js.map +1 -1
- package/dist/utils/mime.d.ts +24 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +64 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/output/envelope.d.ts +30 -0
- package/dist/utils/output/envelope.d.ts.map +1 -1
- package/dist/utils/output/envelope.js +26 -0
- package/dist/utils/output/envelope.js.map +1 -1
- package/dist/utils/output/ndjson.d.ts +25 -0
- package/dist/utils/output/ndjson.d.ts.map +1 -1
- package/dist/utils/output/ndjson.js +12 -0
- package/dist/utils/output/ndjson.js.map +1 -1
- package/dist/utils/signal.d.ts +42 -0
- package/dist/utils/signal.d.ts.map +1 -0
- package/dist/utils/signal.js +45 -0
- package/dist/utils/signal.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded-concurrency per-item dispatch helper for the v0.4-M30
|
|
3
|
+
* `--concurrency <N>` flag extension to `cli-design` §6.4 "Bulk per-
|
|
4
|
+
* item partial-success" (the M25 `item update --continue-on-error`
|
|
5
|
+
* path).
|
|
6
|
+
*
|
|
7
|
+
* **What this module owns.** A bounded-concurrency async-pool variant
|
|
8
|
+
* of `src/api/partial-success-mutation.ts:dispatchSequential` —
|
|
9
|
+
* maintains at most N in-flight per-target dispatch promises at any
|
|
10
|
+
* time, captures per-target failures into the result records exactly
|
|
11
|
+
* the way `dispatchSequential` does. The result array preserves
|
|
12
|
+
* INPUT ORDER (not completion order), so downstream consumers
|
|
13
|
+
* (`src/api/partial-success-bulk.ts:foldPartialSuccessBulkResult`)
|
|
14
|
+
* see the same row sequence regardless of which target completed
|
|
15
|
+
* first. Per-target error decoration + `internal_error` re-throw +
|
|
16
|
+
* non-`MondayCliError` re-throw semantics MUST match
|
|
17
|
+
* `dispatchSequential` exactly. Note: `--concurrency 1` does NOT
|
|
18
|
+
* route through this helper — the partial-success-bulk wrapper
|
|
19
|
+
* routes `concurrency === undefined || concurrency === 1` to
|
|
20
|
+
* `dispatchSequential` and only `concurrency > 1` to
|
|
21
|
+
* `dispatchParallel`. The byte-equivalence guarantee at N=1 holds
|
|
22
|
+
* by construction (the sequential path is unchanged from v0.3-M25).
|
|
23
|
+
*
|
|
24
|
+
* **Why a separate module.** Three reasons mirroring
|
|
25
|
+
* `src/api/partial-success-bulk.ts`'s carve-out:
|
|
26
|
+
*
|
|
27
|
+
* 1. **Single-source-of-truth for the async-pool pattern.** The
|
|
28
|
+
* v0.4-M30 IMPL landed the bounded-concurrency
|
|
29
|
+
* orchestration in one place; any future bulk verb that
|
|
30
|
+
* needs parallel dispatch (`item clear --where`, M13 `update
|
|
31
|
+
* clear-all`, M14 user-fan-out family) imports the same
|
|
32
|
+
* helper without duplicating the in-flight-counter +
|
|
33
|
+
* slot-recycling logic.
|
|
34
|
+
* 2. **Test surface ergonomics.** Mocking the async-pool
|
|
35
|
+
* timing (e.g., asserting "no more than N promises ever
|
|
36
|
+
* in-flight at any tick") is cleaner at the helper's seam
|
|
37
|
+
* than against the action body's branched control flow.
|
|
38
|
+
* 3. **Stub-then-IMPL cadence.** Pre-flight (cluster
|
|
39
|
+
* `8cfd96b..0ca9418`) shipped the type surface + the
|
|
40
|
+
* stubbed body under `c8 ignore start/stop`; IMPL
|
|
41
|
+
* (`8faf20e`) landed the runtime body + the integration
|
|
42
|
+
* tests against `FixtureTransport` cassettes that exercise
|
|
43
|
+
* the parallel dispatch matrix.
|
|
44
|
+
*
|
|
45
|
+
* **What stays at the caller layer.** Argv parse, column
|
|
46
|
+
* resolution, items_page walk, confirmation gate, dry-run path,
|
|
47
|
+
* source aggregation seed, envelope assembly. The wrapper
|
|
48
|
+
* returns the per-item result rows; the caller folds them into
|
|
49
|
+
* `data.results[]` via `foldPartialSuccessBulkResult` (unchanged
|
|
50
|
+
* from M25).
|
|
51
|
+
*
|
|
52
|
+
* **Empirical probe finding (2026-05-13, API 2026-01).** Monday's
|
|
53
|
+
* per-account concurrency cap for trivial reads exceeds 100
|
|
54
|
+
* in-flight without triggering `concurrency_exceeded`; the cap
|
|
55
|
+
* value is plan-tier-dependent (cli-design §2.5) and not
|
|
56
|
+
* empirically pinnable from a single account. The
|
|
57
|
+
* {@link MAX_CONCURRENCY} value below (`32`) is a conservative
|
|
58
|
+
* upper bound for the CLI argv — well under any plausible per-
|
|
59
|
+
* account cap while large enough to give meaningful speedup on
|
|
60
|
+
* bulk operations against high-latency Monday endpoints. The
|
|
61
|
+
* existing `src/api/retry.ts` layer already handles
|
|
62
|
+
* `concurrency_exceeded` with exponential backoff per cli-design
|
|
63
|
+
* §2.5; M30 IMPL inherits this without new logic.
|
|
64
|
+
*/
|
|
65
|
+
import type { PartialSuccessResult, DispatchOneTargetInputs } from './partial-success-mutation.js';
|
|
66
|
+
/**
|
|
67
|
+
* Minimum `--concurrency` argv value. `1` is a valid no-op:
|
|
68
|
+
* `partial-success-bulk.ts`'s routing branch sends
|
|
69
|
+
* `concurrency === 1` (and `undefined`) to `dispatchSequential`,
|
|
70
|
+
* NOT to this helper, so the byte-equivalence guarantee with the
|
|
71
|
+
* existing v0.3-M25 sequential path at N=1 holds by construction.
|
|
72
|
+
* Letting agents pass `1` explicitly lets them flip the flag
|
|
73
|
+
* without worrying about a `0`-edge case.
|
|
74
|
+
*/
|
|
75
|
+
export declare const MIN_CONCURRENCY = 1;
|
|
76
|
+
/**
|
|
77
|
+
* Maximum `--concurrency` argv value. Conservative upper bound
|
|
78
|
+
* informed by the M30 pre-flight empirical probe
|
|
79
|
+
* (`scripts/probe/m30-concurrency.ts`, 2026-05-13, API 2026-01)
|
|
80
|
+
* which observed no `concurrency_exceeded` at N=100 in-flight
|
|
81
|
+
* `me { id }` reads. `32` leaves substantial headroom under any
|
|
82
|
+
* plausible plan-tier cap while bounding the worst-case
|
|
83
|
+
* connection-pool pressure on Monday's edge.
|
|
84
|
+
*/
|
|
85
|
+
export declare const MAX_CONCURRENCY = 32;
|
|
86
|
+
/**
|
|
87
|
+
* Default `--concurrency` value when the argv slot is absent.
|
|
88
|
+
* `1` preserves the v0.3-M25 sequential behaviour exactly —
|
|
89
|
+
* agents who haven't migrated to the M30 surface continue to
|
|
90
|
+
* receive byte-identical envelopes.
|
|
91
|
+
*/
|
|
92
|
+
export declare const DEFAULT_CONCURRENCY = 1;
|
|
93
|
+
/**
|
|
94
|
+
* Bounded-concurrency dispatch over a target list, with per-
|
|
95
|
+
* target error capture into the result records (NOT abort-on-
|
|
96
|
+
* first-error). Maintains at most `concurrency` in-flight
|
|
97
|
+
* dispatch promises at any moment; new targets enter the pool as
|
|
98
|
+
* earlier ones complete. Result array preserves input order.
|
|
99
|
+
*
|
|
100
|
+
* Behavioural invariants (Codex pre-flight audit-point W3 —
|
|
101
|
+
* R-NEW-28 6-axis behavioral-equivalence to dispatchSequential):
|
|
102
|
+
*
|
|
103
|
+
* 1. **Per-target error code semantics** — every code
|
|
104
|
+
* `dispatchSequential` would surface for the same per-
|
|
105
|
+
* target failure lands in `results[i].error.code` here.
|
|
106
|
+
* `MondayCliError`-typed throws land per-record; the
|
|
107
|
+
* caller's `foldAndRemap` (via the dispatch callback) is
|
|
108
|
+
* responsible for the `validation_failed` → `column_archived`
|
|
109
|
+
* stale-cache remap.
|
|
110
|
+
* 2. **`internal_error` re-throw escape hatch** — if a per-
|
|
111
|
+
* target dispatch throws `MondayCliError` with `code ===
|
|
112
|
+
* 'internal_error'`, the helper re-throws whole-call
|
|
113
|
+
* (aborts the pool/scheduler and propagates) so schema-
|
|
114
|
+
* drift surfaces as top-level `ok: false` (M14 round-2 F1 /
|
|
115
|
+
* round-3 F1 precedent at
|
|
116
|
+
* `src/api/partial-success-mutation.ts`'s
|
|
117
|
+
* `dispatchSequential`). Other in-flight calls' results
|
|
118
|
+
* are NOT salvaged — the contract is "whole-call failure
|
|
119
|
+
* on internal_error" so a partial `data.results[]` would
|
|
120
|
+
* be misleading. The pool sets an internal `aborted` flag
|
|
121
|
+
* so workers stop pulling new targets; in-flight dispatches
|
|
122
|
+
* complete on their own in the background but their writes
|
|
123
|
+
* never reach the caller because `Promise.all` rejection
|
|
124
|
+
* surfaces the original error first.
|
|
125
|
+
* 3. **Non-`MondayCliError` re-throw** — programmer-bug
|
|
126
|
+
* exceptions (TypeError, RangeError, etc.) propagate
|
|
127
|
+
* whole-call via the same path as the
|
|
128
|
+
* `dispatchSequential`'s non-CliError branch. Same
|
|
129
|
+
* `aborted` flag mechanism prevents new dispatches.
|
|
130
|
+
* 4. **Empty input** — `targets.length === 0` returns `[]`
|
|
131
|
+
* synchronously (after the leading await tick); no
|
|
132
|
+
* dispatch fires. Matches `dispatchSequential`'s empty-
|
|
133
|
+
* input handling.
|
|
134
|
+
* 5. **Result ordering** — `results[i]` corresponds to
|
|
135
|
+
* `targets[i]`, regardless of completion order. Workers
|
|
136
|
+
* pull from a shared `cursor` to pick the next target's
|
|
137
|
+
* index, then assign the result by that index — never
|
|
138
|
+
* `push()`. A late-completing first target still lands at
|
|
139
|
+
* `results[0]`.
|
|
140
|
+
* 6. **AbortSignal threading.** The optional `signal`
|
|
141
|
+
* parameter is checked at every worker-loop iteration top.
|
|
142
|
+
* When `signal.aborted` becomes true, the worker re-throws
|
|
143
|
+
* `signal.reason` (via `extractSignalReason` from
|
|
144
|
+
* `src/utils/signal.ts`); the `aborted` flag stops other
|
|
145
|
+
* workers from scheduling NEW dispatches.
|
|
146
|
+
* In-flight wire calls abort via the existing
|
|
147
|
+
* `MondayClient.signal` configured at construction time
|
|
148
|
+
* (the client threads its signal into every fetch) — the
|
|
149
|
+
* pool-level check is the scheduler short-circuit, not the
|
|
150
|
+
* wire-call cancellation source. Mirrors
|
|
151
|
+
* `dispatchSequential`'s axis-6 signal check at the
|
|
152
|
+
* iteration boundary.
|
|
153
|
+
*/
|
|
154
|
+
export declare const dispatchParallel: <TargetId extends string>(targets: readonly TargetId[], idField: string, dispatch: (inputs: DispatchOneTargetInputs<TargetId>) => Promise<void>, concurrency: number, signal?: AbortSignal) => Promise<readonly PartialSuccessResult[]>;
|
|
155
|
+
//# sourceMappingURL=parallel-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-dispatch.d.ts","sourceRoot":"","sources":["../../src/api/parallel-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAIH,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACxB,MAAM,+BAA+B,CAAC;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,eAAO,MAAM,gBAAgB,GAAU,QAAQ,SAAS,MAAM,EAC5D,SAAS,SAAS,QAAQ,EAAE,EAC5B,SAAS,MAAM,EACf,UAAU,CAAC,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACtE,aAAa,MAAM,EACnB,SAAS,WAAW,KACnB,OAAO,CAAC,SAAS,oBAAoB,EAAE,CA6FzC,CAAC"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded-concurrency per-item dispatch helper for the v0.4-M30
|
|
3
|
+
* `--concurrency <N>` flag extension to `cli-design` §6.4 "Bulk per-
|
|
4
|
+
* item partial-success" (the M25 `item update --continue-on-error`
|
|
5
|
+
* path).
|
|
6
|
+
*
|
|
7
|
+
* **What this module owns.** A bounded-concurrency async-pool variant
|
|
8
|
+
* of `src/api/partial-success-mutation.ts:dispatchSequential` —
|
|
9
|
+
* maintains at most N in-flight per-target dispatch promises at any
|
|
10
|
+
* time, captures per-target failures into the result records exactly
|
|
11
|
+
* the way `dispatchSequential` does. The result array preserves
|
|
12
|
+
* INPUT ORDER (not completion order), so downstream consumers
|
|
13
|
+
* (`src/api/partial-success-bulk.ts:foldPartialSuccessBulkResult`)
|
|
14
|
+
* see the same row sequence regardless of which target completed
|
|
15
|
+
* first. Per-target error decoration + `internal_error` re-throw +
|
|
16
|
+
* non-`MondayCliError` re-throw semantics MUST match
|
|
17
|
+
* `dispatchSequential` exactly. Note: `--concurrency 1` does NOT
|
|
18
|
+
* route through this helper — the partial-success-bulk wrapper
|
|
19
|
+
* routes `concurrency === undefined || concurrency === 1` to
|
|
20
|
+
* `dispatchSequential` and only `concurrency > 1` to
|
|
21
|
+
* `dispatchParallel`. The byte-equivalence guarantee at N=1 holds
|
|
22
|
+
* by construction (the sequential path is unchanged from v0.3-M25).
|
|
23
|
+
*
|
|
24
|
+
* **Why a separate module.** Three reasons mirroring
|
|
25
|
+
* `src/api/partial-success-bulk.ts`'s carve-out:
|
|
26
|
+
*
|
|
27
|
+
* 1. **Single-source-of-truth for the async-pool pattern.** The
|
|
28
|
+
* v0.4-M30 IMPL landed the bounded-concurrency
|
|
29
|
+
* orchestration in one place; any future bulk verb that
|
|
30
|
+
* needs parallel dispatch (`item clear --where`, M13 `update
|
|
31
|
+
* clear-all`, M14 user-fan-out family) imports the same
|
|
32
|
+
* helper without duplicating the in-flight-counter +
|
|
33
|
+
* slot-recycling logic.
|
|
34
|
+
* 2. **Test surface ergonomics.** Mocking the async-pool
|
|
35
|
+
* timing (e.g., asserting "no more than N promises ever
|
|
36
|
+
* in-flight at any tick") is cleaner at the helper's seam
|
|
37
|
+
* than against the action body's branched control flow.
|
|
38
|
+
* 3. **Stub-then-IMPL cadence.** Pre-flight (cluster
|
|
39
|
+
* `8cfd96b..0ca9418`) shipped the type surface + the
|
|
40
|
+
* stubbed body under `c8 ignore start/stop`; IMPL
|
|
41
|
+
* (`8faf20e`) landed the runtime body + the integration
|
|
42
|
+
* tests against `FixtureTransport` cassettes that exercise
|
|
43
|
+
* the parallel dispatch matrix.
|
|
44
|
+
*
|
|
45
|
+
* **What stays at the caller layer.** Argv parse, column
|
|
46
|
+
* resolution, items_page walk, confirmation gate, dry-run path,
|
|
47
|
+
* source aggregation seed, envelope assembly. The wrapper
|
|
48
|
+
* returns the per-item result rows; the caller folds them into
|
|
49
|
+
* `data.results[]` via `foldPartialSuccessBulkResult` (unchanged
|
|
50
|
+
* from M25).
|
|
51
|
+
*
|
|
52
|
+
* **Empirical probe finding (2026-05-13, API 2026-01).** Monday's
|
|
53
|
+
* per-account concurrency cap for trivial reads exceeds 100
|
|
54
|
+
* in-flight without triggering `concurrency_exceeded`; the cap
|
|
55
|
+
* value is plan-tier-dependent (cli-design §2.5) and not
|
|
56
|
+
* empirically pinnable from a single account. The
|
|
57
|
+
* {@link MAX_CONCURRENCY} value below (`32`) is a conservative
|
|
58
|
+
* upper bound for the CLI argv — well under any plausible per-
|
|
59
|
+
* account cap while large enough to give meaningful speedup on
|
|
60
|
+
* bulk operations against high-latency Monday endpoints. The
|
|
61
|
+
* existing `src/api/retry.ts` layer already handles
|
|
62
|
+
* `concurrency_exceeded` with exponential backoff per cli-design
|
|
63
|
+
* §2.5; M30 IMPL inherits this without new logic.
|
|
64
|
+
*/
|
|
65
|
+
import { MondayCliError } from '../utils/errors.js';
|
|
66
|
+
import { extractSignalReason } from '../utils/signal.js';
|
|
67
|
+
/**
|
|
68
|
+
* Minimum `--concurrency` argv value. `1` is a valid no-op:
|
|
69
|
+
* `partial-success-bulk.ts`'s routing branch sends
|
|
70
|
+
* `concurrency === 1` (and `undefined`) to `dispatchSequential`,
|
|
71
|
+
* NOT to this helper, so the byte-equivalence guarantee with the
|
|
72
|
+
* existing v0.3-M25 sequential path at N=1 holds by construction.
|
|
73
|
+
* Letting agents pass `1` explicitly lets them flip the flag
|
|
74
|
+
* without worrying about a `0`-edge case.
|
|
75
|
+
*/
|
|
76
|
+
export const MIN_CONCURRENCY = 1;
|
|
77
|
+
/**
|
|
78
|
+
* Maximum `--concurrency` argv value. Conservative upper bound
|
|
79
|
+
* informed by the M30 pre-flight empirical probe
|
|
80
|
+
* (`scripts/probe/m30-concurrency.ts`, 2026-05-13, API 2026-01)
|
|
81
|
+
* which observed no `concurrency_exceeded` at N=100 in-flight
|
|
82
|
+
* `me { id }` reads. `32` leaves substantial headroom under any
|
|
83
|
+
* plausible plan-tier cap while bounding the worst-case
|
|
84
|
+
* connection-pool pressure on Monday's edge.
|
|
85
|
+
*/
|
|
86
|
+
export const MAX_CONCURRENCY = 32;
|
|
87
|
+
/**
|
|
88
|
+
* Default `--concurrency` value when the argv slot is absent.
|
|
89
|
+
* `1` preserves the v0.3-M25 sequential behaviour exactly —
|
|
90
|
+
* agents who haven't migrated to the M30 surface continue to
|
|
91
|
+
* receive byte-identical envelopes.
|
|
92
|
+
*/
|
|
93
|
+
export const DEFAULT_CONCURRENCY = 1;
|
|
94
|
+
/**
|
|
95
|
+
* Bounded-concurrency dispatch over a target list, with per-
|
|
96
|
+
* target error capture into the result records (NOT abort-on-
|
|
97
|
+
* first-error). Maintains at most `concurrency` in-flight
|
|
98
|
+
* dispatch promises at any moment; new targets enter the pool as
|
|
99
|
+
* earlier ones complete. Result array preserves input order.
|
|
100
|
+
*
|
|
101
|
+
* Behavioural invariants (Codex pre-flight audit-point W3 —
|
|
102
|
+
* R-NEW-28 6-axis behavioral-equivalence to dispatchSequential):
|
|
103
|
+
*
|
|
104
|
+
* 1. **Per-target error code semantics** — every code
|
|
105
|
+
* `dispatchSequential` would surface for the same per-
|
|
106
|
+
* target failure lands in `results[i].error.code` here.
|
|
107
|
+
* `MondayCliError`-typed throws land per-record; the
|
|
108
|
+
* caller's `foldAndRemap` (via the dispatch callback) is
|
|
109
|
+
* responsible for the `validation_failed` → `column_archived`
|
|
110
|
+
* stale-cache remap.
|
|
111
|
+
* 2. **`internal_error` re-throw escape hatch** — if a per-
|
|
112
|
+
* target dispatch throws `MondayCliError` with `code ===
|
|
113
|
+
* 'internal_error'`, the helper re-throws whole-call
|
|
114
|
+
* (aborts the pool/scheduler and propagates) so schema-
|
|
115
|
+
* drift surfaces as top-level `ok: false` (M14 round-2 F1 /
|
|
116
|
+
* round-3 F1 precedent at
|
|
117
|
+
* `src/api/partial-success-mutation.ts`'s
|
|
118
|
+
* `dispatchSequential`). Other in-flight calls' results
|
|
119
|
+
* are NOT salvaged — the contract is "whole-call failure
|
|
120
|
+
* on internal_error" so a partial `data.results[]` would
|
|
121
|
+
* be misleading. The pool sets an internal `aborted` flag
|
|
122
|
+
* so workers stop pulling new targets; in-flight dispatches
|
|
123
|
+
* complete on their own in the background but their writes
|
|
124
|
+
* never reach the caller because `Promise.all` rejection
|
|
125
|
+
* surfaces the original error first.
|
|
126
|
+
* 3. **Non-`MondayCliError` re-throw** — programmer-bug
|
|
127
|
+
* exceptions (TypeError, RangeError, etc.) propagate
|
|
128
|
+
* whole-call via the same path as the
|
|
129
|
+
* `dispatchSequential`'s non-CliError branch. Same
|
|
130
|
+
* `aborted` flag mechanism prevents new dispatches.
|
|
131
|
+
* 4. **Empty input** — `targets.length === 0` returns `[]`
|
|
132
|
+
* synchronously (after the leading await tick); no
|
|
133
|
+
* dispatch fires. Matches `dispatchSequential`'s empty-
|
|
134
|
+
* input handling.
|
|
135
|
+
* 5. **Result ordering** — `results[i]` corresponds to
|
|
136
|
+
* `targets[i]`, regardless of completion order. Workers
|
|
137
|
+
* pull from a shared `cursor` to pick the next target's
|
|
138
|
+
* index, then assign the result by that index — never
|
|
139
|
+
* `push()`. A late-completing first target still lands at
|
|
140
|
+
* `results[0]`.
|
|
141
|
+
* 6. **AbortSignal threading.** The optional `signal`
|
|
142
|
+
* parameter is checked at every worker-loop iteration top.
|
|
143
|
+
* When `signal.aborted` becomes true, the worker re-throws
|
|
144
|
+
* `signal.reason` (via `extractSignalReason` from
|
|
145
|
+
* `src/utils/signal.ts`); the `aborted` flag stops other
|
|
146
|
+
* workers from scheduling NEW dispatches.
|
|
147
|
+
* In-flight wire calls abort via the existing
|
|
148
|
+
* `MondayClient.signal` configured at construction time
|
|
149
|
+
* (the client threads its signal into every fetch) — the
|
|
150
|
+
* pool-level check is the scheduler short-circuit, not the
|
|
151
|
+
* wire-call cancellation source. Mirrors
|
|
152
|
+
* `dispatchSequential`'s axis-6 signal check at the
|
|
153
|
+
* iteration boundary.
|
|
154
|
+
*/
|
|
155
|
+
export const dispatchParallel = async (targets, idField, dispatch, concurrency, signal) => {
|
|
156
|
+
if (targets.length === 0) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
// Pre-allocated result array indexed by input position. Workers
|
|
160
|
+
// assign by index (NOT push) so completion order can't reorder
|
|
161
|
+
// results — axis 5 of the R-NEW-28 audit.
|
|
162
|
+
const results = new Array(targets.length);
|
|
163
|
+
// Shared cursor across workers. Each worker reads the current
|
|
164
|
+
// value into `i`, increments, then dispatches `targets[i]`. The
|
|
165
|
+
// read-then-increment is safe in single-threaded JS — the worker
|
|
166
|
+
// is between awaits when it touches the cursor.
|
|
167
|
+
let cursor = 0;
|
|
168
|
+
// Whole-call abort flag. Set when a worker hits `internal_error`,
|
|
169
|
+
// a non-`MondayCliError` throw, or the signal aborting. Other
|
|
170
|
+
// workers see the flag at their next iteration top and return
|
|
171
|
+
// immediately without scheduling new dispatches. In-flight
|
|
172
|
+
// dispatches complete (or fail) on their own; their results
|
|
173
|
+
// never reach the caller because Promise.all rejects on the
|
|
174
|
+
// worker that threw.
|
|
175
|
+
let aborted = false;
|
|
176
|
+
const worker = async () => {
|
|
177
|
+
for (;;) {
|
|
178
|
+
if (aborted) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (signal?.aborted === true) {
|
|
182
|
+
aborted = true;
|
|
183
|
+
throw extractSignalReason(signal);
|
|
184
|
+
}
|
|
185
|
+
const i = cursor;
|
|
186
|
+
cursor += 1;
|
|
187
|
+
// `noUncheckedIndexedAccess` is on — read once + narrow rather
|
|
188
|
+
// than a separate length check + non-null assertion, which
|
|
189
|
+
// tripped both `@typescript-eslint/non-nullable-type-assertion-style`
|
|
190
|
+
// and `no-non-null-assertion` depending on the form.
|
|
191
|
+
const targetId = targets[i];
|
|
192
|
+
if (targetId === undefined) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
await dispatch({ targetId });
|
|
197
|
+
results[i] = {
|
|
198
|
+
[idField]: targetId,
|
|
199
|
+
ok: true,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
if (err instanceof MondayCliError) {
|
|
204
|
+
// Mirror `dispatchSequential`'s axis-2 escape hatch:
|
|
205
|
+
// `internal_error` re-throws whole-call so schema-
|
|
206
|
+
// drift surfaces as top-level `ok: false` rather than
|
|
207
|
+
// being papered over as a per-record slot. The aborted
|
|
208
|
+
// flag prevents other workers from scheduling new
|
|
209
|
+
// dispatches once we throw.
|
|
210
|
+
if (err.code === 'internal_error') {
|
|
211
|
+
aborted = true;
|
|
212
|
+
throw err;
|
|
213
|
+
}
|
|
214
|
+
results[i] = {
|
|
215
|
+
[idField]: targetId,
|
|
216
|
+
ok: false,
|
|
217
|
+
error: { code: err.code, message: err.message },
|
|
218
|
+
};
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
// Non-MondayCliError — programmer bug. Mirrors
|
|
222
|
+
// `dispatchSequential`'s axis-3 non-CliError re-throw;
|
|
223
|
+
// runner's catch-all surfaces as `internal_error`.
|
|
224
|
+
aborted = true;
|
|
225
|
+
throw err;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
// Spin up `min(concurrency, targets.length)` workers. Extra
|
|
230
|
+
// workers beyond the target count would immediately exit the
|
|
231
|
+
// loop (cursor >= targets.length on first iteration), so they
|
|
232
|
+
// add no value — bounding here keeps the Promise.all shape
|
|
233
|
+
// tight + makes the "N=8 against 4 targets" edge-case
|
|
234
|
+
// deterministic (4 workers, not 8).
|
|
235
|
+
const workerCount = Math.min(concurrency, targets.length);
|
|
236
|
+
const workers = [];
|
|
237
|
+
for (let w = 0; w < workerCount; w += 1) {
|
|
238
|
+
workers.push(worker());
|
|
239
|
+
}
|
|
240
|
+
await Promise.all(workers);
|
|
241
|
+
return results;
|
|
242
|
+
};
|
|
243
|
+
//# sourceMappingURL=parallel-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-dispatch.js","sourceRoot":"","sources":["../../src/api/parallel-dispatch.ts"],"names":[],"mappings":"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"}
|