Module: utils/shardConfig

CAP-002 — Single source of truth for the per-request shard

  • parallel-worker normalization used by both /run and /trigger.

Replaces the verbatim copy of the clamp + decoupling logic that previously lived in routes/runs.js and routes/trigger.js. Per AGENT.md pre-flight rule #4 ("if a helper is used by ≥2 call sites, put it in utils/"), this lives here as a pure function so both entry points apply identical semantics.

Contract — BUG-0001 decoupling

shardCount and parallelWorkers are independent concepts:

  • shardCount — cross-process partition count. Only > 1 when the caller explicitly passed shards: N. Drives the per-shard progress badge on RunDetail and the BullMQ job fan-out. Cross-shard parallelism comes from BullMQ's worker pool (concurrency: MAX_WORKERS in backend/src/workers/runWorker.js); each shard runs in its own job and is picked up by a separate worker slot.
  • parallelWorkers — concurrency inside one shard's process (the in-shard test pool). Reflects only the dials input; defaults to 1.

shardCount and parallelWorkers are independent — total concurrent browser instances on one replica is bounded by MAX_WORKERS × parallelWorkers, NOT shardCount × parallelWorkers. The previous formula max(shardCount, dialsParallelWorkers) re-coupled the two and produced surprising N² concurrency for callers requesting shards: 4 without an explicit dials override (one slot per shard × 4 internal workers per shard = 16 browsers). Decoupled here so shards: 4 with no dials input gives 4× cross-process parallelism at 1 browser per shard — the operator-intuitive shape.

A request that only sets dialsConfig.parallelWorkers: 4 leaves shardCount = 1 so no shard badge is shown (BUG-0001 — discovered during the CAP-002 review pass).

shards is clamped to [1, WORKER_CONCURRENCY] server-side regardless of input type. Non-numeric / negative / fractional values fall back to 1.

The upper bound is read from WORKER_CONCURRENCY with MAX_WORKERS as a backward-compatible fallback — the same precedence the BullMQ worker uses in backend/src/workers/runWorker.js. Without this mirror, a deployment that sets WORKER_CONCURRENCY=8 (AUTO-008's preferred knob) but leaves MAX_WORKERS unset would silently clamp shards: 8 requests down to 2, wasting 6 worker slots.

Parameters:
Name Type Attributes Description
shardsInput unknown

Raw req.body.shards (any type).

dialsParallelWorkers number | null <optional>

Validated dials request, may be undefined.

Source:
Returns:
Type
Object