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
 
    .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,
        [Int]$MaximumRetryCount=[Int]::MaxValue
    )

    $Attempt = 0
    $StopWatch = [system.diagnostics.stopwatch]::StartNew()

    do {
        $Attempt++
        try {
            "Attempt ${Attempt}, invoking script block ..." | Write-Verbose
            return Invoke-Command -Command $ScriptBlock
        } catch {
            if ($MaximumRetryCount -lt $Attempt) {
                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
        }
    } while ($true)
}