public void OnPeriodicWorkException(IPeriodicWork failedWork, Exception ex, ref IPeriodicWorkExceptionHandler.Feedback feedback)
 {
     _logger.LogCritical("An unhandled exception has been raised in the block validation loop.");
     feedback.IsCritical        = true;
     feedback.ContinueExecution = false;
     feedback.Message           = "Without block validation loop, it's impossible to advance in consensus. A node restart is required to fix the problem.";
 }
Exemple #2
0
        public void OnPeriodicWorkException(IPeriodicWork failedWork, Exception ex, ref IPeriodicWorkExceptionHandler.Feedback feedback)
        {
            if (failedWork == connectionLoop)
            {
                logger.LogCritical(ex, "Connector {Connector} failure, it has been stopped, node may have connection problems.", GetType().Name);
                feedback.ContinueExecution = false;
                feedback.IsCritical        = true;
                feedback.Message           = "Without Connector loop no new connection can be established, restart the node to fix the problem.";
                return;
            }

            feedback.ContinueExecution = true;
        }
Exemple #3
0
        public void OnPeriodicWorkException(IPeriodicWork failedWork, Exception ex, ref IPeriodicWorkExceptionHandler.Feedback feedback)
        {
            string?disconnectionReason = failedWork switch
            {
                IPeriodicWork work when work == _headerSyncLoop => "Peer header syncing loop had failures.",
                  _ => null
            };

            if (disconnectionReason != null)
            {
                feedback.ContinueExecution = false;
                PeerContext.Disconnect(disconnectionReason);
            }
        }
        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);
        }