Skip to content

Commit

Permalink
Get cron job last run time from cache
Browse files Browse the repository at this point in the history
  • Loading branch information
ejsmith committed Jul 26, 2024
1 parent 1176447 commit 5a8436e
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/Foundatio.Extensions.Hosting/Jobs/JobHostExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Foundatio.Extensions.Hosting.Startup;
using Foundatio.Jobs;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
Expand Down
5 changes: 1 addition & 4 deletions src/Foundatio.Extensions.Hosting/Jobs/ScheduledJobManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@

namespace Foundatio.Extensions.Hosting.Jobs;


// TODO: Persist last run time to cache so it's not lost on restart
// TODO: Add telemetry spans around job runs

public interface IScheduledJobManager
{
void AddOrUpdate<TJob>(string cronSchedule, Action<ScheduledJobOptionsBuilder> configure = null) where TJob : class, IJob;
void AddOrUpdate(string jobName, string cronSchedule, Action<ScheduledJobOptionsBuilder> configure = null);
void AddOrUpdate(string jobName, string cronSchedule, Func<IServiceProvider, CancellationToken, Task> action, Action<ScheduledJobOptionsBuilder> configure = null);
void AddOrUpdate(string jobName, string cronSchedule, Func<CancellationToken, Task> action, Action<ScheduledJobOptionsBuilder> configure = null);
void AddOrUpdate(string jobName, string cronSchedule, Func<Task> action, Action<ScheduledJobOptionsBuilder> configure = null);
Expand Down
13 changes: 12 additions & 1 deletion src/Foundatio.Extensions.Hosting/Jobs/ScheduledJobRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal class ScheduledJobRunner
private readonly ILockProvider _lockProvider;
private readonly ILogger _logger;
private readonly DateTime _baseDate = new(2010, 1, 1);
private bool _lastRunChecked = false;

public ScheduledJobRunner(ScheduledJobOptions jobOptions, IServiceProvider serviceProvider, ICacheClient cacheClient, ILoggerFactory loggerFactory = null)
{
Expand Down Expand Up @@ -70,8 +71,18 @@ public string Schedule
public DateTime? NextRun { get; private set; }
public Task RunTask { get; private set; }

public bool ShouldRun()
public async ValueTask<bool> ShouldRunAsync()
{
if (!_lastRunChecked && !LastRun.HasValue) {
var lastRun = await _cacheClient.GetAsync<DateTime>("lastrun:" + Options.Name).AnyContext();
if (lastRun.HasValue)
{
LastRun = lastRun.Value;
NextRun = _cronSchedule.GetNextOccurrence(LastRun.Value);
}
_lastRunChecked = true;
}

if (!NextRun.HasValue)
return false;

Expand Down
17 changes: 6 additions & 11 deletions src/Foundatio.Extensions.Hosting/Jobs/ScheduledJobService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ public class ScheduledJobService : BackgroundService, IJobStatus
{
private readonly IServiceProvider _serviceProvider;
private readonly ScheduledJobManager _jobManager;
private readonly ISystemClock _systemClock;

public ScheduledJobService(IServiceProvider serviceProvider, ScheduledJobManager jobManager)
{
_serviceProvider = serviceProvider;
_jobManager = jobManager;
_systemClock = serviceProvider.GetService<ISystemClock>() ?? SystemClock.Instance;

var lifetime = serviceProvider.GetService<ShutdownHostIfNoJobsRunningService>();
lifetime?.RegisterHostedJobInstance(this);
Expand All @@ -42,16 +40,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)

while (!stoppingToken.IsCancellationRequested)
{
var jobsToRun = _jobManager.Jobs.Where(j => j.ShouldRun()).ToArray();

foreach (var jobToRun in jobsToRun)
await jobToRun.StartAsync(stoppingToken).AnyContext();
foreach (var jobToRun in _jobManager.Jobs)
{
if (await jobToRun.ShouldRunAsync())
await jobToRun.StartAsync(stoppingToken).AnyContext();
}

// run jobs every minute since that is the lowest resolution of the cron schedule
var now = _systemClock.Now();
var nextMinute = now.AddTicks(TimeSpan.FromMinutes(1).Ticks - (now.Ticks % TimeSpan.FromMinutes(1).Ticks));
var timeUntilNextMinute = nextMinute.Subtract(now).Add(TimeSpan.FromMilliseconds(1));
await Task.Delay(timeUntilNextMinute, stoppingToken).AnyContext();
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken).AnyContext();
}
}
}

0 comments on commit 5a8436e

Please sign in to comment.