internal void OnJobFaulted(Exception ex, JobHolder jh) { reTry = 0; lastError = ex; timesFaulted++; jh.Schedule.SetNextFireTime(); }
internal void OnJobExecuted(JobHolder jh) { reTry = 0; lastError = null; timesRun++; previousFireTime = jh.Schedule.GetNextFireTime(); jh.Schedule.SetNextFireTime(); }
/// <summary> /// Entry point to start scheduler's execution /// </summary> /// <returns></returns> public virtual Task Run() { if (execTask != null) { return(execTask); } log.Debug("Scheduler starting ..."); running = true; paused = false; execTask = Task.Run(() => { log.Debug("Scheduler started"); while (running) { lock (pauseLock) { while (paused && running) { try { // wait until scheduler resumes Monitor.Wait(pauseLock, PauseWaitMs); } catch { } } if (!running) { break; } } DateTimeOffset now = Time.Now(); DateTimeOffset endTime = now.Add(timeDelta); nextJobs.Clear(); lock (jobsQueue) { while (true) { JobHolder jh = jobsQueue.FirstOrDefault(); if (jh == null) { break; } DateTimeOffset?nextFireTime = jh.Schedule.GetNextFireTime(); if (!nextFireTime.HasValue) { jobsQueue.Remove(jh); continue; } if (nextFireTime < now) { jobsQueue.Remove(jh); // check for misfire TimeSpan diff = now - nextFireTime.Value; jh.Schedule.HandleMisfire(now, diff); if (jh.Schedule.GetNextFireTime() != null) { jobsQueue.Add(jh); } continue; } if (nextFireTime > endTime) { break; } nextJobs.Add(jh); jobsQueue.Remove(jh); } } // end LOCK if (nextJobs.Count > 0) { // check if pause requested // just after jobs fetched bool pauseReq; lock (pauseLock) pauseReq = paused; if (pauseReq) { // save jobs until next resume lock (jobsQueue) { foreach (JobHolder jh in nextJobs) { jobsQueue.Add(jh); } continue; } } foreach (JobHolder jh in nextJobs) { Task.Run(async() => { try { await jh.Schedule.WaitUntilFire(); await jh.Job.Execute(jh.Context); jh.Context.OnJobExecuted(jh); lock (jobsQueue) jobsQueue.Add(jh); } catch (Exception ex) { Exception lastError = ex; int maxReTry = jh.Schedule.ReTryAttempts; if (maxReTry > 0) { while (maxReTry-- > 0) { try { jh.Context.IncrementReTryAttempt(); await jh.Job.Execute(jh.Context); jh.Context.OnJobExecuted(jh); lock (jobsQueue) jobsQueue.Add(jh); return; } catch (Exception exOnReTry) { lastError = exOnReTry; jh.Context.SetLastError(lastError); continue; } } } jh.Context.OnJobFaulted(lastError, jh); } }); } } } log.Debug("Scheduler shutting down ..."); }); return(execTask); }