Skip to content

Instantly share code, notes, and snippets.

@joerodgers
Last active February 9, 2018 18:00
Show Gist options
  • Save joerodgers/e0518ee519b44fdc23b56b7e6f0ace3a to your computer and use it in GitHub Desktop.
Save joerodgers/e0518ee519b44fdc23b56b7e6f0ace3a to your computer and use it in GitHub Desktop.
Create a new client context with logic to handle service throttling.
function New-ClientContextWithRetry
{
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true, ParameterSetName = "CredentialComponents")]
[Parameter(Mandatory=$true, ParameterSetName = "SharePointOnlineCredential")]
[string]$ContextUrl,
[Parameter(Mandatory=$true, ParameterSetName = "CredentialComponents")]
[string]$UserName,
[Parameter(Mandatory=$true, ParameterSetName = "CredentialComponents")]
[System.Security.SecureString]$SecurePassword,
[Parameter(Mandatory=$true, ParameterSetName = "SharePointOnlineCredential")]
[Microsoft.SharePoint.Client.SharePointOnlineCredentials]$SharePointOnlineCredential,
[Parameter(Mandatory=$false, ParameterSetName = "CredentialComponents")]
[Parameter(Mandatory=$false, ParameterSetName = "SharePointOnlineCredential")]
[int]$Delay = 10,
[Parameter(Mandatory=$false, ParameterSetName = "CredentialComponents")]
[Parameter(Mandatory=$false, ParameterSetName = "SharePointOnlineCredential")]
[int]$RetryAttempts = 5
)
begin
{
$executions = 1
$clientContext = $null
}
process
{
do
{
try
{
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($ContextUrl)
if( $PSCmdlet.ParameterSetName -eq "CredentialComponents" )
{
$clientContext.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
}
else
{
$clientContext.Credentials = $SharePointOnlineCredential
}
$clientContext.Load($clientContext.Web)
$clientContext.Load($clientContext.Site)
$clientContext.ExecuteQuery()
return $clientContext
}
catch [System.Net.WebException]
{
$response = $_.Exception.Response -as [System.Net.HttpWebResponse]
$statusCode = [int]$response.StatusCode
Write-Verbose "Full Exception Details: $($_.Exception)"
Write-Verbose "Status Code: $statusCode"
# 429 and 503 are throttling exceptions.
if( $response -and ($statusCode -eq 429 -or $statusCode -eq 503) )
{
Write-Warning -Message "Execution attempt $executions was throttled, trying again in $Delay seconds."
$executions++
Start-Sleep -Seconds $Delay
}
# seeing erroneous 403 exceptions that require a retry
elseif( $response -and $statusCode -eq 403 )
{
Write-Warning -Message "Execution attempt $executions was forbidden, trying again in $Delay seconds."
$executions++
Start-Sleep -Seconds $Delay
}
elseif( $response -and $statusCode -eq 404 )
{
Write-Warning -Message "A site with the URL $($ContextUrl) was not found in the tenant."
return $null
}
else
{
Write-Error -Message "An error occurred connecting to $($ContextUrl). Exception: $($_.Exception.Message)"
return $null
}
}
catch
{
Write-Verbose "Full Exception Details: $($_.Exception)"
if( $_.Exception.Message -match "Access to this Web site has been blocked")
{
Write-Warning -Message "Cannot contact site at the specified URL $ContextUrl. Access to this Web site has been blocked."
return $null
}
Write-Error -Message "$($MyInvocation.MyCommand.Name) - Unexpected execution exception: $($_.Exception.Message)"
return $null
}
}
while( $executions -le $RetryAttempts )
}
end
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment