/// <inheritdoc /> public async Task RunAsync(IInfiniteDeadManSwitchWorker worker, DeadManSwitchOptions options, CancellationToken cancellationToken) { if (worker == null) { throw new ArgumentNullException(nameof(worker)); } _logger.Trace("Starting infinite worker loop for {WorkerName} using a dead man's switch", worker.Name); using (var deadManSwitchSession = _deadManSwitchSessionFactory.Create(options)) using (var watcherCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) { var deadManSwitch = deadManSwitchSession.DeadManSwitch; var deadManSwitchWatcher = deadManSwitchSession.DeadManSwitchWatcher; var deadManSwitchContext = deadManSwitchSession.DeadManSwitchContext; var watcherTask = Task.Factory.StartNew(() => deadManSwitchWatcher.WatchAsync(watcherCTS.Token), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); var iteration = 1; while (!cancellationToken.IsCancellationRequested) { using (var workerCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, deadManSwitchContext.CancellationToken)) { _logger.Trace("Beginning work iteration {Iteration} of infinite worker {WorkerName} using a dead man's switch", iteration, worker.Name); var workerTask = Task.Run(() => worker.WorkAsync(deadManSwitch, workerCTS.Token), CancellationToken.None); try { await workerTask.ConfigureAwait(false); _logger.Debug("Worker {WorkerName} completed gracefully", worker.Name); deadManSwitch.Notify("Worker task completed gracefully"); } catch (OperationCanceledException) { _logger.Warning("Worker {WorkerName} was canceled", worker.Name); // Restart watcher await watcherTask.ConfigureAwait(false); deadManSwitch.Notify("Worker task was canceled"); watcherTask = Task.Factory.StartNew(() => deadManSwitchWatcher.WatchAsync(watcherCTS.Token), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } } iteration++; } _logger.Information("Cancellation requested, cleaning up infinite worker loop for {WorkerName}", worker.Name); watcherCTS.Cancel(); await watcherTask.ConfigureAwait(false); } _logger.Trace("Infinite worker loop for {WorkerName} has stopped", worker.Name); }
/// <inheritdoc /> public async Task <TResult> RunAsync <TResult>(IDeadManSwitchWorker <TResult> worker, DeadManSwitchOptions options, CancellationToken cancellationToken) { if (worker == null) { throw new ArgumentNullException(nameof(worker)); } using (var deadManSwitchSession = _deadManSwitchSessionFactory.Create(options)) using (var watcherCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var workerCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, deadManSwitchSession.DeadManSwitchContext.CancellationTokenSource.Token)) { _logger.Trace("Running worker {WorkerName} using a dead man's switch", worker.Name); var deadManSwitch = deadManSwitchSession.DeadManSwitch; var deadManSwitchWatcher = deadManSwitchSession.DeadManSwitchWatcher; var workerTask = Task.Run(async() => await worker.WorkAsync(deadManSwitch, workerCTS.Token).ConfigureAwait(false), CancellationToken.None); var watcherTask = Task.Run(async() => await deadManSwitchWatcher.WatchAsync(watcherCTS.Token).ConfigureAwait(false), CancellationToken.None); var task = await Task.WhenAny(workerTask, watcherTask).ConfigureAwait(false); if (task == workerTask) { watcherCTS.Cancel(); return(await workerTask.ConfigureAwait(false)); } workerCTS.Cancel(); throw new OperationCanceledException(workerCTS.Token); } }
public void Trigger() { _logger.Warning("The worker task did not notify the dead man's switch within the agreed timeout of {TimeoutInSeconds}s " + "and will be cancelled.", _deadManSwitchOptions.Timeout.TotalSeconds); var notifications = _deadManSwitchContext.Notifications.ToArray(); _logger.Warning("These were the last {NotificationCount} notifications: ", notifications.Length); foreach (var notification in notifications) { _logger.Warning("{NotificationTimestamp} {NotificationContent}", notification.Timestamp, notification.Content); } _logger.Trace("Marking worker cancellation token as cancelled"); _deadManSwitchContext.Cancel(); }
public async ValueTask TriggerAsync(CancellationToken cancellationToken) { _logger.Warning("The worker task did not notify the dead man's switch within the agreed timeout of {TimeoutInSeconds}s " + "and will be cancelled.", _deadManSwitchOptions.Timeout.TotalSeconds); var notifications = (await _deadManSwitchContext.GetNotificationsAsync(cancellationToken).ConfigureAwait(false)).ToList(); _logger.Warning("These were the last {NotificationCount} notifications: ", notifications.Count); foreach (var notification in notifications) { _logger.Warning("{NotificationTimestamp} {NotificationContent}", notification.Timestamp, notification.Content); } var cancellationTokenSource = _deadManSwitchContext.CancellationTokenSource; _deadManSwitchContext.CancellationTokenSource = new CancellationTokenSource(); _logger.Trace("Marking worker cancellation token as cancelled"); cancellationTokenSource.Cancel(); cancellationTokenSource.Dispose(); }