Projektdateien hinzufügen.
This commit is contained in:
106
FileinterfaceCronScheduler/Scheduler/CronScheduler.cs
Normal file
106
FileinterfaceCronScheduler/Scheduler/CronScheduler.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FileInterface.Scheduler
|
||||
{
|
||||
public sealed class CronScheduler : IDisposable
|
||||
{
|
||||
private readonly CronJobRepository _repository;
|
||||
private readonly CronJobExecutor _executor;
|
||||
private readonly JobLog _log;
|
||||
private readonly ConcurrentDictionary<string, byte> _running = new ConcurrentDictionary<string, byte>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, string> _lastMinuteRun = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
private Timer _timer;
|
||||
private int _checking;
|
||||
|
||||
public CronScheduler(CronJobRepository repository, CronJobExecutor executor, JobLog log)
|
||||
{
|
||||
_repository = repository;
|
||||
_executor = executor;
|
||||
_log = log;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (_timer != null) return;
|
||||
_timer = new Timer(CheckDueJobs, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
|
||||
}
|
||||
|
||||
public bool RunNow(string jobId)
|
||||
{
|
||||
CronJobConfig job = _repository.GetById(jobId);
|
||||
if (job == null) return false;
|
||||
QueueExecution(job, "manual");
|
||||
return true;
|
||||
}
|
||||
|
||||
public IList<string> GetRunningJobIds()
|
||||
{
|
||||
return new List<string>(_running.Keys);
|
||||
}
|
||||
|
||||
private void CheckDueJobs(object state)
|
||||
{
|
||||
if (Interlocked.Exchange(ref _checking, 1) == 1) return;
|
||||
try
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
string minuteStamp = now.ToString("yyyyMMddHHmm");
|
||||
foreach (CronJobConfig job in _repository.GetAll())
|
||||
{
|
||||
if (!job.Enabled) continue;
|
||||
try
|
||||
{
|
||||
CronExpression cron = CronExpression.Parse(job.Cron);
|
||||
if (!cron.IsMatch(now)) continue;
|
||||
|
||||
string previous;
|
||||
if (_lastMinuteRun.TryGetValue(job.Id, out previous) && previous == minuteStamp) continue;
|
||||
_lastMinuteRun[job.Id] = minuteStamp;
|
||||
QueueExecution(job, "cron " + job.Cron);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error(job, "Invalid cron/configuration: " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally { Interlocked.Exchange(ref _checking, 0); }
|
||||
}
|
||||
|
||||
private void QueueExecution(CronJobConfig job, string reason)
|
||||
{
|
||||
byte ignored;
|
||||
if (!_running.TryAdd(job.Id, 0))
|
||||
{
|
||||
_log.Info(job, "Skipped " + reason + " start because this job is still running.");
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_log.Info(job, "Job started (" + reason + ").");
|
||||
_executor.Execute(job);
|
||||
_log.Info(job, "Job finished.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error(job, "Job crashed: " + ex);
|
||||
}
|
||||
finally { _running.TryRemove(job.Id, out ignored); }
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Timer timer = _timer;
|
||||
_timer = null;
|
||||
if (timer != null) timer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user