PSRetryCommand.psm1
|
Function Wait-Until { <# .SYNOPSIS Wait polling for a scriptblock to complete successfully .DESCRIPTION Wait polling for a scriptblock to complete successfully .PARAMETER ScriptBlock Specifies the commands to run. Enclose the commands in braces ({ }) to create a script block. .PARAMETER Timeout Specifies the maximum wait time for each job, in seconds. The default value, -1, indicates that the cmdlet will wait indefinitely. .PARAMETER DelayMillis Amount of milliseconds to sleep between polling attempts .PARAMETER MaximumRetryCount Max amount of polling attempts .PARAMETER AbortOnExceptions List of exception types to abort execution with failure immediately .PARAMETER SkipResultTest By default only results evaluating to true with simple if check are considered as valid. Skip this check to e.g. accept empty string as a valid response .EXAMPLE PS C:\> Wait-Until -ScriptBlock {Invoke-RestMethod http://localhost:8080} Waits until we get a valid response from localhost port 8080. #> [CmdletBinding()] Param( [Parameter(Mandatory = $true)] [ScriptBlock]$ScriptBlock, [Parameter(Mandatory = $false)] [Int32]$Timeout = -1, [ValidateScript({ $_ -gt 0 })] [Alias("RetryEvery")] [Parameter(Mandatory = $false)] [Int]$DelayMillis = 100, [Parameter(Mandatory = $false)] [Int]$MaximumRetryCount = [Int]::MaxValue, [Parameter(Mandatory = $false)] [String[]]$AbortOnExceptions = @(), [switch]$SkipResultTest ) process { $Attempt = 0 $StopWatch = [system.diagnostics.stopwatch]::StartNew() $EndLoop = $false do { $Attempt++ try { "Attempt ${Attempt}, invoking script block ..." | Write-Verbose $ret = Invoke-Command -Command $ScriptBlock if ($SkipResultTest -or $ret) { return $ret } else { throw $ret } } catch { if ($_.Exception.GetType().FullName -in $AbortOnExceptions) { "Terminating Exception '$($_.Exception.GetType().FullName)' caught, bailing out ..." | Write-Verbose throw $_.Exception } if ($MaximumRetryCount -lt $Attempt) { "Maximum Attempts (${Attempt}) reached, bailing out ..." | Write-Verbose throw $_.Exception } $RemainingMillis = [Int]::MaxValue if ($Timeout -ge 0) { $RemainingMillis = $Timeout * 1000 - [int] $stopwatch.Elapsed.TotalMilliseconds } $SleepMillis = [Math]::Min($RemainingMillis, $DelayMillis) if ($SleepMillis -le 0) { throw $_.Exception } Write-Error $_.Exception -ErrorAction Continue "Sleeping ${SleepMillis} milliseconds ..." | Write-Verbose Start-Sleep -Milliseconds $SleepMillis } } until ($EndLoop) } } |