/// <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> /// execute the function and return a result using the retry policy /// </summary> public static T ExecuteWithRetry <T>(this IRedisRetryPolicy retryPolicy, Func <T> redisFunction) { var returnValue = default(T); ExecuteWithRetryInternal(() => returnValue = redisFunction(), retryPolicy); return(returnValue); }
/// <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); }
public RedisIntegrationTest() { _testObject = new CachingTestClass(); _serializedTestObject = KrakenSerializer.Serialize(_testObject); _redisRetryPolicy = new RedisRetryPolicy(50, 100, 150); _connection = new RedisConnection(RedisConnectionString, _redisRetryPolicy); }
/// <summary> /// Initializes a new instance of the <see cref="RedisConnection"/> class. /// </summary> /// <param name="connectionString">Connection string to Redis</param> /// <param name="redisRetryPolicy">Retry policy</param> public RedisConnection(string connectionString, IRedisRetryPolicy redisRetryPolicy) { _setKeyChannel = "~SetKey~:" + _instanceId; _baseRetryPolicy = Policy.Handle<TimeoutException>() .Or<TimeoutException>() .Or<SocketException>() .Or<IOException>(); // for async _retryPolicy = GetBaseRetryPolicyBuilder().WaitAndRetry(redisRetryPolicy.SleepDurations); _retryPolicyAsync = GetBaseRetryPolicyBuilder().WaitAndRetryAsync(redisRetryPolicy.SleepDurations); var options = ConfigurationOptions.Parse(connectionString); ConfigureIfMissing(options, "abortConnect", connectionString, o => { o.AbortOnConnectFail = false; }); ConfigureIfMissing(options, "allowAdmin", connectionString, o => { o.AllowAdmin = true; }); _multiplexer = ConnectionMultiplexer.Connect(options); _multiplexer.PreserveAsyncOrder = false; SubscribeToEvents(); }
/// <summary> /// execute the function and return an async task result using the retry policy /// </summary> public static Task <T> ExecuteWithRetryAsync <T>(this IRedisRetryPolicy retryPolicy, Func <Task <T> > asyncFunction) { return(ExecuteWithRetryInternalAsync(() => asyncFunction(), retryPolicy)); }
/// <summary> /// execute the action using the retry policy with async operations /// </summary> public static Task ExecuteWithRetryAsync(this IRedisRetryPolicy retryPolicy, Func <Task> redisAction) { return(ExecuteWithRetryInternalAsync(redisAction, retryPolicy)); }
/// <summary> /// execute the action using the retry policy /// </summary> public static void ExecuteWithRetry(this IRedisRetryPolicy retryPolicy, Action redisAction) { ExecuteWithRetryInternal(redisAction, retryPolicy); }