Public/Start-ParallelModuleExport.ps1
function Start-ParallelModuleExport { <# .SYNOPSIS Exports multiple modules in parallel for improved performance. .PARAMETER ModuleNames Array of module names to export. .PARAMETER OutputDirectory Directory where exports will be saved. .PARAMETER Format Export format (JSON, Markdown, XML). .PARAMETER MaxConcurrentModules Maximum number of modules to process simultaneously. #> param( [Parameter(Mandatory = $true)] [string[]]$ModuleNames, [Parameter(Mandatory = $true)] [string]$OutputDirectory, [Parameter(Mandatory = $false)] [ValidateSet("JSON", "Markdown", "XML")] [string]$Format = "JSON", [Parameter(Mandatory = $false)] [int]$MaxConcurrentModules = 3 ) # Add input validation if (-not $ModuleNames -or $ModuleNames.Count -eq 0) { throw "ModuleNames array cannot be null or empty" } if (-not (Test-Path $OutputDirectory) -and -not (New-Item -Path $OutputDirectory -ItemType Directory -Force -ErrorAction SilentlyContinue)) { throw "Cannot create output directory: $OutputDirectory" } $exportScript = { param($ModuleName, $OutputDirectory, $Format, $ModulePath) try { # Import the module containing Export-ModuleCommandsForLLM Import-Module $ModulePath -Force -ErrorAction Stop # Verify the function is available if (-not (Get-Command Export-ModuleCommandsForLLM -ErrorAction SilentlyContinue)) { throw "Export-ModuleCommandsForLLM function not found after importing module" } # Now call the export function with suppressed verbose output in jobs $VerbosePreference = 'SilentlyContinue' $exportPath = Export-ModuleCommandsForLLM -ModuleName $ModuleName -OutputDirectory $OutputDirectory -FileName "$ModuleName-Commands" -Format $Format -SkipProgressBar return [PSCustomObject]@{ ModuleName = $ModuleName Success = $true ExportPath = $exportPath Error = $null } } catch { return [PSCustomObject]@{ ModuleName = $ModuleName Success = $false ExportPath = $null Error = $_.Exception.Message } } } Write-Output "Starting parallel export of $($ModuleNames.Count) modules..." # Track execution time $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $results = @() $batches = for ($i = 0; $i -lt $ModuleNames.Count; $i += $MaxConcurrentModules) { $endIndex = [Math]::Min($i + $MaxConcurrentModules - 1, $ModuleNames.Count - 1) $ModuleNames[$i..$endIndex] } # Get the module path to pass to jobs $currentModulePath = $MyInvocation.MyCommand.Module.Path if (-not $currentModulePath) { # If module path is not available, try to find it $currentModule = Get-Module -Name "Export-ModuleInfoForLLM" -ErrorAction SilentlyContinue if ($currentModule) { $currentModulePath = $currentModule.Path } else { # Fallback to script path - look for the psm1 file $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $moduleFile = Join-Path $scriptDir "Export-ModuleInfoForLLM.psm1" if (Test-Path $moduleFile) { $currentModulePath = $moduleFile } else { # Last resort - use the current file $currentModulePath = $MyInvocation.MyCommand.Path } } } $jobCount = 0 foreach ($batch in $batches) { $jobs = @() foreach ($moduleName in $batch) { Write-Verbose "Starting job for module: $moduleName" -Verbose $job = Start-Job -ScriptBlock $exportScript -ArgumentList $moduleName, $OutputDirectory, $Format, $currentModulePath -Name "Export-$moduleName" $jobs += $job $jobCount++ } # Wait for batch completion with progress Write-Progress -Activity "Exporting Modules" -Status "Processing batch..." -PercentComplete (($jobCount / $ModuleNames.Count) * 100) Wait-Job -Job $jobs | Out-Null # Collect results foreach ($job in $jobs) { $jobOutput = Receive-Job -Job $job -ErrorAction SilentlyContinue # Filter out null or empty results if ($jobOutput) { # Handle both single results and arrays of results if ($jobOutput -is [array]) { foreach ($result in $jobOutput) { if ($result -and $result.ModuleName) { $results += $result if ($result.Success) { Write-Verbose "Successfully exported: $($result.ModuleName)" -Verbose } else { Write-Warning "Failed to export: $($result.ModuleName) - $($result.Error)" } } } } else { if ($jobOutput.ModuleName) { $results += $jobOutput if ($jobOutput.Success) { Write-Verbose "Successfully exported: $($jobOutput.ModuleName)" -Verbose } else { Write-Warning "Failed to export: $($jobOutput.ModuleName) - $($jobOutput.Error)" } } } } Remove-Job -Job $job -Force -ErrorAction SilentlyContinue } } Write-Progress -Activity "Exporting Modules" -Completed $stopwatch.Stop() # Filter results to remove any empty entries $results = $results | Where-Object { $_ -and $_.ModuleName } # Report results $successCount = ($results | Where-Object Success).Count Write-Output "Parallel export completed in $([Math]::Round($stopwatch.Elapsed.TotalSeconds, 2)) seconds" Write-Output "Successfully exported: $successCount of $($results.Count) modules" # Show any failures (only non-empty ones) $failures = $results | Where-Object { -not $_.Success -and $_.ModuleName } if ($failures) { $failures | ForEach-Object { Write-Warning "Failed to export $($_.ModuleName): $($_.Error)" } } return $results } |