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}'."); }
/// <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)); }