/// <summary>
        /// Ok time to call whatever it is we are trying to do
        /// </summary>
        private static void ExecuteWithRetryInternal(Action redisAction, IRedisRetryPolicy retryPolicy)
        {
            IRedisRetryPolicy callPolicy = null == retryPolicy ? _DefaultRetryPolicy : retryPolicy;
            int      retryCount          = callPolicy.MaxRetry;
            TimeSpan?delay = null;

            while (true)
            {
                try
                {
                    redisAction();
                    return;
                }
                catch (Exception callError)
                {
                    if (retryCount > 0 && callPolicy.ShouldRetry(callError))
                    {
                        retryCount--;
                        delay = callPolicy.CalculateDelay(retryCount);
                    }
                    else
                    {
                        throw;
                    }
                }
                if (delay.HasValue)
                {
                    //borrowed from Entity Framework execution strategy
                    using (var waitEvent = new ManualResetEventSlim(false))
                    {
                        waitEvent.WaitHandle.WaitOne(delay.Value);
                    }
                }
            }
        }
        /// <summary>
        /// In order for us to return the task, we need to create a new task
        /// that wraps the async action task so that it can be retried withen
        /// an external await
        /// </summary>
        private static Task <T> ExecuteWithRetryInternalAsync <T>(Func <Task <T> > asyncFunction, IRedisRetryPolicy retryPolicy)
        {
            IRedisRetryPolicy callPolicy = null == retryPolicy ? _DefaultRetryPolicy : retryPolicy;
            int      retryCount          = callPolicy.MaxRetry;
            Task <T> returnValue         = Task.Run <T>(async() =>
            {
                TimeSpan?delay = null;
                while (true)
                {
                    try
                    {
                        T taskResult = await asyncFunction();
                        return(taskResult);
                    }
                    catch (Exception callError)
                    {
                        if (retryCount > 0 && callPolicy.ShouldRetry(callError))
                        {
                            retryCount--;
                            delay = callPolicy.CalculateDelay(retryCount);
                        }
                        else
                        {
                            throw;
                        }
                    }
                    if (delay.HasValue)
                    {
                        await Task.Delay(delay.Value);
                    }
                }
            });

            return(returnValue);
        }