Private/GitHub/Invoke-CgrGitHubApiReadRequest.ps1
|
function Invoke-CgrGitHubApiReadRequest { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string[]] $ArgumentList, [ValidateRange(1, 10)] [int] $MaxAttempts = 3, [ValidateRange(1, 60000)] [int] $BaseDelayMilliseconds = 250, [ValidateRange(1, 60000)] [int] $MaxDelayMilliseconds = 2000, [ValidateRange(1, 300)] [int] $MaxServerRetryAfterSeconds = 60 ) for ($attempt = 1; $attempt -le $MaxAttempts; $attempt++) { $result = Invoke-CgrNativeCommand -FilePath 'gh' -ArgumentList $ArgumentList $result | Add-Member -NotePropertyName RetryAttempts -NotePropertyValue $attempt -Force $result | Add-Member -NotePropertyName RetryDiagnostic -NotePropertyValue $null -Force if ($result.ExitCode -eq 0) { return $result } $errorText = [string] $result.ErrorText $retryable = $errorText -match '(?i)(HTTP\s+(429|502|503|504)\b|secondary rate limit|rate limit exceeded|abuse detection|connection (was )?reset|connection timed out|temporary failure|TLS handshake timeout|server disconnected|unexpected EOF)' if (-not $retryable -or $attempt -ge $MaxAttempts) { return $result } $retryAfterSeconds = $null $retryAfterMatch = [regex]::Match( $errorText, '(?im)(?:Retry-After\s*[:=]\s*|retry after\s+)(?<seconds>\d+)\s*(?:seconds?)?' ) if ($retryAfterMatch.Success) { $retryAfterSeconds = [int] $retryAfterMatch.Groups['seconds'].Value } if ($null -ne $retryAfterSeconds) { if ($retryAfterSeconds -gt $MaxServerRetryAfterSeconds) { $result.RetryDiagnostic = "Automatic retry was not attempted because the server requested a $retryAfterSeconds second delay, exceeding the $MaxServerRetryAfterSeconds second automatic-wait limit." return $result } $delayMilliseconds = $retryAfterSeconds * 1000 } else { $exponentialDelay = [Math]::Min( $MaxDelayMilliseconds, $BaseDelayMilliseconds * [Math]::Pow(2, $attempt - 1) ) $jitterCeiling = [Math]::Max(1, [int] [Math]::Ceiling($BaseDelayMilliseconds / 4)) $jitterMilliseconds = Get-Random -Minimum 0 -Maximum ($jitterCeiling + 1) $delayMilliseconds = [int] [Math]::Min( $MaxDelayMilliseconds, $exponentialDelay + $jitterMilliseconds ) } Start-Sleep -Milliseconds $delayMilliseconds } } |