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); } }