internal/functions/Receive-Workload.ps1

function Receive-Workload
{
<#
    .SYNOPSIS
        Waits for worker agents to finish and receives their results.
     
    .DESCRIPTION
        Waits for worker agents to finish and receives their results.
        Returns all result objects generated by each worker.
        Use of this commands assumes that:
        - Start-WorkloadManager was used to prepare worker agent execution
        - Add-Workload was used to queue data gathering agents for the affected targets.
     
    .EXAMPLE
        PS C:\> Receive-Workload
     
        Waits for worker agents to finish and receives their results.
     
    .NOTES
        Results are also stored in the module-scope $script:lastCheckResults variable.
        This is strictly for debugging purposes
#>

    [CmdletBinding()]
    param (
        
    )
    
    process
    {
        while ($script:runspaces | Where-Object Received -EQ $false)
        {
            #region Collect Data from finished workers
            foreach ($runspaceContainer in ($script:runspaces | Where-Object { -not $_.Received -and $_.Runspace.IsCompleted }))
            {
                $resultObject = $runspaceContainer.PowerShell.EndInvoke($runspaceContainer.Runspace)
                $runspaceContainer.PowerShell.Dispose()
                $script:lastCheckResults += $resultObject
                
                if (-not $resultObject.Connected)
                {
                    $runspaceContainer.Received = $true
                    Write-PSFMessage -Level Warning -String 'Receive-Workload.ConnectFailed' -StringValues $resultObject.Target.Name, $resultObject.Errors.Exception.Message -Target $resultObject.Target.Name
                    continue
                }
                
                Import-Data -TargetName $resultObject.Target.Name
                if (-not $script:data[$resultObject.Target.Name])
                {
                    $script:data[$resultObject.Target.Name] = @{ }
                }
                foreach ($key in $resultObject.Results.Keys)
                {
                    if ($resultObject.ErrorChecks.Name -contains $key)
                    {
                        Write-PSFMessage -Level Warning -String 'Receive-Workload.CheckFailed' -StringValues $key, $resultObject.Target.Name, $resultObject.Results[$key].Message -Target $resultObject.Target.Name
                        continue
                    }
                    $script:data[$resultObject.Target.Name][$key] = $resultObject.Results[$key]
                }
                Export-Data -TargetName $resultObject.Target.Name
                
                $runspaceContainer.Received = $true
                $resultObject
            }
            #endregion Collect Data from finished workers
            
            #region Terminate worker agents that timed out
            foreach ($runspaceContainer in ($script:runspaces | Where-Object { -not $_.Received -and ($_.StartTime.Add((Get-PSFConfigValue -FullName 'Monitoring.Runspace.ExecutionTimeout')) -lt (Get-Date)) }))
            {
                Write-PSFMessage -Level Warning -String 'Receive-Workload.RunspaceTimeout' -StringValues $runspaceContainer.Workload.Target.Name -Target $runspaceContainer.Workload.Target.Name
                $runspaceContainer.PowerShell.Dispose()
                $runspaceContainer.Received = $true
            }
            #endregion Terminate worker agents that timed out
            
            # Prevent max CPU load while runspaces are still busy
            Start-Sleep -Milliseconds 100
        }
    }
}