/// <summary> /// Main /// </summary> public static async Task Main(string[] args) { // --> #1 AcquireLock with retry. using (ILockObject outerLockObject = _lockFactory.AcquireLock(_lockKey, TimeSpan.FromSeconds(3))) using (ILockObject innerLockObject = _lockFactory.AcquireLock(_lockKey, TimeSpan.FromSeconds(5), 2, TimeSpan.FromSeconds(2))) Console.WriteLine($"Did I get a lock? -> {innerLockObject.IsAcquired}"); // --> #2 AcquireLockAsync with retry. using (ILockObject outerLockObject = await _lockFactory.AcquireLockAsync(_lockKey, TimeSpan.FromSeconds(3))) using (ILockObject innerLockObject = await _lockFactory.AcquireLockAsync(_lockKey, TimeSpan.FromSeconds(5), 2, TimeSpan.FromSeconds(2))) Console.WriteLine($"Did I get a lock? -> {innerLockObject.IsAcquired}"); // --> #3 AcquireLockAsync with retry + timeout. try { using (CancellationTokenSource ctSource = new CancellationTokenSource(TimeSpan.FromSeconds(3.5))) { using (ILockObject outerLockObject = await _lockFactory.AcquireLockAsync(_lockKey, TimeSpan.FromSeconds(3))) using (ILockObject innerLockObject = await _lockFactory.AcquireLockAsync(_lockKey, TimeSpan.FromSeconds(5), 2, TimeSpan.FromSeconds(2), ctSource.Token)) Console.WriteLine($"Did I get a lock? -> {innerLockObject.IsAcquired}"); } } catch (OperationCanceledException) { Console.WriteLine("I expected for an OperationCanceledException."); } // --> #4 Dinner is ready to eat. Parallel.For(0, 5, x => personEat(x)); Console.WriteLine("End of the dinner."); }
public async Task <TResponse> ExecuteAsync <TResponse>(string key, Func <CancellationToken, Task <TResponse> > action) { ILockObject @lock = await _lockFactory.AcquireLockAsync(key); DateTime processStarted = DateTime.UtcNow; try { using var subscribedCancellationSource = new CancellationTokenSource(); await _redisSubscriber.SubscribeAsync( key, (channel, _) => { _logger.LogInformation( $"A cancellation message was received for key: {key}" ); if (!subscribedCancellationSource.IsCancellationRequested) { subscribedCancellationSource.Cancel(); } } ).ConfigureAwait(false); TResponse response = await Policy .Handle <Exception>() .WaitAndRetryAsync(_distributedCancellationConfiguration.MaxRetries, _ => _distributedCancellationConfiguration.MaximumRetryDelay) .ExecuteAsync(() => { return(action(subscribedCancellationSource.Token)); }); _logger.LogDebug($"Finished processing for key: {key}"); await _databaseAsync.StringIncrementAsync(key); return(response); } catch (Exception ex) { throw new DistributedCancellationException("An exception happened", ex); } finally { await @lock.ReleaseAsync(); await _redisSubscriber.UnsubscribeAsync(key).ConfigureAwait(false); } }