コード例 #1
0
        /// <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);
            }
        }