/// <summary>
        /// Create an exponential backoff retry policy given a detection strategy.
        /// </summary>
        /// <param name="strategy"></param>
        /// <returns></returns>
        private static RetryPolicy Exponential(ITransientErrorDetectionStrategy strategy, int retryCount)
        {
            if (retryCount == 0)
                return RetryPolicy.NoRetry;

            if (retryCount == 1)
            {
                var retryPolicy = new RetryPolicy(strategy, 1);
                retryPolicy.RetryStrategy.FastFirstRetry = true;

                return retryPolicy;
            }

            var minBackoff = TimeSpan.FromSeconds(1);
            var maxBackoff = TimeSpan.FromSeconds(10);
            var deltaBackoff = TimeSpan.FromSeconds(5);

            // if retryCount is equal to Int16.MaxValue (32767)
            // then increase the backoff intervals.
            if (retryCount == Int16.MaxValue)
            {
                minBackoff = TimeSpan.FromSeconds(1);
                maxBackoff = TimeSpan.FromSeconds(300);
                deltaBackoff = TimeSpan.FromSeconds(10);
            }

            // 30 60 120 240

            var exponentialBackoff = new ExponentialBackoff(retryCount, minBackoff, maxBackoff, deltaBackoff);

            return new RetryPolicy(strategy, exponentialBackoff);
        }
        private static RetryPolicy Exponential(ITransientErrorDetectionStrategy strategy)
        {
            var retryCount = 3;
            var minBackoff = TimeSpan.FromSeconds(1);
            var maxBackoff = TimeSpan.FromSeconds(10);
            var deltaBackoff = TimeSpan.FromSeconds(5);

            var exponentialBackoff = new ExponentialBackoff(retryCount, minBackoff, maxBackoff, deltaBackoff);

            return new RetryPolicy(strategy, exponentialBackoff);
        }
        private void InitializeBackoffStrategy()
        {
            // Create Backoff Strategy
            _backoffStrategy = new ExponentialBackoff(
                "exponentialBackoffStrategy",
                Convert.ToInt32(ConfigurationManager.AppSettings["TransientFaultHandlingRetryCount"].Trim()),
                TimeSpan.FromSeconds(Convert.ToInt32(ConfigurationManager.AppSettings["TransientFaultHandlingMinBackoffDelaySeconds"].Trim())),
                TimeSpan.FromSeconds(Convert.ToInt32(ConfigurationManager.AppSettings["TransientFaultHandlingMaxBackoffDelaySeconds"].Trim())),
                TimeSpan.FromSeconds(Convert.ToInt32(ConfigurationManager.AppSettings["TransientFaultHandlingDeltaBackoffSeconds"].Trim())));

            // Set default retry manager
            RetryManager.SetDefault(new RetryManager(new List<RetryStrategy> { _backoffStrategy }, "exponentialBackoffStrategy"));
        }
        private static RetryPolicy Exponential(ITransientErrorDetectionStrategy stgy,
                                                int retryCount,
                                                double maxBackoffDelayInSeconds,
                                                double delta)
        {
            var maxBackoff = TimeSpan.FromSeconds(maxBackoffDelayInSeconds);
            var deltaBackoff = TimeSpan.FromSeconds(delta);
            var minBackoff = TimeSpan.FromSeconds(0);

            var exponentialBackoff = new ExponentialBackoff(retryCount,
                                                            minBackoff,
                                                            maxBackoff,
                                                            deltaBackoff);
            return new RetryPolicy(stgy, exponentialBackoff);
        }
        /// <summary>
        /// Initialize the Sql Azure settings and connections
        /// </summary>
        public void InitializeSqlAzure()
        {
            this.SqlConnectionString = ConfigurationManager.AppSettings["SqlAzureConnectionString"];
            if(String.IsNullOrWhiteSpace(this.SqlConnectionString))
            {
                throw new ArgumentException("A required AppSetting cannot be null or empty", "SqlAzureConnectionString");
            }

            this.SqlTableName = ConfigurationManager.AppSettings["SqlAzureTableName"];
            if (String.IsNullOrWhiteSpace(this.SqlTableName))
            {
                throw new ArgumentException("A required AppSetting cannot be null or empty", "SqlAzureTableName");
            }

            var columns = ConfigurationManager.AppSettings["SqlAzureTableColumns"];
            if (String.IsNullOrWhiteSpace(columns))
            {
                throw new ArgumentException("A required AppSetting cannot be null or empty", "SqlAzureTableColumns");
            }

            this.SqlTableColumns = columns.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries).Select(c => c.Trim()).ToList();

            //Reference: https://msdn.microsoft.com/en-us/library/azure/dn864744.aspx
            //1. Define an Exponential Backoff retry strategy for Azure SQL Database throttling (ExponentialBackoff Class). An exponential back-off strategy will gracefully back off the load on the service.
            int retryCount = 4;
            int minBackoffDelayMilliseconds = 2000;
            int maxBackoffDelayMilliseconds = 8000;
            int deltaBackoffMilliseconds = 2000;

            ExponentialBackoff exponentialBackoffStrategy = 
                new ExponentialBackoff("exponentialBackoffStrategy",
                    retryCount,
                    TimeSpan.FromMilliseconds(minBackoffDelayMilliseconds), 
                    TimeSpan.FromMilliseconds(maxBackoffDelayMilliseconds),
                    TimeSpan.FromMilliseconds(deltaBackoffMilliseconds));

            //2. Set a default strategy to Exponential Backoff.
            RetryManager manager = new RetryManager(
                new List<RetryStrategy>
                {  
                    exponentialBackoffStrategy 
                },
                "exponentialBackoffStrategy");

            //3. Set a default Retry Manager. A RetryManager provides retry functionality, or if you are using declarative configuration, you can invoke the RetryPolicyFactory.CreateDefault
            RetryManager.SetDefault(manager);

            //4. Define a default SQL Connection retry policy and SQL Command retry policy. A policy provides a retry mechanism for unreliable actions and transient conditions.
            ConnectionRetryPolicy = manager.GetDefaultSqlConnectionRetryPolicy();
            CommandRetryPolicy = manager.GetDefaultSqlCommandRetryPolicy();

            //5. Create a function that will retry the connection using a ReliableSqlConnection.
            InitializeSqlAzureConnection();
        }
        private static RetryPolicy Exponential(
            ITransientErrorDetectionStrategy strategy,
            int retryCount = 3,
            double maxBackoffDelayInSeconds = 1024,
            double delta = 2)
        {
            var exponentialBackoff = new ExponentialBackoff(retryCount,
                TimeSpan.FromSeconds(0),
                TimeSpan.FromSeconds(maxBackoffDelayInSeconds),
                TimeSpan.FromSeconds(delta));

            return new RetryPolicy(strategy,
                exponentialBackoff);
        }