Created
January 20, 2021 17:55
-
-
Save Jaykul/54a213dd2db42406a8a69c9666394d44 to your computer and use it in GitHub Desktop.
There are so many ways to write this...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Invoke-WithRetry { | |
<# | |
.SYNOPSIS | |
Invoke a ScriptBlock until it returns a value (or until a certain ammount of time elapses) | |
.DESCRIPTION | |
Invokes the given ScriptBlock on $RetryEvery interval until it returns a value. | |
If the $Limit time passes without a value, returns nothing. | |
.EXAMPLE | |
$Time = (Get-Date).AddMinutes(0.5) | |
Invoke-WithRetry { if($Time -lt (Get-Date)) { return $Time } } | |
Runs a simple ScriptBlock until it returns a value | |
.EXAMPLE | |
$Time = (Get-Date).AddMinutes(0.5) | |
Invoke-WithRetry { if($Time -lt (Get-Date)) { return $Time } } -Activity "Wait for $Time" -Limit "0:0:15" | |
Runs the script with progress output and a shorter time limit (which will expire without returning a value) | |
#> | |
[CmdletBinding()] | |
param( | |
# The code you want to run in a retry loop | |
# This script block MUST have output on success, and no output otherwise. | |
# You can Write to streams, but not Output unless you have success. | |
[Parameter(Mandatory)] | |
[ScriptBlock] | |
$ScriptBlock, | |
# A label for progress messages. If set, Invoke-WithRetry will Write-Progress after each failed attempt. | |
[string] | |
$Activity, | |
# The maximum amount of time to wait. Default is 10 minutes: "0:10" | |
[timespan] | |
$Limit = "0:10", | |
# The minimum amount of time between tries. Default is 5 seconds: "0:0:5" | |
[timespan] | |
$RetryEvery = "0:0:5" | |
) | |
$ShowProgress = $PSBoundParameters.ContainsKey("Activity") | |
$Stopwatch = [System.Diagnostics.Stopwatch]::new() | |
$Stopwatch.Start() | |
$Result = $null | |
$Count = 0 | |
try { | |
do { | |
$Result = & $ScriptBlock | |
if (!$Result ) { | |
$Count++ | |
if ($ShowProgress) { | |
Write-Progress -Activity $Activity -Status "Attempted $Count time(s). Waiting $RetryEvery to try again." -SecondsRemaining ($Limit - $Stopwatch.Elapsed).TotalSeconds | |
} | |
Start-Sleep -Milliseconds $RetryEvery.TotalMilliseconds | |
} | |
} while (!$Result -and $Stopwatch.Elapsed -lt $Limit) | |
$Result | |
} finally { | |
$Stopwatch.Stop() | |
if ($ShowProgress) { | |
Write-Progress -Activity $Activity -Completed | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment