BlogExamples
BlogExamples copied to clipboard
Cron - Not running multiple instances of a job
This is not an elaborate solution, but it works (in theory). You can't choose to have multiple instances running or not. I just assumed not to have multiple instances running regardless. I assumed this is not required unless you are running a job every minute or two.
I added a field to the scheduler that tracks the Task
returned by job.Run(stoppingToken);
. On ever tick check the list for completed tasks and clear them. Prior to running a job skip if it is on the list of running jobs.
I'm sure this might need some tweaking this was my first attempt at it.
private Dictionary<string, Task> _runningJobs;
.
.
.
// Clear completed jobs
foreach (var key in _runningJobs.Keys)
{
if (_runningJobs[key].IsCompleted)
{
_runningJobs[key].Dispose();
_runningJobs.Remove(key);
}
}
// Run jobs that are in the map
RunActiveJobs(runMap, now, stoppingToken);
.
.
.
foreach (var run in currentRuns)
{
// We are sure (thanks to our extension method)
// that the service is of type ICronJob
var job = (ICronJob)_serviceProvider.GetRequiredService(run);
string jobName = job.GetType().Name;
// Continue to next job if job is already running
if (_runningJobs.ContainsKey(jobName))
{
continue;
}
// We don't want to await jobs explicitly because that
// could interfere with other job runs
var task = job.Run(stoppingToken);
// Add task to running jobs
_runningJobs.Add(jobName, task);
}
I don't even think that the solution is "not an elaborate" as you put it. I would do the same and track the running tasks, which gives you the flexibility to:
- Have only one task running
- Or have
n
tasks running - Implement behavior like: "If I start a new task, the old should be cancelled"
I guess I would refactor this into its own class, but the underlying idea would be the same.
Small nitpick: You don't have to Dispose
tasks in general (99% of cases). There is a nice article from Stephan Toub: https://devblogs.microsoft.com/pfxteam/do-i-need-to-dispose-of-tasks/
I was wondering about the dispose
ing of a task, I backed that out. The additional features sound great and I would assume would be set when registering the job. Not only when to run the task, but how many.