Eric Yin
Eric Yin

Reputation: 8973

Read retry on Azure Table

I got error No connection could be made because the target machine actively refused it often, when read from Azure Table Storage, sometime on 80(http) sometime on 443(https)

I know I can setup retry for write by .SaveChangesWithRetries(), but how to apply retry on read?

btw, I read by code

DataServiceQuery<datatype> query = tableContext.CreateQuery<datatype>("table");
IQueryable<datatype> results= from q in query select q

Upvotes: 0

Views: 1507

Answers (2)

Ciaran
Ciaran

Reputation: 573

Use Polly: https://github.com/App-vNext/Polly to implement a retry handler which intercepts the error types / codes / etc you wish to handle and retry them. Polly is recommended by MS themselves for certain services (see: https://learn.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific and https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly) .. and i've found its fuild syntax to be a joy to use. Here's an example of a Polly retry handler i created to handle StorageException from Azure Storage. It implements an Exponential backoff (https://github.com/App-vNext/Polly/wiki/Retry#exponential-backoff) strategy.

int retries = 0;
int maxRetryAttempts = 5;

var retryStorageExceptionPolicy = Policy
    .Handle<StorageException>()
    .WaitAndRetry(maxRetryAttempts, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
        onRetry: (exception, calculatedWaitDuration) =>
        {
            retries++;
            loggingService.LogWarning(exception,
                new Dictionary<string, string>
                {
                    {"Message", $"A StorageException occurred when trying to Execute Query With Retry. This exception has been caught and will be retried." },
                    {"Current Retry Count", retries.ToString() },
                    {"tableName", table.Name},
                    {"ExtendedErrorInformation.ErrorCode", (exception as StorageException)?.RequestInformation.ExtendedErrorInformation.ErrorCode },
                    {"ExtendedErrorInformation.ErrorMessage", (exception as StorageException)?.RequestInformation.ExtendedErrorInformation.ErrorMessage }
                });
        });

retryStorageExceptionPolicy
    .ExecuteAndCapture(() =>
    {
        // your method accessing Azure Storage here                
    });

If you want a method to build a list of Transient error codes for Http calls let me know.

Upvotes: 0

Gleno
Gleno

Reputation: 16969

Last I had to use the semi-official Transient Fault Handling Framework, but this was over a year ago; and the best practices guidelines may have changed.

EDIT

As pointed out in the comments, this solution has evolved into a The Transient Fault Handling Application Block, which is now available as a NuGet package.

For the uninitiated, the framework basically specifies retry (hammer) policy for a class of transport-type errors that occur naturally in any distributed environment and particularly in Azure. For example SQL azure may return an error code "Server too busy, try again in a moment" or "Your data got lost on the way over here, oops", and you don't need to know all those codes in order to basically say "Retry".

Upvotes: 1

Related Questions