From 81318b00ea460d7bda809f7d4bad8ff82ae06ad2 Mon Sep 17 00:00:00 2001 From: Ryan Date: Wed, 10 Apr 2024 15:21:48 +1000 Subject: [PATCH] just use Task.Delay() in conjunction with cron --- src/Hosting/Hosting/src/Workers/CronWorker.cs | 65 +++++++------------ .../CronWorkerTests.cs | 4 -- 2 files changed, 24 insertions(+), 45 deletions(-) diff --git a/src/Hosting/Hosting/src/Workers/CronWorker.cs b/src/Hosting/Hosting/src/Workers/CronWorker.cs index b010843..e6e0fc4 100644 --- a/src/Hosting/Hosting/src/Workers/CronWorker.cs +++ b/src/Hosting/Hosting/src/Workers/CronWorker.cs @@ -6,13 +6,11 @@ using Cronos; using Microsoft.Extensions.Logging; -public abstract class CronWorker : Worker, IDisposable +public abstract class CronWorker : Worker { private readonly ILogger _logger; private readonly Random _delayGenerator = new(); private readonly CronWorkerOption? _option; - private Timer? _timer; - private CancellationTokenSource? _cancellationTokenSource; // Cron format: https://www.nuget.org/packages/Cronos/ protected abstract string CronSchedule { get; } @@ -28,42 +26,36 @@ protected CronWorker(CronWorkerOption option, ILogger logger) : base(logger) _logger = logger; } - protected override Task ExecuteAsync(CancellationToken cancellationToken) + protected override async Task ExecuteAsync(CancellationToken cancellationToken) { - var dueTime = GetNextScheduleDelay(); - if (!dueTime.HasValue) - throw new Exception("Failed to get next schedule"); - - _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - _timer = new Timer(_ => TimerCallbackAsync(_cancellationTokenSource.Token), null, dueTime.Value, Timeout.InfiniteTimeSpan); + while (!cancellationToken.IsCancellationRequested) + { + var dueTime = GetNextScheduleDelay(); + if (!dueTime.HasValue) + { + _logger.LogWarning("Failed to get next schedule"); - return Task.CompletedTask; - } + // Wait for a while before retrying + await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); + continue; + } - private async void TimerCallbackAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - return; + try + { + await Task.Delay(dueTime.Value, cancellationToken); + } + catch (OperationCanceledException) + { + return; + } - try - { - await RunAsync(cancellationToken); - } - catch (Exception ex) - { - _logger.LogError(ex, "Unhandled exception caught in SchedulerWorker ({WorkerName})", Name); - } - finally - { - var dueTime = GetNextScheduleDelay(); - if (dueTime.HasValue) + try { - // Reschedule the timer - _timer?.Change(dueTime.Value, Timeout.InfiniteTimeSpan); + await RunAsync(cancellationToken); } - else + catch (Exception ex) { - _logger.LogError("Unable to get the next schedule in SchedulerWorker ({WorkerName})", Name); + _logger.LogError(ex, "Unhandled exception caught in CronWorker ({WorkerName})", Name); } } } @@ -87,14 +79,5 @@ private async void TimerCallbackAsync(CancellationToken cancellationToken) return delay.Add(extraDelay); } - public void Dispose() - { - _cancellationTokenSource?.Cancel(); - - // Stop the timer - _timer?.Change(Timeout.Infinite, 0); - _timer?.Dispose(); - } - protected abstract Task RunAsync(CancellationToken cancellationToken); } diff --git a/src/Hosting/Hosting/test/ClickView.Extensions.Hosting.Tests/CronWorkerTests.cs b/src/Hosting/Hosting/test/ClickView.Extensions.Hosting.Tests/CronWorkerTests.cs index c339ee7..f11f9f9 100644 --- a/src/Hosting/Hosting/test/ClickView.Extensions.Hosting.Tests/CronWorkerTests.cs +++ b/src/Hosting/Hosting/test/ClickView.Extensions.Hosting.Tests/CronWorkerTests.cs @@ -22,8 +22,6 @@ public async Task RunAsync_RunEveryTwoSeconds() await scheduler.StopAsync(CancellationToken.None); Assert.True(scheduler.Counter >= 2); - - scheduler.Dispose(); } [Fact] @@ -52,8 +50,6 @@ public async Task RunAsync_RunEveryTwoSeconds_return() Assert.NotNull(scheduler.FirstExecutionTime); Assert.True(scheduler.FirstExecutionTime.Value - currentTime > TimeSpan.FromSeconds(2)); - - scheduler.Dispose(); } public class TestScheduler : CronWorker