@@ -46,10 +46,6 @@ internal class FindHelper
4646 // If running 'Install-PSResource Az, TestModule, NewTestModule', it will contain one parent and its dependencies.
4747 private ConcurrentDictionary < string , List < string > > _packagesFound ;
4848
49- // Creates a new instance of depPkgsFound each time FindDependencyPackages() is called.
50- // This will eventually return the PSResourceInfo object to the main cmdlet class.
51- private ConcurrentDictionary < string , PSResourceInfo > depPkgsFound ;
52-
5349 // Contains the latest found version of a particular package.
5450 private ConcurrentDictionary < string , PSResourceInfo > _knownLatestPkgVersion ;
5551
@@ -1060,13 +1056,36 @@ private IEnumerable<PSResourceInfo> SearchByNames(ServerApiCall currentServer, R
10601056 // After retrieving all packages find their dependencies
10611057 if ( _includeDependencies )
10621058 {
1063- foreach ( PSResourceInfo currentPkg in parentPkgs )
1059+ // Resolving each parent package's dependency closure is independent work, so do it concurrently.
1060+ // yield return cannot be used inside Parallel.ForEach, so collect results into a thread-safe bag first.
1061+ ConcurrentBag < PSResourceInfo > dependencyPkgs = new ConcurrentBag < PSResourceInfo > ( ) ;
1062+ int processorCount = Environment . ProcessorCount ;
1063+ int maxDegreeOfParallelism = processorCount * 4 ;
1064+ if ( parentPkgs . Count > processorCount )
1065+ {
1066+ Parallel . ForEach ( parentPkgs , new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism } , currentPkg =>
1067+ {
1068+ foreach ( PSResourceInfo pkgDep in FindDependencyPackages ( currentServer , currentResponseUtil , currentPkg , repository ) )
1069+ {
1070+ dependencyPkgs . Add ( pkgDep ) ;
1071+ }
1072+ } ) ;
1073+ }
1074+ else
10641075 {
1065- foreach ( PSResourceInfo pkgDep in FindDependencyPackages ( currentServer , currentResponseUtil , currentPkg , repository ) )
1076+ foreach ( PSResourceInfo currentPkg in parentPkgs )
10661077 {
1067- yield return pkgDep ;
1078+ foreach ( PSResourceInfo pkgDep in FindDependencyPackages ( currentServer , currentResponseUtil , currentPkg , repository ) )
1079+ {
1080+ dependencyPkgs . Add ( pkgDep ) ;
1081+ }
10681082 }
10691083 }
1084+
1085+ foreach ( PSResourceInfo pkgDep in dependencyPkgs )
1086+ {
1087+ yield return pkgDep ;
1088+ }
10701089 }
10711090 }
10721091
@@ -1158,15 +1177,17 @@ private string FormatPkgVersionString(PSResourceInfo pkg)
11581177
11591178 internal IEnumerable < PSResourceInfo > FindDependencyPackages ( ServerApiCall currentServer , ResponseUtil currentResponseUtil , PSResourceInfo currentPkg , PSRepositoryInfo repository )
11601179 {
1161- depPkgsFound = new ConcurrentDictionary < string , PSResourceInfo > ( ) ;
1180+ // Use a local instance so multiple parent packages can resolve their dependency closures concurrently
1181+ // without racing on shared state.
1182+ ConcurrentDictionary < string , PSResourceInfo > depPkgsFound = new ConcurrentDictionary < string , PSResourceInfo > ( ) ;
11621183 _cmdletPassedIn . WriteDebug ( $ "In FindHelper::FindDependencyPackages() - { currentPkg . Name } ") ;
1163- FindDependencyPackagesHelper ( currentServer , currentResponseUtil , currentPkg , repository ) ;
1184+ FindDependencyPackagesHelper ( currentServer , currentResponseUtil , currentPkg , repository , depPkgsFound ) ;
11641185
11651186 return depPkgsFound . Values . ToList ( ) ;
11661187 }
11671188
11681189 // Method 2
1169- internal void FindDependencyPackagesHelper ( ServerApiCall currentServer , ResponseUtil currentResponseUtil , PSResourceInfo currentPkg , PSRepositoryInfo repository )
1190+ internal void FindDependencyPackagesHelper ( ServerApiCall currentServer , ResponseUtil currentResponseUtil , PSResourceInfo currentPkg , PSRepositoryInfo repository , ConcurrentDictionary < string , PSResourceInfo > depPkgsFound )
11701191 {
11711192 ConcurrentQueue < ErrorRecord > errorMsgs = new ConcurrentQueue < ErrorRecord > ( ) ;
11721193 ConcurrentQueue < string > verboseMsgs = new ConcurrentQueue < string > ( ) ;
@@ -1185,15 +1206,15 @@ internal void FindDependencyPackagesHelper(ServerApiCall currentServer, Response
11851206 Parallel . ForEach ( currentPkg . Dependencies , new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism } , dep =>
11861207 {
11871208 debugMsgs . Enqueue ( $ "Finding dependency '{ dep . Name } ' version range '{ dep . VersionRange } '") ;
1188- FindDependencyPackageVersion ( dep , currentServer , currentResponseUtil , currentPkg , repository , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
1209+ FindDependencyPackageVersion ( dep , currentServer , currentResponseUtil , currentPkg , repository , depPkgsFound , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
11891210 } ) ;
11901211 }
11911212 else
11921213 {
11931214 foreach ( var dep in currentPkg . Dependencies )
11941215 {
11951216 debugMsgs . Enqueue ( $ "Finding dependency '{ dep . Name } ' version range '{ dep . VersionRange } '") ;
1196- FindDependencyPackageVersion ( dep , currentServer , currentResponseUtil , currentPkg , repository , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
1217+ FindDependencyPackageVersion ( dep , currentServer , currentResponseUtil , currentPkg , repository , depPkgsFound , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
11971218 }
11981219 }
11991220
@@ -1208,6 +1229,7 @@ private void FindDependencyPackageVersion(
12081229 ResponseUtil currentResponseUtil ,
12091230 PSResourceInfo currentPkg ,
12101231 PSRepositoryInfo repository ,
1232+ ConcurrentDictionary < string , PSResourceInfo > depPkgsFound ,
12111233 ConcurrentQueue < ErrorRecord > errorMsgs ,
12121234 ConcurrentQueue < string > warningMsgs ,
12131235 ConcurrentQueue < string > debugMsgs ,
@@ -1228,7 +1250,7 @@ private void FindDependencyPackageVersion(
12281250 else
12291251 {
12301252 // Find this version from the server
1231- depPkg = FindDependencyWithLowerBound ( dep , currentServer , currentResponseUtil , currentPkg , repository , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
1253+ depPkg = FindDependencyWithLowerBound ( dep , currentServer , currentResponseUtil , currentPkg , repository , depPkgsFound , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
12321254 }
12331255 }
12341256 else if ( dep . VersionRange . HasLowerBound && dep . VersionRange . MinVersion . Equals ( dep . VersionRange . MaxVersion ) )
@@ -1245,7 +1267,7 @@ private void FindDependencyPackageVersion(
12451267 }
12461268 else
12471269 {
1248- depPkg = FindDependencyWithSpecificVersion ( dep , currentServer , currentResponseUtil , currentPkg , repository , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
1270+ depPkg = FindDependencyWithSpecificVersion ( dep , currentServer , currentResponseUtil , currentPkg , repository , depPkgsFound , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
12491271 }
12501272 }
12511273 else
@@ -1261,7 +1283,7 @@ private void FindDependencyPackageVersion(
12611283 }
12621284 else
12631285 {
1264- depPkg = FindDependencyWithUpperBound ( dep , currentServer , currentResponseUtil , currentPkg , repository , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
1286+ depPkg = FindDependencyWithUpperBound ( dep , currentServer , currentResponseUtil , currentPkg , repository , depPkgsFound , errorMsgs , warningMsgs , debugMsgs , verboseMsgs ) ;
12651287 }
12661288 }
12671289 }
@@ -1273,6 +1295,7 @@ private PSResourceInfo FindDependencyWithSpecificVersion(
12731295 ResponseUtil currentResponseUtil ,
12741296 PSResourceInfo currentPkg ,
12751297 PSRepositoryInfo repository ,
1298+ ConcurrentDictionary < string , PSResourceInfo > depPkgsFound ,
12761299 ConcurrentQueue < ErrorRecord > errorMsgs ,
12771300 ConcurrentQueue < string > warningMsgs ,
12781301 ConcurrentQueue < string > debugMsgs ,
@@ -1351,7 +1374,7 @@ private PSResourceInfo FindDependencyWithSpecificVersion(
13511374 // This will eventually return the PSResourceInfo object to the main cmdlet class.
13521375 debugMsgs . Enqueue ( $ "Adding'{ key } ' to list of dependency packages found") ;
13531376 depPkgsFound . TryAdd ( key , depPkg ) ;
1354- FindDependencyPackagesHelper ( currentServer , currentResponseUtil , depPkg , repository ) ;
1377+ FindDependencyPackagesHelper ( currentServer , currentResponseUtil , depPkg , repository , depPkgsFound ) ;
13551378 }
13561379 }
13571380 }
@@ -1366,6 +1389,7 @@ private PSResourceInfo FindDependencyWithLowerBound(
13661389 ResponseUtil currentResponseUtil ,
13671390 PSResourceInfo currentPkg ,
13681391 PSRepositoryInfo repository ,
1392+ ConcurrentDictionary < string , PSResourceInfo > depPkgsFound ,
13691393 ConcurrentQueue < ErrorRecord > errorMsgs ,
13701394 ConcurrentQueue < string > warningMsgs ,
13711395 ConcurrentQueue < string > debugMsgs ,
@@ -1419,7 +1443,7 @@ private PSResourceInfo FindDependencyWithLowerBound(
14191443 // This will eventually return the PSResourceInfo object to the main cmdlet class.
14201444 debugMsgs . Enqueue ( $ "Adding'{ key } ' to list of dependency packages found") ;
14211445 depPkgsFound . TryAdd ( key , depPkg ) ;
1422- FindDependencyPackagesHelper ( currentServer , currentResponseUtil , depPkg , repository ) ;
1446+ FindDependencyPackagesHelper ( currentServer , currentResponseUtil , depPkg , repository , depPkgsFound ) ;
14231447 }
14241448 }
14251449 }
@@ -1434,6 +1458,7 @@ private PSResourceInfo FindDependencyWithUpperBound(
14341458 ResponseUtil currentResponseUtil ,
14351459 PSResourceInfo currentPkg ,
14361460 PSRepositoryInfo repository ,
1461+ ConcurrentDictionary < string , PSResourceInfo > depPkgsFound ,
14371462 ConcurrentQueue < ErrorRecord > errorMsgs ,
14381463 ConcurrentQueue < string > warningMsgs ,
14391464 ConcurrentQueue < string > debugMsgs ,
@@ -1490,7 +1515,7 @@ private PSResourceInfo FindDependencyWithUpperBound(
14901515 // This will eventually return the PSResourceInfo object to the main cmdlet class.
14911516 debugMsgs . Enqueue ( $ "Adding'{ key } ' to list of dependency packages found") ;
14921517 depPkgsFound . TryAdd ( key , depPkg ) ;
1493- FindDependencyPackagesHelper ( currentServer , currentResponseUtil , depPkg , repository ) ;
1518+ FindDependencyPackagesHelper ( currentServer , currentResponseUtil , depPkg , repository , depPkgsFound ) ;
14941519 }
14951520 }
14961521 }
0 commit comments