Skip to content

[rush-lib] Fix weighted concurrency budget being capped by operation count#5646

Open
itsnothuy wants to merge 2 commits intomicrosoft:mainfrom
itsnothuy:fix/weighted-concurrency-cap
Open

[rush-lib] Fix weighted concurrency budget being capped by operation count#5646
itsnothuy wants to merge 2 commits intomicrosoft:mainfrom
itsnothuy:fix/weighted-concurrency-cap

Conversation

@itsnothuy
Copy link

Summary

Fixes #5607 — resolves a weighted scheduling bug where the concurrency unit budget was incorrectly capped by the number of operations.

Background

When Rush uses weighted scheduling (Operation.weight > 1), the concurrency parameter in Async.forEachAsync represents a unit budget, not a task count. However, OperationExecutionManager was passing Math.min(totalOperations, parallelism), which shrinks the budget when totalOperations < parallelism.

Example: 4 operations with weight=4, parallelism=10:

  • Before: concurrency = min(4, 10) = 4 → only 1 operation fits → sequential execution
  • After: concurrency = 10 → 2 operations fit (4+4=8 ≤ 10) → parallel execution

This was reported by @LPegasus in issue #5607.

Changes

1. Fix: OperationExecutionManager.ts

  • Separated the display calculation from the scheduler's concurrency value
  • Display message now uses Math.min(totalOperations, parallelism) to avoid confusing messages like "max 10 processes" when only 4 operations exist (a UX improvement over the old code which showed raw this._parallelism)
  • Scheduler receives this._parallelism directly as the full unit budget (the core fix)

2. Tests: OperationExecutionManager.test.ts

Added 9 new tests in a "Weighted concurrency" describe block:

  1. Regression test — core bug reproduction (4 ops × w=4, p=10 → peak=2)
  2. Weight clamping — weight > budget completes without deadlock
  3. Oversubscription enabled — w=7×2, p=10 → both run concurrently
  4. Oversubscription disabled — w=7×2, p=10 → serialized
  5. Zero-weight operations — don't consume budget
  6. Mixed weights — budget accounting with varying weights
  7. Backwards compatibility — weight=1 behaves like unweighted
  8. Display message — shows capped count when parallelism > ops
  9. Display message — shows parallelism when parallelism < ops

All tests are deterministic (no timing dependencies) and use Async.sleepAsync(0) to yield control to the scheduler.

Impact

  • No API changes — purely internal fix
  • Backwards compatible — when all weights=1 (default), behavior is identical
  • No schema changes — no config file modifications needed

Testing

  • All 581 rush-lib tests pass (0 failures)
  • 9 new weighted concurrency tests pass
  • Existing snapshot tests unchanged
  • Local build: rush build --to rush-lib succeeds
  • No public API surface changes

Scope

This PR addresses only the scheduling bug. The "weight": "NN%" feature (Proposal 1 in #5607) is intentionally excluded — it requires schema changes and maintainer design approval, so it should be a separate PR.

Checklist

  • Read CONTRIBUTING.md and followed all guidelines
  • Added comprehensive tests with clear scenarios
  • Ran rush build --to rush-lib locally (passes)
  • Ran rush change and committed change file
  • Verified no public API changes
  • PR description explains the problem, solution, and testing
  • Signed Microsoft CLA

…count

test(rush-lib): expand weighted concurrency edge case tests

test(rush-lib): expand weighted concurrency edge case tests

refactor(OperationExecutionManager.test): align comment and naming style with codebase conventions

- Replace // ─── section banners and // Test N: numbered headers with brief
  inline prose comments matching the existing test file style
- Replace // WHAT: / // SCENARIO: / // DETERMINISM: structured blocks with
  concise inline comments
- Rename createWeightedOp → createWeightedOperation for consistency with
  other helper names (createExecutionManager, etc.)
- Rename counters.active / counters.peak → counters.concurrentCount /
  counters.peakConcurrency for self-documenting field names
- Extract new AbortController() calls into named abortController variables
  matching the pattern used throughout the rest of the test file
- No logic or assertion changes; all 18 tests continue to pass

chore: add rush change file for @microsoft/rush-lib weighted concurrency fix

refactor: reduce test comment density to match codebase patterns
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a weighted scheduling bug in rush-lib where the concurrency unit budget was being incorrectly reduced to the number of operations, preventing expected parallelism when Operation.weight > 1.

Changes:

  • Pass the full parallelism value as the weighted scheduler’s concurrency unit budget (no longer capped by operation count).
  • Improve the startup log message to cap the displayed “simultaneous processes” count by the number of operations (UX clarity).
  • Add a comprehensive Jest test suite covering weighted concurrency behaviors (regression, clamping, oversubscription, mixed/zero weights, and display output).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
libraries/rush-lib/src/logic/operations/OperationExecutionManager.ts Fixes the weighted scheduler’s concurrency budget and separates display calculation from scheduling.
libraries/rush-lib/src/logic/operations/test/OperationExecutionManager.test.ts Adds deterministic test coverage for weighted concurrency scenarios and logging output.
common/changes/@microsoft/rush-lib/fix_weighted-concurrency-cap_2026-02-19-07-57.json Patch change file documenting the fix for release notes/versioning.

@itsnothuy
Copy link
Author

@itsnothuy please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree

@iclanton
Copy link
Member

@dmichon-msft - mind reviewing this?

@itsnothuy
Copy link
Author

@dmichon-msft - mind reviewing this?

Any updates on PR status?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs triage

Development

Successfully merging this pull request may close these issues.

[rush] Improve task scheduler to handle tasks that consume 100% CPU

3 participants