public IBackgroundDispatcher Create(BackgroundServerContext context, BackgroundProcessingServerOptions options) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var execution = new BackgroundExecution( context.StoppingToken, new BackgroundExecutionOptions { Name = _process.GetType().Name, RetryDelay = options.RetryDelay }); return(new BackgroundDispatcherAsync( execution, ExecuteProcess, Tuple.Create(_process, context, execution), _taskScheduler(), _maxConcurrency, _ownsScheduler)); }
private IBackgroundDispatcher CreateDispatcher() { var execution = new BackgroundExecution( _stoppingCts.Token, new BackgroundExecutionOptions { Name = nameof(BackgroundServerProcess), ErrorThreshold = TimeSpan.Zero, StillErrorThreshold = TimeSpan.Zero, RetryDelay = retry => _options.RestartDelay }); return(new BackgroundDispatcher( execution, RunServer, execution, ThreadFactory)); }
public void Execute(Guid executionId, BackgroundExecution execution, CancellationToken stoppingToken, CancellationToken stoppedToken, CancellationToken shutdownToken) { var serverId = GetServerId(); Stopwatch stoppedAt = null; void HandleStopRestartSignal() => Interlocked.CompareExchange(ref stoppedAt, Stopwatch.StartNew(), null); void HandleStoppingSignal() => _logger.Info($"{GetServerTemplate(serverId)} caught stopping signal..."); void HandleStoppedSignal() => _logger.Info($"{GetServerTemplate(serverId)} caught stopped signal..."); void HandleShutdownSignal() => _logger.Warn($"{GetServerTemplate(serverId)} caught shutdown signal..."); void HandleRestartSignal() { if (!stoppingToken.IsCancellationRequested) { _logger.Info($"{GetServerTemplate(serverId)} caught restart signal..."); } } //using (LogProvider.OpenMappedContext("ServerId", serverId.ToString())) using (var restartCts = new CancellationTokenSource()) using (var restartStoppingCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, restartCts.Token)) using (var restartStoppedCts = CancellationTokenSource.CreateLinkedTokenSource(stoppedToken, restartCts.Token)) using (var restartShutdownCts = CancellationTokenSource.CreateLinkedTokenSource(shutdownToken, restartCts.Token)) using (restartStoppingCts.Token.Register(HandleStopRestartSignal)) using (stoppingToken.Register(HandleStoppingSignal)) using (stoppedToken.Register(HandleStoppedSignal)) using (shutdownToken.Register(HandleShutdownSignal)) using (restartCts.Token.Register(HandleRestartSignal)) { var context = new BackgroundServerContext( serverId, _storage, _properties, restartStoppingCts.Token, restartStoppedCts.Token, restartShutdownCts.Token); var dispatchers = new List <IBackgroundDispatcher>(); CreateServer(context); try { // ReSharper disable once AccessToDisposedClosure using (var heartbeat = CreateHeartbeatProcess(context, () => restartCts.Cancel())) { StartDispatchers(context, dispatchers); execution.NotifySucceeded(); WaitForDispatchers(context, dispatchers); restartCts.Cancel(); // TODO Either modify the IBackgroundDispatcher.Wait method to handle CancellationToken // or expose the WaitHandle property to not to perform sync-over-async and vice versa // in 2.0. heartbeat.WaitAsync(Timeout.InfiniteTimeSpan, shutdownToken).GetAwaiter().GetResult(); } } finally { DisposeDispatchers(dispatchers); ServerDelete(context, stoppedAt); } } }