Repository navigation
Resolve WinGet search results in parallel and once per package - #5687
Gabriel Dufresne (GabrielDuf) wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
A stop/search cancellation race can trigger unintended WinGet repair and cache clearing, while concurrent metadata resolution lacks deterministic tests for duplicate handling, output ordering, cache consistency, and cancellation.
2 open issues
What changed in this PR
This PR addresses #5040 by parallelizing WinGet search metadata reads and resolving each package once, while preserving applicable-version selection and result ordering.
Changes:
- Resolves metadata with up to eight workers, deduplicates overlapping matches, and summarizes read failures.
- Adds per-listing cancellation on timeout and explicit stop.
- Adds tests for cancellation, token isolation, and deduplication ordering.
| File | Description |
|---|---|
src/UniGetUI.PackageEngine.Tests/WinGetManagerTests.cs |
Tests deduplication, ordering, unreadable IDs, and casing. |
src/UniGetUI.PackageEngine.Tests/PackageManagerTests.cs |
Tests listing cancellation and token isolation. |
src/UniGetUI.PackageEngine.Tests/Infrastructure/Fakes/TestPackageManager.cs |
Exposes cancellation and configurable timeouts for tests. |
src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs |
Manages cancellation tokens alongside listing processes. |
src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs |
Exposes listing cancellation to the native helper. |
src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/NativeWinGetHelper.cs |
Resolves unique search results concurrently with cancellation and summarized errors. |
Review effort: Balanced
There was a problem hiding this comment.
🔵 Needs a closer look
Parallel WinGet COM property reads still need Windows compatibility validation on supported older WinGet versions and lower-trust activation paths, which the reported A/B run and fake-reader tests do not verify.
No open issues 🎉
2 resolved since last review
Review effort: Balanced
There was a problem hiding this comment.
🤖 Pull request was approved automatically: the AI review is complete and all its review threads are resolved. 🎉
Integration Details
{
"deliveryId": "2cb9aca0-d946-11f1-81b8-0a680e0f20d6",
"headSha": "3a1db9b1755a1e4bd6cc758694f3ad91c227b292",
"reviewer": "copilot-pull-request-reviewer[bot]"
}
Fixes #5040.
Why WinGet search was slow
Through the COM API, the search read
CatalogPackage.DefaultInstallVersionfor every match, one at a time. On the winget source's V2 index that property returns the newest version that isn't pinned and has an installer this machine can use. Deciding that means downloading the package'sversionData.mszymland its manifest from the CDN. A search for "firefox" made 630 sequential requests for 315 packages, whilewinget searchreads the version from its local index and downloads nothing. Each package was also processed up to 3 times, because the Name, Id and Moniker queries run separately and overlap (941 matches for 316 packages).Behind a slow proxy this goes past the 60 s listing timeout. The search is then retried once and shows no results, which is what the reporters described.
Change
(catalog, id)pair resolves its name and version, so duplicates are never resolved twice. Results keep the order of their first occurrence (SelectUniqueSearchMatches, unit-tested).DefaultInstallVersionis kept on purpose.AvailableVersions[0]would skip the manifest download, but it ignoreswinget pinand installer applicability, so the displayed version would change.StopRunningListings, so an abandoned search stops instead of running alongside its retry.AttemptFastRepair, which reconnects the COM server and clearsNativePackageHandlerover a single transient failure.Verification
A/B against the previous build: winget's download cache was cleared before each run, then 10 queries were searched (thunderbird, firefox, vlc, discord, spotify, python, visual studio, 7zip, chrome, netflix). Results were identical: 590 lines with the same packages, versions, catalogs and order, all 14 msstore entries included.
The download count is unchanged; the downloads now overlap.
New tests: cancellation on stop, on timeout (made overridable for the test; confirmed to fail when the cancel is removed), one token per listing, no token outside a listing, and dedupe ordering, unreadable matches and id casing.
Full
UniGetUI.PackageEngine.Tests: passes (2136 + 3157; 9 opt-in E2E tests skipped). Bothdotnet formatgates exit 0.Not covered
The 60 s timeout should now be far harder to hit, but a very broad query behind a high-latency proxy still needs one version-data and one manifest download per result. Removing that cost entirely would mean showing the index's latest version in search results instead of winget's applicable one, which is a separate decision.
🤖 Generated with Claude Code