@glubean/runner 0.7.0 → 0.8.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 (71) hide show
  1. package/dist/engine-bridge.d.ts +4 -0
  2. package/dist/engine-bridge.d.ts.map +1 -1
  3. package/dist/engine-bridge.js +10 -1
  4. package/dist/engine-bridge.js.map +1 -1
  5. package/dist/executor.d.ts +2 -2
  6. package/dist/executor.d.ts.map +1 -1
  7. package/dist/executor.js +9 -226
  8. package/dist/executor.js.map +1 -1
  9. package/dist/harness.js +3 -79
  10. package/dist/harness.js.map +1 -1
  11. package/dist/index.d.ts +16 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +17 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/load/continuation-pool.d.ts +82 -0
  16. package/dist/load/continuation-pool.d.ts.map +1 -0
  17. package/dist/load/continuation-pool.js +154 -0
  18. package/dist/load/continuation-pool.js.map +1 -0
  19. package/dist/load/execute-iteration.d.ts +126 -0
  20. package/dist/load/execute-iteration.d.ts.map +1 -0
  21. package/dist/load/execute-iteration.js +367 -0
  22. package/dist/load/execute-iteration.js.map +1 -0
  23. package/dist/load/histogram.d.ts +63 -0
  24. package/dist/load/histogram.d.ts.map +1 -0
  25. package/dist/load/histogram.js +149 -0
  26. package/dist/load/histogram.js.map +1 -0
  27. package/dist/load/orchestrator.d.ts +55 -0
  28. package/dist/load/orchestrator.d.ts.map +1 -0
  29. package/dist/load/orchestrator.js +571 -0
  30. package/dist/load/orchestrator.js.map +1 -0
  31. package/dist/load/reducer.d.ts +109 -0
  32. package/dist/load/reducer.d.ts.map +1 -0
  33. package/dist/load/reducer.js +718 -0
  34. package/dist/load/reducer.js.map +1 -0
  35. package/dist/load/route-key.d.ts +38 -0
  36. package/dist/load/route-key.d.ts.map +1 -0
  37. package/dist/load/route-key.js +107 -0
  38. package/dist/load/route-key.js.map +1 -0
  39. package/dist/load/samples.d.ts +83 -0
  40. package/dist/load/samples.d.ts.map +1 -0
  41. package/dist/load/samples.js +269 -0
  42. package/dist/load/samples.js.map +1 -0
  43. package/dist/load/sink.d.ts +127 -0
  44. package/dist/load/sink.d.ts.map +1 -0
  45. package/dist/load/sink.js +351 -0
  46. package/dist/load/sink.js.map +1 -0
  47. package/dist/load/subprocess.d.ts +83 -0
  48. package/dist/load/subprocess.d.ts.map +1 -0
  49. package/dist/load/subprocess.js +229 -0
  50. package/dist/load/subprocess.js.map +1 -0
  51. package/dist/load/threshold.d.ts +44 -0
  52. package/dist/load/threshold.d.ts.map +1 -0
  53. package/dist/load/threshold.js +197 -0
  54. package/dist/load/threshold.js.map +1 -0
  55. package/dist/load/timeline.d.ts +36 -0
  56. package/dist/load/timeline.d.ts.map +1 -0
  57. package/dist/load/timeline.js +158 -0
  58. package/dist/load/timeline.js.map +1 -0
  59. package/dist/load-harness.d.ts +2 -0
  60. package/dist/load-harness.d.ts.map +1 -0
  61. package/dist/load-harness.js +105 -0
  62. package/dist/load-harness.js.map +1 -0
  63. package/dist/runner-resolve.d.ts +53 -0
  64. package/dist/runner-resolve.d.ts.map +1 -0
  65. package/dist/runner-resolve.js +264 -0
  66. package/dist/runner-resolve.js.map +1 -0
  67. package/dist/workflow/event-timeline.d.ts +3 -0
  68. package/dist/workflow/event-timeline.d.ts.map +1 -0
  69. package/dist/workflow/event-timeline.js +72 -0
  70. package/dist/workflow/event-timeline.js.map +1 -0
  71. package/package.json +4 -4
@@ -0,0 +1,571 @@
1
+ import { parseDurationMs } from "@glubean/sdk/load";
2
+ import { createEngineCore } from "../engine-bridge.js";
3
+ import { compileLoadScenario, startLoadIteration, } from "./execute-iteration.js";
4
+ import { ContinuationPool } from "./continuation-pool.js";
5
+ import { createLoadReducer } from "./reducer.js";
6
+ import { LoadSink } from "./sink.js";
7
+ import { evaluateThresholds } from "./threshold.js";
8
+ /**
9
+ * Ramp-up start offset (ms) for a slot. `rampUp` is the time to reach FULL
10
+ * concurrency, so slots spread evenly across `[0, rampUp]` with the LAST slot
11
+ * starting at the end of the window (slot 0 at 0, slot N-1 at `rampUp`). A single
12
+ * slot (or no ramp) starts immediately.
13
+ */
14
+ export function rampDelayMs(slotIndex, concurrency, rampUpMs) {
15
+ if (concurrency <= 1 || rampUpMs <= 0)
16
+ return 0;
17
+ return (slotIndex / (concurrency - 1)) * rampUpMs;
18
+ }
19
+ /** Deep-clone the base session for one iteration — copy-on-write isolation that
20
+ * also covers nested values, so a mutation in one iteration never leaks into
21
+ * another. (structuredClone is available on the Node runtime the runner targets.) */
22
+ function cloneSession(base) {
23
+ return structuredClone(base);
24
+ }
25
+ /** Resolve a scenario reference (un-built builder → built scenario). */
26
+ function resolveScenario(ref) {
27
+ const r = ref;
28
+ if (r.__glubean_type === "load-scenario-builder" && typeof r.build === "function") {
29
+ return r.build();
30
+ }
31
+ return ref;
32
+ }
33
+ /** Normalize a pacing config's thinkTime to ms (number or {min,max}). */
34
+ function normalizeThinkTime(pacing) {
35
+ const tt = pacing?.thinkTime;
36
+ if (tt === undefined)
37
+ return undefined;
38
+ if (typeof tt === "object") {
39
+ const min = parseDurationMs(tt.min);
40
+ const max = parseDurationMs(tt.max);
41
+ if (max < min) {
42
+ throw new Error(`pacing.thinkTime range is inverted: min (${min}ms) must be <= max (${max}ms)`);
43
+ }
44
+ return { min, max };
45
+ }
46
+ return parseDurationMs(tt);
47
+ }
48
+ /** A single think-time delay (random within [min,max] for a range). */
49
+ function thinkDelay(thinkTimeMs) {
50
+ if (thinkTimeMs === undefined)
51
+ return 0;
52
+ if (typeof thinkTimeMs === "number")
53
+ return thinkTimeMs;
54
+ const { min, max } = thinkTimeMs;
55
+ return min + Math.random() * Math.max(0, max - min);
56
+ }
57
+ function isMixConfig(config) {
58
+ return "scenarios" in config;
59
+ }
60
+ /**
61
+ * Drain the in-flight continuations from released iterations before the run
62
+ * finalizes. With a `drainTimeoutMs`, stop waiting once it elapses and return how
63
+ * many were still unsettled (abandoned) — so a continuation that never settles
64
+ * (e.g. an unbounded poll) can't hang an otherwise-bounded run. With no timeout,
65
+ * wait for them all (continuations are expected to be self-bounded via poll
66
+ * timeouts). The abandoned continuations keep running but are no longer awaited.
67
+ */
68
+ async function drainContinuations(continuations, drainTimeoutMs) {
69
+ const inflight = [...continuations]; // snapshot the still-in-flight continuations
70
+ if (inflight.length === 0)
71
+ return 0;
72
+ if (drainTimeoutMs === undefined) {
73
+ await Promise.allSettled(inflight);
74
+ return 0;
75
+ }
76
+ // Track settlement so we can count what the timeout abandons.
77
+ let settled = 0;
78
+ const tracked = inflight.map((p) => p.then(() => { settled += 1; }, () => { settled += 1; }));
79
+ let timer;
80
+ const timeout = new Promise((resolve) => { timer = setTimeout(resolve, drainTimeoutMs); });
81
+ await Promise.race([Promise.allSettled(tracked), timeout]);
82
+ if (timer !== undefined)
83
+ clearTimeout(timer);
84
+ return inflight.length - settled;
85
+ }
86
+ /**
87
+ * Resolve the continuation (bounded-open) config to its ms-normalized artifact
88
+ * form, applying the documented default backlog policy. Present only when the user
89
+ * configured `continuation`; the producer-release scheduling that consumes it is
90
+ * M6 (a bare `primaryComplete` without `releaseProducerSlot` ignores it).
91
+ */
92
+ function resolveContinuationConfig(c) {
93
+ if (c === undefined)
94
+ return undefined;
95
+ return {
96
+ ...(c.maxOutstanding !== undefined ? { maxOutstanding: c.maxOutstanding } : {}),
97
+ ...(c.maxConcurrent !== undefined ? { maxConcurrent: c.maxConcurrent } : {}),
98
+ ...(c.minPollInterval !== undefined ? { minPollIntervalMs: parseDurationMs(c.minPollInterval) } : {}),
99
+ ...(c.drainTimeout !== undefined ? { drainTimeoutMs: parseDurationMs(c.drainTimeout) } : {}),
100
+ // When a configured backlog bound is hit the default is to back-pressure the
101
+ // producer (`await primaryComplete` waits for capacity); `fail-iteration` is opt-in.
102
+ onBacklogFull: c.onBacklogFull ?? "block-producer",
103
+ };
104
+ }
105
+ /**
106
+ * Run a load plan locally and return its finalized `LoadArtifact`. Handles BOTH a
107
+ * single-scenario run and a traffic mix (`scenarios[]`): each is lowered to a list of
108
+ * weighted `Workload`s, and every iteration picks one (weighted-random for a mix, the
109
+ * sole workload otherwise). Throws on a plan with neither `duration` nor `iterations`
110
+ * (it would run forever). Closed model; continuation / pacing / thresholds are
111
+ * run-level (shared across a mix), per-scenario results attributed via each entry id.
112
+ */
113
+ export async function runLoad(plan, opts = {}) {
114
+ const config = plan.config;
115
+ const projection = plan.projection;
116
+ const { concurrency, durationMs, iterations, rampUpMs } = projection;
117
+ if (durationMs === undefined && iterations === undefined) {
118
+ throw new Error(`loadRunner "${plan.id}": set \`duration\` and/or \`iterations\` — a load run needs a termination bound`);
119
+ }
120
+ if (!Number.isInteger(concurrency) || concurrency < 1) {
121
+ throw new Error(`loadRunner "${plan.id}": concurrency must be a positive integer (got ${concurrency})`);
122
+ }
123
+ if (iterations !== undefined && (!Number.isInteger(iterations) || iterations < 1)) {
124
+ throw new Error(`loadRunner "${plan.id}": iterations must be a positive integer (got ${iterations})`);
125
+ }
126
+ if (durationMs !== undefined && (!Number.isFinite(durationMs) || durationMs <= 0)) {
127
+ throw new Error(`loadRunner "${plan.id}": duration must resolve to a positive number of ms (got ${durationMs})`);
128
+ }
129
+ const continuationCfg = resolveContinuationConfig(config.continuation);
130
+ if (continuationCfg?.maxOutstanding !== undefined && (!Number.isInteger(continuationCfg.maxOutstanding) || continuationCfg.maxOutstanding < 1)) {
131
+ throw new Error(`loadRunner "${plan.id}": continuation.maxOutstanding must be a positive integer (got ${continuationCfg.maxOutstanding})`);
132
+ }
133
+ if (continuationCfg?.maxConcurrent !== undefined && (!Number.isInteger(continuationCfg.maxConcurrent) || continuationCfg.maxConcurrent < 1)) {
134
+ throw new Error(`loadRunner "${plan.id}": continuation.maxConcurrent must be a positive integer (got ${continuationCfg.maxConcurrent})`);
135
+ }
136
+ // Report sample caps bound retained samples — a non-integer / negative / Infinity cap
137
+ // would break the bounded-sampling guarantee. 0 is allowed (disables that sample type).
138
+ const failureTraceCap = config.report?.failureTraces;
139
+ if (failureTraceCap !== undefined && (!Number.isInteger(failureTraceCap) || failureTraceCap < 0)) {
140
+ throw new Error(`loadRunner "${plan.id}": report.failureTraces must be a non-negative integer (got ${failureTraceCap})`);
141
+ }
142
+ const slowSummaryCap = config.report?.slowTransactionSummaries;
143
+ if (slowSummaryCap !== undefined && (!Number.isInteger(slowSummaryCap) || slowSummaryCap < 0)) {
144
+ throw new Error(`loadRunner "${plan.id}": report.slowTransactionSummaries must be a non-negative integer (got ${slowSummaryCap})`);
145
+ }
146
+ const now = opts.now ?? (() => Date.now());
147
+ const runnerId = opts.runnerId ?? plan.id;
148
+ const runId = opts.runId ?? runnerId;
149
+ const baseSession = opts.baseSession ?? {};
150
+ // Fail fast (once) with a clear message if the base session can't be deep-cloned,
151
+ // rather than throwing mid-run on the first iteration's copy.
152
+ try {
153
+ cloneSession(baseSession);
154
+ }
155
+ catch (e) {
156
+ throw new Error(`loadRunner "${plan.id}": baseSession must be structured-cloneable (no functions / class instances): ${e instanceof Error ? e.message : String(e)}`);
157
+ }
158
+ // Lower the plan to weighted workloads (one for a single scenario, one per mix entry).
159
+ // The runner-level `assertions.onFailure` default is shared; each entry's scenario /
160
+ // step meta can still override it during compilation.
161
+ const compileOpts = config.assertions?.onFailure !== undefined ? { defaultOnFailure: config.assertions.onFailure } : {};
162
+ // One stable counter key per SHARED feeder NAME, reused across the entries that draw it, so
163
+ // its draws advance run-globally. Keyed by name (not the binding) so two shared names that
164
+ // happen to reuse the same binding object stay independent slots (and single-scenario feeders
165
+ // each get their own per-name sequence regardless of binding reuse).
166
+ const sharedCounterKeys = new Map();
167
+ const sharedCounterKey = (name) => {
168
+ let key = sharedCounterKeys.get(name);
169
+ if (key === undefined) {
170
+ key = {};
171
+ sharedCounterKeys.set(name, key);
172
+ }
173
+ return key;
174
+ };
175
+ const makeWorkload = (ref, weight, scenarioRefId, sharedFeeders, entryFeeders, input) => {
176
+ const scenario = resolveScenario(ref);
177
+ const entry = entryFeeders ?? {};
178
+ const feeders = [];
179
+ // Shared (top-level) feeders the entry does NOT override: keyed per NAME, shared across
180
+ // the non-overriding entries → one run-global draw sequence. `Object.entries` +
181
+ // `hasOwnProperty` are own-prop only, so a feeder named `toString` survives (a
182
+ // `name in entry` check would drop it via Object.prototype).
183
+ for (const [name, binding] of Object.entries(sharedFeeders ?? {})) {
184
+ if (!Object.prototype.hasOwnProperty.call(entry, name)) {
185
+ feeders.push({ name, binding, counterKey: sharedCounterKey(name) });
186
+ }
187
+ }
188
+ // The entry's own feeders (entry wins a name clash): each gets a UNIQUE marker key, so
189
+ // two entries reusing the same binding object still draw independent per-entry sequences.
190
+ for (const [name, binding] of Object.entries(entry)) {
191
+ feeders.push({ name, binding, counterKey: {} });
192
+ }
193
+ return {
194
+ scenarioId: scenario.meta.id,
195
+ ...(scenarioRefId !== undefined ? { scenarioRefId } : {}),
196
+ compiled: compileLoadScenario(scenario, compileOpts),
197
+ feeders,
198
+ input,
199
+ weight,
200
+ };
201
+ };
202
+ let workloads;
203
+ if (isMixConfig(config)) {
204
+ const mix = config;
205
+ if (!Array.isArray(mix.scenarios) || mix.scenarios.length === 0) {
206
+ throw new Error(`loadRunner "${plan.id}": a traffic mix needs at least one entry in \`scenarios\``);
207
+ }
208
+ const seenIds = new Set();
209
+ workloads = mix.scenarios.map((entry) => {
210
+ if (typeof entry.id !== "string" || entry.id === "") {
211
+ throw new Error(`loadRunner "${plan.id}": every traffic-mix entry needs a non-empty \`id\``);
212
+ }
213
+ if (seenIds.has(entry.id)) {
214
+ throw new Error(`loadRunner "${plan.id}": duplicate traffic-mix entry id "${entry.id}" — ids attribute per-scenario results, so they must be unique`);
215
+ }
216
+ seenIds.add(entry.id);
217
+ if (!Number.isFinite(entry.weight) || entry.weight <= 0) {
218
+ throw new Error(`loadRunner "${plan.id}": traffic-mix entry "${entry.id}" weight must be a positive number (got ${entry.weight})`);
219
+ }
220
+ // Top-level feeders are shared (run-global draws); the entry's own are per-entry.
221
+ return makeWorkload(entry.scenario, entry.weight, entry.id, mix.feeders, entry.feeders, entry.input);
222
+ });
223
+ }
224
+ else {
225
+ // Single scenario: all feeders are "shared" (run-global) so the indexing is exactly
226
+ // the pre-mix behavior; there are no per-entry feeders.
227
+ const single = config;
228
+ workloads = [makeWorkload(single.scenario, 1, undefined, single.feeders, undefined, single.input)];
229
+ }
230
+ // Weighted scenario selection for a mix; the sole workload for a single scenario (no
231
+ // RNG draw, so a single-scenario run is byte-identical to before).
232
+ const random = opts.random ?? Math.random;
233
+ const totalWeight = workloads.reduce((sum, w) => sum + w.weight, 0);
234
+ const selectWorkload = () => {
235
+ if (workloads.length === 1)
236
+ return workloads[0];
237
+ let r = random() * totalWeight;
238
+ for (const w of workloads) {
239
+ r -= w.weight;
240
+ if (r < 0)
241
+ return w;
242
+ }
243
+ return workloads[workloads.length - 1]; // float-rounding safety net
244
+ };
245
+ const thinkTimeMs = normalizeThinkTime(config.pacing);
246
+ const reducer = createLoadReducer({
247
+ maxFailureTraces: config.report?.failureTraces,
248
+ maxSlowTransactionSummaries: config.report?.slowTransactionSummaries,
249
+ });
250
+ const sink = new LoadSink(reducer, runId, runnerId, now);
251
+ const core = createEngineCore(sink.handleWire, {
252
+ vars: opts.vars ?? {},
253
+ secrets: opts.secrets ?? {},
254
+ abortMode: config.abort ?? "precise",
255
+ });
256
+ // Run-level abort, handed to every iteration's engine run. Fired once at finalization
257
+ // (see the `finally` below) to truly CANCEL any continuation tail still in flight —
258
+ // its in-flight HTTP and engine poll/retry waits stop at once, instead of running to
259
+ // completion in the background after the drain phase stopped awaiting them. (Opaque
260
+ // user async — a bare `setTimeout` in a step — still can't be cancelled.)
261
+ const runAbort = new AbortController();
262
+ // Continuation backlog for producer release (M6). The pool bound is the tighter of
263
+ // maxOutstanding / maxConcurrent (every in-flight continuation is concurrently
264
+ // scheduled, so the two coincide); unset on both → unbounded. Default backlog
265
+ // policy is block-producer (back-pressure). Continuations from released iterations
266
+ // are drained before the run finalizes.
267
+ const continuationBound = continuationCfg?.maxOutstanding !== undefined && continuationCfg?.maxConcurrent !== undefined
268
+ ? Math.min(continuationCfg.maxOutstanding, continuationCfg.maxConcurrent)
269
+ : continuationCfg?.maxOutstanding ?? continuationCfg?.maxConcurrent;
270
+ const continuationPool = new ContinuationPool(continuationBound, continuationCfg?.onBacklogFull ?? "block-producer", continuationCfg?.drainTimeoutMs, now);
271
+ // In-flight continuations from released iterations. A Set with settle-time removal
272
+ // keeps only the CURRENTLY in-flight ones, so a long / high-rate run doesn't retain
273
+ // every released iteration's promise until the final drain.
274
+ const continuations = new Set();
275
+ // Peak concurrent continuation tails — including deadline-released ones the pool
276
+ // never admitted — so the reported backlog peak isn't understated.
277
+ let peakContinuations = 0;
278
+ const trackContinuation = (p) => {
279
+ continuations.add(p);
280
+ if (continuations.size > peakContinuations)
281
+ peakContinuations = continuations.size;
282
+ void p.finally(() => continuations.delete(p));
283
+ };
284
+ // Record the traffic-mix composition so the reducer can seed a 0-iteration aggregate for
285
+ // every configured entry (a low-weight entry that's never selected still shows up).
286
+ const mixScenarios = isMixConfig(config)
287
+ ? workloads.map((w) => ({ scenarioRefId: w.scenarioRefId, scenarioId: w.scenarioId, weight: w.weight }))
288
+ : undefined;
289
+ const resolvedConfig = {
290
+ concurrency,
291
+ ...(durationMs !== undefined ? { durationMs } : {}),
292
+ ...(iterations !== undefined ? { iterations } : {}),
293
+ ...(rampUpMs !== undefined ? { rampUpMs } : {}),
294
+ ...(thinkTimeMs !== undefined ? { pacing: { thinkTimeMs } } : {}),
295
+ ...(continuationCfg !== undefined ? { continuation: continuationCfg } : {}),
296
+ ...(mixScenarios !== undefined ? { scenarios: mixScenarios } : {}),
297
+ };
298
+ const start = now();
299
+ sink.emitLoadStart(resolvedConfig);
300
+ // Run-end coordination. Ramp-up / think-time waits are CANCELLABLE real timers:
301
+ // while a slot legitimately waits, its timer is ref'd (so a standalone Node run
302
+ // can't exit before it resolves), but the moment the run ends — iterations cap
303
+ // reached, or the duration deadline fires — every pending wait is cleared and
304
+ // resolved at once, so a slot never overruns the bound (late ramped slots that
305
+ // will claim nothing, or a think-time after the final iteration, wake instantly).
306
+ let ended = false;
307
+ const activeWaiters = new Map();
308
+ // The wall-clock (duration) deadline `closeImmediate()`s the pool: every parked
309
+ // producer is cancelled at once (the run's hard bound is up) and any later park is
310
+ // rejected immediately. The per-park `drainTimeout` bound is always-on in the pool
311
+ // (armed from when each producer parks, even before the run ends — so an
312
+ // all-producers-blocked backlog can't hang an iterations-bounded run), so the
313
+ // iterations cap needs no pool action here: a parked release self-bounds by its
314
+ // drainTimeout, or — with no drainTimeout — waits for capacity until either a
315
+ // continuation frees a slot or a duration deadline (if any) closes the pool.
316
+ const markEnded = (wallClockUp = false) => {
317
+ const firstEnd = !ended;
318
+ if (firstEnd) {
319
+ ended = true;
320
+ for (const [timer, resolve] of activeWaiters) {
321
+ clearTimeout(timer);
322
+ resolve();
323
+ }
324
+ activeWaiters.clear();
325
+ }
326
+ if (wallClockUp)
327
+ continuationPool.closeImmediate();
328
+ };
329
+ // A duration deadline timer wakes ramp/think waiters at the bound even if no slot
330
+ // happens to claim (and thus re-check) right then.
331
+ let deadlineTimer;
332
+ if (durationMs !== undefined)
333
+ deadlineTimer = setTimeout(() => markEnded(true), durationMs);
334
+ /** Wait `ms`, returning early the instant the run ends (never overruns the bound). */
335
+ const pausedSleep = (ms) => {
336
+ if (ms <= 0 || ended)
337
+ return Promise.resolve();
338
+ return new Promise((resolve) => {
339
+ const timer = setTimeout(() => {
340
+ activeWaiters.delete(timer);
341
+ resolve();
342
+ }, ms);
343
+ activeWaiters.set(timer, resolve);
344
+ });
345
+ };
346
+ // The shared, monotonically-claimed global iteration counter. A slot claims the
347
+ // next index before running; -1 means the run is over. Single-threaded JS makes
348
+ // the claim atomic.
349
+ let claimed = 0;
350
+ const durationExpired = () => durationMs !== undefined && now() - start >= durationMs;
351
+ const claimIteration = () => {
352
+ // The deadline timer can flip `ended` independently of the (possibly frozen /
353
+ // injected) clock, so honour it directly — not just `durationExpired()`.
354
+ if (ended)
355
+ return -1;
356
+ if (durationExpired()) {
357
+ markEnded(true); // duration bound hit on a claim → wall-clock is up
358
+ return -1;
359
+ }
360
+ if (iterations !== undefined && claimed >= iterations) {
361
+ markEnded();
362
+ return -1;
363
+ }
364
+ const index = claimed++;
365
+ // Claiming the last iteration ends the run — wake any ramp/think waiters now.
366
+ if (iterations !== undefined && claimed >= iterations)
367
+ markEnded();
368
+ return index;
369
+ };
370
+ /**
371
+ * Start one iteration's PRIMARY phase. Returns its handle (the producer slot is
372
+ * freed when `primaryDone` resolves), or `"skip"` (feeder opt-out, not counted) /
373
+ * `"failed"` (a setup failure recorded as a started+failed iteration). The slot
374
+ * loop awaits the handle's `primaryDone`; with producer release that resolves at
375
+ * the boundary so the slot can start the next primary while the continuation runs.
376
+ */
377
+ const startOneIteration = (slotIndex, producerSlotId, globalIteration, slotIteration, workload, feederSlotDraws) => {
378
+ const iterationId = `it-${globalIteration}`;
379
+ const producerSlot = { id: producerSlotId, index: slotIndex };
380
+ const iteration = { id: iterationId, index: globalIteration };
381
+ const envelope = {
382
+ scenarioId: workload.scenarioId,
383
+ ...(workload.scenarioRefId !== undefined ? { scenarioRefId: workload.scenarioRefId } : {}),
384
+ producerSlotId,
385
+ iterationId,
386
+ };
387
+ // `globalIteration`/`slotIteration` keep their public contract — the REAL run-global and
388
+ // per-slot iteration indices (so a custom feeder reading them is unaffected by mix
389
+ // scheduling). The built-in feeders index by `drawIndex`/`slotDrawIndex` instead: ITS OWN
390
+ // per-binding draw count, so a binding shared across entries advances run-wide while a
391
+ // per-entry (or partially-overridden) binding advances only when its entry runs — correct
392
+ // even when only some entries override a shared name (codex). For a single scenario a
393
+ // feeder is drawn every iteration, so its draw count equals the iteration index.
394
+ const drawCtxFor = (counterKey) => {
395
+ const g = feederGlobalDraws.get(counterKey) ?? 0;
396
+ feederGlobalDraws.set(counterKey, g + 1);
397
+ const s = feederSlotDraws.get(counterKey) ?? 0;
398
+ feederSlotDraws.set(counterKey, s + 1);
399
+ return { producerSlot: slotIndex, producerCount: concurrency, slotIteration, globalIteration, drawIndex: g, slotDrawIndex: s };
400
+ };
401
+ const failSetup = () => {
402
+ // A setup-time failure (feeder exhausted / input threw) still counts as a
403
+ // started+failed iteration so the artifact reflects it.
404
+ sink.beginIteration(envelope);
405
+ sink.emitIterationStart(envelope, {});
406
+ sink.emitIterationEnd(envelope, { ok: false, durationMs: 0, errorKind: "setupError" });
407
+ sink.endIteration(iterationId);
408
+ return "failed";
409
+ };
410
+ // Feeder allocation + input resolution are the iteration's SETUP. Any failure
411
+ // here (a feeder exhausted under `fail`, a feeder `allocate()` that throws, or a
412
+ // throwing `input` fn) becomes a recorded failed iteration — it must never
413
+ // escape and reject the whole run.
414
+ const feed = {};
415
+ const feederKeys = {};
416
+ let input;
417
+ let skipped = false;
418
+ try {
419
+ for (const { name, binding, counterKey } of workload.feeders) {
420
+ const draw = binding.allocate(drawCtxFor(counterKey));
421
+ if (draw.outcome === "value") {
422
+ feed[name] = draw.value;
423
+ if (draw.key !== undefined)
424
+ feederKeys[name] = draw.key;
425
+ }
426
+ else if (draw.outcome === "skip" || draw.outcome === "wait") {
427
+ // `skip`/`wait`: the iteration opts out (wait-and-retry isn't modelled in
428
+ // the closed MVP — both just skip). Not a failure, not counted.
429
+ skipped = true;
430
+ break;
431
+ }
432
+ else {
433
+ return failSetup(); // exhausted (fail policy)
434
+ }
435
+ }
436
+ if (skipped)
437
+ return "skip";
438
+ input =
439
+ typeof workload.input === "function"
440
+ ? workload.input({
441
+ row: plan.row,
442
+ feed,
443
+ producerSlot,
444
+ iteration,
445
+ })
446
+ : (workload.input ?? {});
447
+ }
448
+ catch {
449
+ return failSetup();
450
+ }
451
+ return startLoadIteration({
452
+ core,
453
+ sink,
454
+ scenario: workload.compiled,
455
+ envelope,
456
+ input,
457
+ producerSlot,
458
+ iteration,
459
+ session: cloneSession(baseSession), // copy-on-write: each iteration gets its own (deep)
460
+ ...(Object.keys(feederKeys).length > 0 ? { feederKeys } : {}),
461
+ now,
462
+ continuation: { pool: continuationPool },
463
+ signal: runAbort.signal,
464
+ });
465
+ };
466
+ // Run-global per-feeder draw count, keyed by each feeder slot's `counterKey` (a shared
467
+ // feeder's binding object, or an entry feeder's unique marker — see WorkloadFeeder).
468
+ // Shared across slots, so a shared feeder advances run-wide while a per-entry slot advances
469
+ // only on its entry's turns. Feeds `drawIndex` (built-in uniquePerIteration / roundRobin).
470
+ const feederGlobalDraws = new Map();
471
+ const runSlot = async (slotIndex) => {
472
+ if (rampUpMs !== undefined) {
473
+ await pausedSleep(rampDelayMs(slotIndex, concurrency, rampUpMs));
474
+ }
475
+ sink.emitProducerSlotStart(slotIndex);
476
+ const producerSlotId = `p${slotIndex}`;
477
+ // Per-slot iteration index (the `slotIteration` public contract field), and per-slot
478
+ // per-feeder draw counts (what partitionByVu actually indexes by, via `slotDrawIndex`).
479
+ let slotIteration = 0;
480
+ const feederSlotDraws = new Map();
481
+ let primaryIterations = 0;
482
+ for (;;) {
483
+ const globalIteration = claimIteration();
484
+ if (globalIteration < 0)
485
+ break;
486
+ // Pick this iteration's workload (weighted-random for a mix, the sole one for a single
487
+ // scenario); the feeders it draws advance their own per-binding counters (see drawCtxFor).
488
+ const workload = selectWorkload();
489
+ const started = startOneIteration(slotIndex, producerSlotId, globalIteration, slotIteration, workload, feederSlotDraws);
490
+ slotIteration += 1;
491
+ if (started !== "skip") {
492
+ // A real (or failed-setup) primary iteration.
493
+ if (started !== "failed") {
494
+ // Hold the slot until the primary phase finishes: at the producer-release
495
+ // boundary (then the continuation drains in the background) or, with no
496
+ // release, at full completion (closed model).
497
+ const { released } = await started.primaryDone;
498
+ if (released)
499
+ trackContinuation(started.completed);
500
+ }
501
+ primaryIterations += 1;
502
+ }
503
+ // Pace EVERY slot turn — including a feeder skip/wait — so an exhausted
504
+ // skip/wait feeder doesn't spin the loop in a paced run.
505
+ if (thinkTimeMs !== undefined)
506
+ await pausedSleep(thinkDelay(thinkTimeMs));
507
+ }
508
+ sink.emitProducerSlotEnd(slotIndex, primaryIterations);
509
+ };
510
+ let abortedByDrainTimeout = 0;
511
+ try {
512
+ await Promise.all(Array.from({ length: concurrency }, (_, i) => runSlot(i)));
513
+ abortedByDrainTimeout = await drainContinuations(continuations, continuationCfg?.drainTimeoutMs);
514
+ }
515
+ finally {
516
+ if (deadlineTimer !== undefined)
517
+ clearTimeout(deadlineTimer);
518
+ // All primaries are done and the drain phase has run; abort whatever continuation
519
+ // tail is still in flight so its in-flight HTTP / engine poll waits stop NOW rather
520
+ // than running on in the background. A tail that already settled (drain awaited it,
521
+ // or there was no drainTimeout) makes this a no-op. The aborted tails settle on later
522
+ // microtasks — after the synchronous `seal()` below — so their late events are still
523
+ // dropped, leaving the artifact unchanged; only the wasted in-flight work is cut.
524
+ runAbort.abort();
525
+ }
526
+ const endReason = iterations !== undefined && claimed >= iterations ? "iterations" : durationMs !== undefined ? "duration" : "iterations";
527
+ sink.emitLoadEnd(endReason);
528
+ // Seal the sink so a continuation the drain timeout abandoned can't emit into the
529
+ // reducer after the artifact is built. The `runAbort.abort()` above already cancelled
530
+ // its in-flight HTTP / engine poll waits, so a tail settles promptly; seal is the
531
+ // backstop for the late events that abort can't pre-empt (e.g. a bare `setTimeout` in
532
+ // user code, which no signal can cancel) and for the settle that lands post-seal.
533
+ sink.seal();
534
+ const artifact = reducer.finalize();
535
+ // Continuations the drain timeout abandoned are still in flight at finalize —
536
+ // surface them (the reducer can't know the orchestrator's drain decision).
537
+ if (artifact.summary.continuation) {
538
+ const c = artifact.summary.continuation;
539
+ // The orchestrator saw the true peak of concurrent tails (incl. deadline-released
540
+ // ones the pool never admitted, so the reducer's maxBacklog can't see them).
541
+ c.maxBacklog = Math.max(c.maxBacklog, peakContinuations);
542
+ c.maxConcurrent = Math.max(c.maxConcurrent, peakContinuations);
543
+ if (abortedByDrainTimeout > 0) {
544
+ c.abortedByDrainTimeout = abortedByDrainTimeout;
545
+ c.backlog = abortedByDrainTimeout;
546
+ c.active = abortedByDrainTimeout;
547
+ artifact.runtime.continuationInFlight = abortedByDrainTimeout;
548
+ }
549
+ }
550
+ // Advisory: some iteration ran a long TAIL poll but didn't request producer release,
551
+ // so its slot stayed tied up for the whole tail (closed end-to-end scheduling), under-
552
+ // pressuring the upstream. The sink decides this PER ITERATION (`unreleasedTailPollRan`):
553
+ // - a TAIL poll (a step-scoped request before it, none after) — excludes a poll in an
554
+ // untaken branch (never runs) and a readiness/token poll before the primary request;
555
+ // - in an iteration that did NOT ask for release — a bare `primaryComplete()` still
556
+ // gets advised, but a requested-but-rejected release does not (they already asked),
557
+ // and a row that releases doesn't mute the advisory for a sibling row that doesn't.
558
+ if (sink.unreleasedTailPollRan) {
559
+ (artifact.summary.advisories ??= []).push("Most producer slot time is spent after the primary request; closed end-to-end scheduling may reduce upstream pressure. Call `await ctx.report.primaryComplete(..., { releaseProducerSlot: true })` after the primary load is issued if you want sustained ingress pressure.");
560
+ }
561
+ // Evaluate configured thresholds against the finalized artifact and refine the pass
562
+ // verdict (a crash-free run still fails if a threshold is breached). Thresholds are
563
+ // run-level — for a mix they apply to the aggregate, not per scenario.
564
+ if (config.thresholds !== undefined) {
565
+ const { thresholds, pass } = evaluateThresholds(artifact, config.thresholds);
566
+ artifact.summary.thresholds = thresholds;
567
+ artifact.summary.pass = pass;
568
+ }
569
+ return artifact;
570
+ }
571
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/load/orchestrator.ts"],"names":[],"mappings":"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"}