diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index 1a074b67e..72b1cc60a 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -1168,8 +1168,14 @@ private string FormatPkgVersionString(PSResourceInfo pkg) internal IEnumerable FindDependencyPackages(ServerApiCall currentServer, ResponseUtil currentResponseUtil, PSResourceInfo currentPkg, PSRepositoryInfo repository) { depPkgsFound = new ConcurrentDictionary(); - _cmdletPassedIn.WriteDebug($"In FindHelper::FindDependencyPackages() - {currentPkg.Name}"); - FindDependencyPackagesHelper(currentServer, currentResponseUtil, currentPkg, repository); + ConcurrentQueue errorMsgs = new ConcurrentQueue(); + ConcurrentQueue verboseMsgs = new ConcurrentQueue(); + ConcurrentQueue debugMsgs = new ConcurrentQueue(); + ConcurrentQueue warningMsgs = new ConcurrentQueue(); + + _cmdletPassedIn.WriteDebug($"In FindHelper::FindDependencyPackages() - {currentPkg.Name}"); + FindDependencyPackagesHelper(currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); + Utils.WriteOutConcurrentQueue(_cmdletPassedIn, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); return depPkgsFound.Values.ToList(); } @@ -1181,15 +1187,30 @@ internal void FindDependencyPackagesHelper(ServerApiCall currentServer, Response ConcurrentQueue verboseMsgs = new ConcurrentQueue(); ConcurrentQueue debugMsgs = new ConcurrentQueue(); ConcurrentQueue warningMsgs = new ConcurrentQueue(); + + FindDependencyPackagesHelper(currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); + Utils.WriteOutConcurrentQueue(_cmdletPassedIn, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); + } + + private void FindDependencyPackagesHelper( + ServerApiCall currentServer, + ResponseUtil currentResponseUtil, + PSResourceInfo currentPkg, + PSRepositoryInfo repository, + ConcurrentQueue errorMsgs, + ConcurrentQueue warningMsgs, + ConcurrentQueue debugMsgs, + ConcurrentQueue verboseMsgs) + { debugMsgs.Enqueue("In FindHelper::FindDependencyPackagesHelper()"); if (currentPkg.Dependencies.Length > 0) { - // If finding more than 5 packages, do so concurrently - //const int PARALLEL_THRESHOLD = 5; // TODO: Trottle limit from user, defaults to 5; int processorCount = Environment.ProcessorCount; + // Use parallel dependency resolution for V2 repositories when the dependency count exceeds the processor count. + int parallelThreshold = InternalHooks.FindDependencyPackagesParallelThreshold >= 0 ? InternalHooks.FindDependencyPackagesParallelThreshold : processorCount; int maxDegreeOfParallelism = processorCount * 4; - if (currentServer.Repository.ApiVersion == PSRepositoryInfo.APIVersion.V2 && currentPkg.Dependencies.Length > processorCount) + if (currentServer.Repository.ApiVersion == PSRepositoryInfo.APIVersion.V2 && currentPkg.Dependencies.Length > parallelThreshold) { Parallel.ForEach(currentPkg.Dependencies, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, dep => { @@ -1205,8 +1226,6 @@ internal void FindDependencyPackagesHelper(ServerApiCall currentServer, Response FindDependencyPackageVersion(dep, currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); } } - - Utils.WriteOutConcurrentQueue(_cmdletPassedIn, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); } } @@ -1343,7 +1362,7 @@ private PSResourceInfo FindDependencyWithSpecificVersion( // This will eventually return the PSResourceInfo object to the main cmdlet class. debugMsgs.Enqueue($"Adding'{key}' to list of dependency packages found"); depPkgsFound.TryAdd(key, depPkg); - FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository); + FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); } } } @@ -1418,7 +1437,7 @@ private PSResourceInfo FindDependencyWithLowerBound( // This will eventually return the PSResourceInfo object to the main cmdlet class. debugMsgs.Enqueue($"Adding'{key}' to list of dependency packages found"); depPkgsFound.TryAdd(key, depPkg); - FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository); + FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); } } } @@ -1497,7 +1516,7 @@ private PSResourceInfo FindDependencyWithUpperBound( // This will eventually return the PSResourceInfo object to the main cmdlet class. debugMsgs.Enqueue($"Adding'{key}' to list of dependency packages found"); depPkgsFound.TryAdd(key, depPkg); - FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository); + FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs); } } } diff --git a/src/code/InternalHooks.cs b/src/code/InternalHooks.cs index 99d6104ce..741338e06 100644 --- a/src/code/InternalHooks.cs +++ b/src/code/InternalHooks.cs @@ -17,6 +17,8 @@ public class InternalHooks internal static string MARPrefix; + internal static int FindDependencyPackagesParallelThreshold = -1; + public static void SetTestHook(string property, object value) { var fieldInfo = typeof(InternalHooks).GetField(property, BindingFlags.Static | BindingFlags.NonPublic); diff --git a/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 b/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 index 9538adf30..5fb76e172 100644 --- a/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 +++ b/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 @@ -121,7 +121,14 @@ Describe 'Test HTTP Find-PSResource for V2 Server Protocol' -tags 'CI' { # TestModuleWithDependencyB >= 1.0.0.0 # TestModuleWithDependencyD <= 1.0.0.0 - $resWithDependencies = Find-PSResource -Name "TestModuleWithDependencyE" -IncludeDependencies -Repository $PSGalleryName + try { + [Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("FindDependencyPackagesParallelThreshold", 0) + $resWithDependencies = Find-PSResource -Name "TestModuleWithDependencyE" -IncludeDependencies -Repository $PSGalleryName + } + finally { + [Microsoft.PowerShell.PSResourceGet.UtilClasses.InternalHooks]::SetTestHook("FindDependencyPackagesParallelThreshold", -1) + } + $resWithDependencies | Should -HaveCount 4 $foundParentPkgE = $false