Public/Invoke-WithRetry.ps1
|
<#
.SYNOPSIS Executes a script block with automatic retry logic on failure. .DESCRIPTION The Invoke-WithRetry function wraps a script block in retry logic, automatically re-executing it when exceptions occur. It supports configurable retry counts, delays with optional exponential backoff, filtering by exception type, and an optional callback on each retry. If all retries are exhausted, the last exception is rethrown. .PARAMETER ScriptBlock The script block to execute. If execution throws an exception, the function will retry according to the configured retry parameters. .PARAMETER MaxRetries The maximum number of retry attempts after the initial failure. Defaults to 3. .PARAMETER DelaySeconds The base delay in seconds between retry attempts. Defaults to 2. .PARAMETER BackoffMultiplier A multiplier applied to the delay on each successive retry. Set to a value greater than 1 for exponential backoff (e.g., 2 doubles the delay each retry). Defaults to 1 (constant delay). .PARAMETER RetryableExceptions An optional array of .NET exception types to retry on. When specified, only exceptions matching one of these types will trigger a retry. If omitted, all exceptions trigger a retry. .PARAMETER OnRetry An optional script block invoked on each retry attempt. It receives the current exception as the first argument and the attempt number as the second argument. .INPUTS None This function does not accept pipeline input. .OUTPUTS System.Object Returns the output of the successfully executed ScriptBlock. .EXAMPLE Invoke-WithRetry -ScriptBlock { Get-Content "\\server\share\file.txt" } -MaxRetries 5 -DelaySeconds 3 Attempts to read a file up to 5 times with a 3-second delay between retries. .EXAMPLE Invoke-WithRetry -ScriptBlock { Invoke-RestMethod -Uri $uri } -MaxRetries 4 -DelaySeconds 1 -BackoffMultiplier 2 Calls a REST endpoint with exponential backoff: 1s, 2s, 4s, 8s delays between retries. .EXAMPLE $onRetry = { param($ex, $attempt) Write-Warning "Retry $attempt : $($ex.Message)" } Invoke-WithRetry -ScriptBlock { Connect-Database } -MaxRetries 3 -RetryableExceptions @([System.Net.Sockets.SocketException]) -OnRetry $onRetry Retries only on SocketException, invoking a warning callback on each retry. .NOTES Author: Nigel Tatschner Company: TheCodeSaiyan Version: 0.2.0 This function is part of the tcs.core module and provides robust retry logic suitable for network operations, transient fault handling, and resilient scripting. .LINK https://ntatschner.github.io/TheCodeSaiyan-PowerShell-tcs.core/ #> function Invoke-WithRetry { [CmdletBinding()] [OutputType([System.Object])] param( [Parameter(Mandatory = $true, HelpMessage = "The script block to execute with retry logic.")] [scriptblock]$ScriptBlock, [Parameter(HelpMessage = "Maximum number of retry attempts.")] [int]$MaxRetries = 3, [Parameter(HelpMessage = "Base delay in seconds between retries.")] [int]$DelaySeconds = 2, [Parameter(HelpMessage = "Multiplier applied to the delay on each successive retry.")] [double]$BackoffMultiplier = 1, [Parameter(HelpMessage = "Optional list of exception types to retry on.")] [type[]]$RetryableExceptions, [Parameter(HelpMessage = "Optional callback script block invoked on each retry.")] [scriptblock]$OnRetry ) $attempt = 0 $lastException = $null while ($true) { try { $result = & $ScriptBlock return $result } catch { $lastException = $_.Exception $attempt++ # Check if we should retry based on exception type if ($RetryableExceptions) { $shouldRetry = $false foreach ($exType in $RetryableExceptions) { if ($lastException -is $exType) { $shouldRetry = $true break } } if (-not $shouldRetry) { throw } } if ($attempt -gt $MaxRetries) { throw $lastException } $currentDelay = $DelaySeconds * [Math]::Pow($BackoffMultiplier, $attempt) Write-Verbose "Attempt $attempt of $MaxRetries failed. Retrying in $currentDelay seconds... Exception: $($lastException.Message)" if ($OnRetry) { & $OnRetry $lastException $attempt } Start-Sleep -Seconds $currentDelay } } } |