Skip to content

fix: use idle() instead of length() to guard queue drain#1236

Merged
scolladon merged 1 commit intomainfrom
fix/non-deterministic-queue-drain
Mar 3, 2026
Merged

fix: use idle() instead of length() to guard queue drain#1236
scolladon merged 1 commit intomainfrom
fix/non-deterministic-queue-drain

Conversation

@scolladon
Copy link
Owner

Explain your changes

Race condition fix in DiffLineInterpreter.process(). The async.queue.length() method only counts items waiting in the queue, not items currently being processed by workers. When all items were dequeued but workers were still running, length() returned 0 and drain() was skipped — causing the method to return incomplete results non-deterministically.

Replaced processor.length() > 0 with !processor.idle(), which correctly checks both waiting AND running items.

Note: drain() cannot be called unconditionally because it hangs forever on an already-idle queue in async@3.x. The guard is necessary but must use idle() instead of length().

Does this close any currently open issues?

closes #1235

  • Jest tests added to cover the fix.
  • NUT tests added to cover the fix.
  • E2E tests added to cover the fix.

Any particular element that can be tested locally

Run npx jest __tests__/unit/lib/service/diffLineInterpreter.test.ts — the new test "Given slow handlers, When queue workers finish after enqueuing, Then all results are collected" verifies that delayed handler results are fully collected.

Any other comments

Root cause analysis:

Queue state length() running() idle() Old guard Correct behavior
No items pushed 0 0 true skip drain ✓ skip drain
Items queued, not started >0 0 false await drain ✓ await drain
All dequeued, still running 0 >0 false skip drain ✗ await drain
All done 0 0 true skip drain ✓ skip drain

Controlled test showed 100% failure with the old guard vs 0% failure with !idle().

queue.length() only counts items waiting in the queue, not items
currently being processed by workers. When all items are dequeued
but still running, length() returns 0 and drain() is skipped,
causing non-deterministic incomplete results.

queue.idle() correctly checks both waiting AND running items.
@scolladon scolladon requested a review from mehdicherf as a code owner March 3, 2026 21:20
@github-actions
Copy link

github-actions bot commented Mar 3, 2026

Published under dev-1236 npm channel.

$ sf plugins install sf-git-merge-driver@dev-1236

@scolladon scolladon merged commit de82ee4 into main Mar 3, 2026
19 of 21 checks passed
@scolladon scolladon deleted the fix/non-deterministic-queue-drain branch March 3, 2026 21:29
@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (c6c20ab) to head (26471f8).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1236   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           58        58           
  Lines         1544      1544           
  Branches       194       194           
=========================================
  Hits          1544      1544           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link

github-actions bot commented Mar 4, 2026

Shipped in release v6.33.0.
Version v6.33.0 will be assigned to the latest npm channel soon
Install it using either v6.33.0 or the latest-rc npm channel

$ sf plugins install sfdx-git-delta@latest-rc
# Or
$ sf plugins install sfdx-git-delta@v6.33.0

💡 Enjoying sfdx-git-delta?
Your contribution helps us provide fast support 🚀 and high quality features 🔥
Become a sponsor 💙
Happy incremental deployment!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Non-deterministic CustomLabels handling in delta deployment

1 participant