Ejemplo n.º 1
0
        private async Task StartInternalAsync(string label, IPeriodicWork.WorkAsync work, Func <TimeSpan> interval, CancellationToken cancellation)
        {
            if (_isRunning)
            {
                _logger.LogError("PeriodicWork {PeriodicWorkId} is already running.", Id);
                ThrowHelper.ThrowInvalidOperationException("Cannot start a periodic work that's already running.");
                return;
            }

            _label = label;
            Interlocked.Exchange(ref _exceptionsCount, 0);

            _periodicWorkTracker.StartTracking(this);

            using (_cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellation))
            {
                CancellationToken token = _cancellationTokenSource.Token;

                _logger.LogDebug("PeriodicWork {PeriodicWorkId} is starting.", Id);
                _isRunning = true;
                while (!token.IsCancellationRequested)
                {
                    try
                    {
                        await work(token).WithCancellationAsync(token).ConfigureAwait(false);

                        await Task.Delay(interval()).WithCancellationAsync(token).ConfigureAwait(false);
                    }
                    catch (OperationCanceledException)
                    {
                        _logger.LogDebug("PeriodicWork {PeriodicWorkId} aborted.", Id);
                        break;
                    }
                    catch (Exception ex)
                    {
                        _lastException = ex;
                        Interlocked.Increment(ref _exceptionsCount);

                        var feedback = new IPeriodicWorkExceptionHandler.Feedback(!_stopOnException, false, null);
                        _exceptionHandler?.OnPeriodicWorkException(this, ex, ref feedback);

                        if (!feedback.ContinueExecution)
                        {
                            _logger.LogDebug("PeriodicWork {PeriodicWorkId} terminated because of {PeriodicWorkException}.", Id, ex);
                            _isRunning = false;

                            if (feedback.IsCritical)
                            {
                                _eventBus.Publish(new PeriodicWorkCriticallyStopped(_label, Id, _lastException, feedback.Message));
                            }

                            return;
                        }
                    }
                }

                _isRunning = false;

                if (ExceptionsCount == 0)
                {
                    _logger.LogDebug("PeriodicWork {PeriodicWorkId} terminated without errors.", Id);
                }
                else
                {
                    _logger.LogDebug("PeriodicWork {PeriodicWorkId} terminated with {PeriodicWorkErrors} errors.", Id, ExceptionsCount);
                }
            }

            _periodicWorkTracker.StopTracking(this);
        }
Ejemplo n.º 2
0
 public Task StartAsync(string label, IPeriodicWork.WorkAsync work, Func <TimeSpan> interval, CancellationToken cancellation)
 {
     return(StartInternalAsync(label, work, interval, cancellation));
 }