protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation(
                CoreEventIds.BackgroundServiceStarting,
                "Starting background service {BackgroundService}...",
                GetType().FullName);

            // Run another task to avoid deadlocks
            return(Task.Factory.StartNew(
                       async() =>
            {
                try
                {
                    Lock = await _distributedLockManager.AcquireAsync(_distributedLockSettings, stoppingToken)
                           .ConfigureAwait(false);

                    if (Lock != null)
                    {
                        _logger.LogInformation(
                            CoreEventIds.BackgroundServiceLockAcquired,
                            "Lock acquired, executing background service {BackgroundService}.",
                            GetType().FullName);
                    }

                    await ExecuteLockedAsync(stoppingToken).ConfigureAwait(false);
                }
                catch (TaskCanceledException)
                {
                    // Don't log exception that is fired by the cancellation token.
                }
                catch (Exception ex)
                {
                    _logger.LogError(
                        CoreEventIds.BackgroundServiceException,
                        ex,
                        "Background service '{BackgroundService}' failed.",
                        GetType().FullName);
                }
                finally
                {
                    if (Lock != null)
                    {
                        await Lock.ReleaseAsync().ConfigureAwait(false);
                    }
                }
            },
                       stoppingToken,
                       TaskCreationOptions.LongRunning,
                       TaskScheduler.Default));
        }
        /// <inheritdoc cref="IDistributedLockManager.AcquireAsync" />
        public async Task <DistributedLock?> AcquireAsync(
            DistributedLockSettings settings,
            CancellationToken cancellationToken = default)
        {
            Check.NotNull(settings, nameof(settings));

            if (string.IsNullOrEmpty(settings.ResourceName))
            {
                throw new InvalidOperationException(
                          "ResourceName cannot be null. Please provide a valid resource name in the settings.");
            }

            if (settings is NullLockSettings)
            {
                return(await NullLockManager.AcquireAsync(settings, cancellationToken).ConfigureAwait(false));
            }

            _logger.LogInformation(
                CoreEventIds.AcquiringDistributedLock,
                "Trying to acquire lock {lockName} ({lockUniqueId})...",
                settings.ResourceName,
                settings.UniqueId);

            var stopwatch = Stopwatch.StartNew();

            while (settings.AcquireTimeout == null || stopwatch.Elapsed < settings.AcquireTimeout)
            {
                if (await TryAcquireLockAsync(settings).ConfigureAwait(false))
                {
                    _logger.LogInformation(
                        CoreEventIds.DistributedLockAcquired,
                        "Acquired lock {lockName} ({lockUniqueId}).",
                        settings.ResourceName,
                        settings.UniqueId);
                    return(new DistributedLock(settings, this));
                }

                await Task.Delay(settings.AcquireRetryInterval, cancellationToken).ConfigureAwait(false);

                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }
            }

            throw new TimeoutException($"Timeout waiting to get the required lock '{settings.ResourceName}'.");
        }
예제 #3
0
        /// <summary>
        ///     Ensures that the lock is still valid, otherwise tries to re-acquire it.
        /// </summary>
        /// <param name="cancellationToken">
        ///     A <see cref="CancellationToken" /> to observe while waiting for the task to complete.
        /// </param>
        /// <returns>
        ///     A <see cref="Task" /> representing the asynchronous operation.
        /// </returns>
        public async Task RenewAsync(CancellationToken cancellationToken = default)
        {
            if (Status == DistributedLockStatus.Released)
            {
                throw new InvalidOperationException("This lock was explicitly released and cannot be renewed.");
            }

            await CheckIsStillLockedAsync().ConfigureAwait(false);

            if (Status == DistributedLockStatus.Acquired)
            {
                await _lockManager.SendHeartbeatAsync(_settings).ConfigureAwait(false);
            }
            else
            {
                await _lockManager.AcquireAsync(_settings, cancellationToken).ConfigureAwait(false);

                Status = DistributedLockStatus.Acquired;
            }
        }
        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogBackgroundServiceStarting(this);

            // Run another task to avoid deadlocks
            return(Task.Factory.StartNew(
                       async() =>
            {
                try
                {
                    Lock = await _distributedLockManager.AcquireAsync(_distributedLockSettings, stoppingToken)
                           .ConfigureAwait(false);

                    if (Lock != null)
                    {
                        _logger.LogBackgroundServiceLockAcquired(this);
                    }

                    await ExecuteLockedAsync(stoppingToken).ConfigureAwait(false);
                }
                catch (TaskCanceledException)
                {
                    // Don't log exception that is fired by the cancellation token.
                }
                catch (Exception ex)
                {
                    _logger.LogBackgroundServiceException(this, ex);
                }
                finally
                {
                    if (Lock != null)
                    {
                        await Lock.ReleaseAsync().ConfigureAwait(false);
                    }
                }
            },
                       stoppingToken,
                       TaskCreationOptions.LongRunning,
                       TaskScheduler.Default));
        }