velocious 1.0.690 → 1.0.691

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "velocious": "build/bin/velocious.js"
4
4
  },
5
5
  "name": "velocious",
6
- "version": "1.0.690",
6
+ "version": "1.0.691",
7
7
  "main": "build/index.js",
8
8
  "types": "build/index.d.ts",
9
9
  "files": [
@@ -1617,7 +1617,11 @@ export default class BackgroundJobsWorker {
1617
1617
  * whole drain window, which can stretch to the longest in-flight job. The
1618
1618
  * retiring child stops receiving new jobs and is terminated only once its
1619
1619
  * in-flight set drains, so a long-running job (e.g. a build) is never cut
1620
- * off.
1620
+ * off. When the pool already carries its bounded over-cap child, retiring
1621
+ * the last working child is deferred instead of emptying the working pool:
1622
+ * the child keeps serving and a later observation retries the retirement
1623
+ * once a draining exit has freed a cap slot, so advertised capacity cannot
1624
+ * collapse to zero inside a wave.
1621
1625
  * @param {import("node:child_process").ChildProcess} child - Child to retire.
1622
1626
  * @returns {void}
1623
1627
  */
@@ -1625,6 +1629,17 @@ export default class BackgroundJobsWorker {
1625
1629
  const state = this.pooledChildStates.get(child)
1626
1630
  if (!state || state.retiring) return
1627
1631
 
1632
+ // Retiring the last non-retiring child while the pool already carries its
1633
+ // bounded over-cap child would leave advertised capacity at zero until the
1634
+ // next draining exit — up to the longest in-flight job (tens of minutes
1635
+ // with builds), stalling dispatch cluster-wide. Defer this retirement
1636
+ // instead: the child keeps serving and a later observation retries once a
1637
+ // drain has freed a cap slot for its replacement.
1638
+ if (!this.shouldStop && this.configuration && this._nonRetiringPooledChildCount() <= 1 && this.pooledChildren.size > this.pooledRunnerCount) {
1639
+ this._logPooledCapacityEvent("pooled-capacity-retirement-deferred")
1640
+ return
1641
+ }
1642
+
1628
1643
  state.retiring = true
1629
1644
  // Best-effort pre-warm: skip when stopping (no new work) or before the
1630
1645
  // worker is initialized (no configuration to fork a child from). The cap
@@ -1688,9 +1703,11 @@ export default class BackgroundJobsWorker {
1688
1703
  * surface that reaches the production log). Used by the bounded liveness
1689
1704
  * replacement in `_ensureNonRetiringChild`: the spawn that keeps dispatch
1690
1705
  * alive through a full retirement wave (at a retirement mark or a child
1691
- * exit), or the bounded starvation when an over-cap child is already
1692
- * draining and the pool must wait for an exit.
1693
- * @param {"pooled-capacity-liveness-spawn" | "pooled-capacity-starved"} event - Event name.
1706
+ * exit), the deferred retirement of the last working child while the pool
1707
+ * already carries its bounded over-cap child (retried after the next drain
1708
+ * frees a cap slot), or the bounded starvation when an over-cap child is
1709
+ * already draining and the pool must wait for an exit.
1710
+ * @param {"pooled-capacity-liveness-spawn" | "pooled-capacity-starved" | "pooled-capacity-retirement-deferred"} event - Event name.
1694
1711
  * @returns {void}
1695
1712
  */
1696
1713
  _logPooledCapacityEvent(event) {