示例#1
0
 internal void OnJobFaulted(Exception ex, JobHolder jh)
 {
     reTry     = 0;
     lastError = ex;
     timesFaulted++;
     jh.Schedule.SetNextFireTime();
 }
示例#2
0
 internal void OnJobExecuted(JobHolder jh)
 {
     reTry     = 0;
     lastError = null;
     timesRun++;
     previousFireTime = jh.Schedule.GetNextFireTime();
     jh.Schedule.SetNextFireTime();
 }
示例#3
0
        /// <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);
        }