private/export/Wait-ZtTenantDataExport.ps1
|
function Wait-ZtTenantDataExport { <# .SYNOPSIS Wait for the parallelized data export to complete. .DESCRIPTION Wait for the parallelized data export to complete. .PARAMETER Workflow The runspace workflow we are waiting to complete. .EXAMPLE PS C:\> Wait-ZtTenantDataExport -Workflow $workflow Wait for the parallelized data export to complete. #> [CmdletBinding()] param ( [PSFramework.Runspace.RSWorkflow] $Workflow ) begin { $failedExports = @{} $totalCount = $Workflow.Queues["Input"].TotalItemCount $progressID = Get-Random -Minimum 1 -Maximum 999 $taskProgID = @{ } $lastMessageScan = [datetime]::MinValue # Initialize progress dashboard summary for the export stage Update-ZtProgressState -TotalItems $totalCount -CompletedItems 0 -FailedItems 0 -InProgressItems 0 } process { Write-Progress -Id $progressID -Activity "Processing $($totalCount) Exports" -PercentComplete 0 while (-not $Workflow.Queues["Results"].Closed) { Start-Sleep -Milliseconds 500 $groups = $Workflow.Data.Values | Group-Object Status $countPending = @($groups).Where{$_.Name -eq 'Pending'}.Group.Count $countWaiting = @($groups).Where{$_.Name -eq 'Waiting'}.Group.Count $countInProgress = @($groups).Where{$_.Name -eq 'InProgress'}.Group.Count $countDone = @($groups).Where{$_.Name -eq 'Done'}.Group.Count $countFailed = @($groups).Where{$_.Name -eq 'Failed'}.Group.Count foreach ($failure in @($groups).Where{$_.Name -eq 'Failed'}.Group) { if ($failedExports[$failure.Name]) { continue } $failedExports[$failure.Name] = $true Write-PSFMessage -Level Warning -Message "Export '{0}' failed: {1}" -StringValues $failure.Name, $failure.Message } $status = "$($Workflow.Queues["Results"].Count) / $totalCount | Pending: $($countPending) | Waiting: $($countWaiting) | In Progress: $($countInProgress) | Done: $($countDone) | Failed: $($countFailed)" $percent = ($Workflow.Queues["Results"].Count / $totalCount * 100) -as [int] if ($percent -lt 0) { $percent = 0 } if ($percent -gt 100) { $percent = 100 } Write-Progress -Id $progressID -Activity "Processing $($totalCount) Exports" -Status $status -PercentComplete $percent # Update progress dashboard summary counts Update-ZtProgressState -TotalItems $totalCount -CompletedItems $countDone -FailedItems $countFailed -InProgressItems ($countInProgress + $countWaiting) # Scan recent PSFMessages to update worker detail lines try { $recentMessages = Get-PSFMessage -Last 100 | Where-Object { $_.Timestamp -gt $lastMessageScan } $lastMessageScan = [datetime]::Now # Build runspace-to-export mapping from the progress state $rsMappings = @{} foreach ($key in @($script:__ZtSession.ProgressState.Value.Keys)) { if ($key -like 'rs_*') { $rsId = $key.Substring(3) $rsMappings[$rsId] = $script:__ZtSession.ProgressState.Value[$key] } } foreach ($msg in $recentMessages) { $rsId = $msg.Runspace.ToString() if ($rsMappings.ContainsKey($rsId)) { $exportName = $rsMappings[$rsId] $workerKey = "worker_$exportName" $worker = $null if ($script:__ZtSession.ProgressState.Value.TryGetValue($workerKey, [ref]$worker)) { if ($worker -and $worker.Status -in @('Running', 'InProgress', 'Waiting')) { Update-ZtProgressState -WorkerId $exportName -WorkerName $exportName -WorkerStatus $worker.Status -WorkerDetail $msg.LogMessage } } } } } catch { # Non-critical: don't let message scanning break the wait loop } foreach ($task in $Workflow.Data.Values) { if ($task.Status -in 'Waiting', 'InProgress') { if (-not $taskProgID[$task.Name]) { $taskProgID[$task.Name] = Get-Random -Minimum 1000 -Maximum 9999 } Write-Progress -Id $taskProgID[$task.Name] -ParentId $progressID -Activity "$($task.Name) : $($task.Status)" -Status "$((Get-Date) - $task.Updated)" -PercentComplete 0 } if ($task.Status -notin 'Waiting', 'InProgress' -and $taskProgID[$task.Name]) { Write-Progress -Id $taskProgID[$task.Name] -ParentId $progressID -Completed $taskProgID.Remove($task.Name) } } } # Final summary update after the loop exits — ensures _inProgressItems is 0 # and the dashboard shows correct totals before workers get cleared by next stage $finalGroups = $Workflow.Data.Values | Group-Object Status $finalDone = @($finalGroups).Where{$_.Name -eq 'Done'}.Group.Count $finalFailed = @($finalGroups).Where{$_.Name -eq 'Failed'}.Group.Count Update-ZtProgressState -TotalItems $totalCount -CompletedItems $finalDone -FailedItems $finalFailed -InProgressItems 0 Write-Progress -Id $progressID -Activity "Processing $($totalCount) Exports" -Completed } } |