Eric Yin
Eric Yin

Reputation: 8993

Whats the correct code for Microsoft.Practices.TransientFaultHandling.RetryPolicy?

I use following code:

Create a retry policy, when error, retry after 1 second, then wait 3 seconds, then 5 seconds. based on Azure SLA, retry within 10 seconds must success (No throttled, I sure this. because error even happens on unique partition and table which no traffic yet)

var retryStrategy = new Incremental(3, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
var FaultHandlingRetryPolicy = new RetryPolicy<StorageTransientErrorDetectionStrategy>(retryStrategy);

Then I use this code to get data

FaultHandlingRetryPolicy .ExecuteAction(() =>
        {
            var results = (from q in Query select new q).ToList();
        });

I DO NOT KNOW if its retried or not, because the error log not shown

Errors:

System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 70.37.127.112:443
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at System.Data.Services.Client.QueryResult.Execute()
   at System.Data.Services.Client.DataServiceRequest.Execute[TElement](DataServiceContext context, QueryComponents queryComponents)
   at System.Data.Services.Client.DataServiceQuery`1.Execute()
   at System.Data.Services.Client.DataServiceQuery`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Microsoft.Practices.TransientFaultHandling.RetryPolicy.<>c__DisplayClass1.<ExecuteAction>b__0()
   at Microsoft.Practices.TransientFaultHandling.RetryPolicy.ExecuteAction[TResult](Func`1 func)

Please let me know if this code will retry, thanks

Upvotes: 1

Views: 4066

Answers (1)

Matt Warren
Matt Warren

Reputation: 10291

When you setup a retry policy, you specify the class that will control the retires, in your case it is StorageTransientErrorDetectionStrategy.

Each time an exception is thrown inside the ExecuteAction() method, this class will decide if a retry is possible or not. For instance some exceptions are transient, so it's not worth retrying them.

To actually track the number of retries, you can use code like this:

FaultHandlingRetryPolicy.Retrying += (obj, eventArgs) =>
            {
                Console.Writeline("Retrying, CurrentRetryCount = {0} , Exception = {1}", eventArgs.CurrentRetryCount, eventArgs.LastException.Message);
            };

Update

You can create your own error handling strategy like so and use it in-place of the standard one. BUT you'll have to tune the errors to fit with your scenario, these worked for me.

    public class CustomSqlAzureTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy
    {
        private readonly SqlAzureTransientErrorDetectionStrategy _normalStrategy =
            new SqlAzureTransientErrorDetectionStrategy();

        public bool IsTransient(Exception ex)
        {
            if (_normalStrategy.IsTransient(ex))
                return true;

            //do our custom logic
            if (ex is SqlException)
            {
                var sqEx = ex as SqlException;
                if (sqEx.Message.Contains("The timeout period elapsed prior to completion of the operation or the server is not responding") ||
                    sqEx.Message.Contains("An existing connection was forcibly closed by the remote host") ||
                    sqEx.Message.Contains("The service has encountered an error processing your request. Please try again") ||
                    sqEx.Message.Contains("Timeout expired") ||
                    sqEx.Message.Contains("was deadlocked on lock resources with another process and has been chosen as the deadlock victim") ||
                    sqEx.Message.Contains("A transport-level error has occurred when receiving results from the server"))
                {                        
                    return true;
                }
            }

            return false;
        }
    }

Upvotes: 5

Related Questions