public IScheduledJob Add(Type type) { _locker.EnterUpgradeableReadLock(); try { var existingJob = _jobs.Any(_ => _.Type == type); if (existingJob) { throw new TempusException("The job is already scheduled."); } _locker.EnterWriteLock(); try { var job = new ScheduledJob(type); _jobs.Add(job); return(job); } finally { _locker.ExitWriteLock(); } } finally { _locker.ExitUpgradeableReadLock(); } }
private void Unlock(ScheduledJob job) { if (job.OverlapHandling != OverlapHandling.Wait) { return; } Monitor.Exit(job); }
internal ActiveJob(ScheduledJob job, CancellationToken cancellationToken) { _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); _disposed = false; ExecutionId = Interlocked.Increment(ref _executionId); Job = job; Started = DateTime.UtcNow; }
public IScheduledJob Add(string pattern, Func <JobExecutionContext, Task> handler, OverlapHandling overlapHandling = OverlapHandling.Allow) { var job = new ScheduledJob(pattern, handler, overlapHandling); _locker.EnterWriteLock(); try { _jobs.Add(job); } finally { _locker.ExitWriteLock(); } return(job); }
private void ExecuteJob(IJobFactory factory, IJobRunner runner, ScheduledJob job) { if (!OnJobStarting(job)) { return; } runner.Run(async() => { if (job.OverlapHandling == OverlapHandling.Skip && _activeJobs.Contains(job)) { return; } Lock(job); var activeJob = new ActiveJob(job, _cts.Token); _activeJobs.Add(activeJob); try { var context = new JobExecutionContext(this, activeJob.Token); OnJobStarted(context); try { if (!job.IsAnonymous) { using (var scope = factory.CreateScope()) { var instance = scope.Create(job.Type); await instance.ExecuteAsync(context); var supportsDispose = typeof(IDisposable).IsAssignableFrom(instance.GetType()); if (supportsDispose) { var disposable = (IDisposable)instance; disposable.Dispose(); } } } else { await job.Handler(context); } } catch (Exception ex) { if (OnJobError(context, ex)) { throw; } } OnJobFinished(job); } finally { _activeJobs.Remove(activeJob); Unlock(job); } }); }