/// <summary> /// Executes any scheduled jobs that are due. /// </summary> private void ExecuteScheduledJobs() { int count = this.MaximumConcurrency - this.ExecutingJobCount; if (count > 0) { DateTime now = DateTime.UtcNow; long heartbeat = this.lastScheduleCheck == null ? this.Heartbeat : (long)Math.Ceiling(now.Subtract(this.lastScheduleCheck.Value).TotalMilliseconds); this.lastScheduleCheck = now; var scheduleNames = this.Schedules.Select(s => s.Name); var tuples = ScheduledJobTuple.GetExecutableTuples(this.ScheduledJobs, now, heartbeat, count); using (IJobStoreTransaction trans = this.store.BeginTransaction()) { try { foreach (ScheduledJobTuple tuple in tuples) { JobRecord record = ScheduledJob.CreateRecord(tuple.Schedule, tuple.ScheduledJob, now); bool running = this.runs.GetAll().Any( r => tuple.Schedule.Name.Equals(r.ScheduleName, StringComparison.OrdinalIgnoreCase) && tuple.ScheduledJob.JobType.StartsWith(record.JobType, StringComparison.OrdinalIgnoreCase)); if (!running) { IJob job = null; Exception toJobEx = null; try { job = ScheduledJob.CreateFromConfiguration(tuple.ScheduledJob); } catch (ConfigurationErrorsException ex) { toJobEx = ex; this.RaiseEvent(this.Error, new JobErrorEventArgs(record, toJobEx)); } if (job != null) { record.Name = job.Name; record.JobType = JobRecord.JobTypeString(job); record.Data = job.Serialize(); this.store.SaveJob(record, trans); JobRun run = new JobRun(record.Id.Value, job); run.Finished += new EventHandler<JobRunEventArgs>(this.JobRunFinished); this.runs.Add(run); run.Start(); this.RaiseEvent(this.ExecuteScheduledJob, new JobRecordEventArgs(record)); } else { record.Status = JobStatus.FailedToLoadType; record.FinishDate = now; record.Exception = new ExceptionXElement(toJobEx).ToString(); } this.store.SaveJob(record, trans); } } this.runs.Flush(); trans.Commit(); } catch { trans.Rollback(); throw; } } } }
/// <summary> /// Dequeues pending jobs in the job store. /// </summary> private void DequeueJobs() { int count = this.MaximumConcurrency - this.ExecutingJobCount; if (count > 0) { DateTime now = DateTime.UtcNow; using (IJobStoreTransaction trans = this.store.BeginTransaction()) { try { foreach (var record in this.store.GetJobs(JobStatus.Queued, count, now, trans)) { record.Status = JobStatus.Started; record.StartDate = now; IJob job = null; Exception toJobEx = null; try { job = record.ToJob(); } catch (InvalidOperationException ex) { toJobEx = ex.InnerException ?? ex; this.RaiseEvent(this.Error, new JobErrorEventArgs(record, toJobEx)); } if (job != null) { JobRun run = new JobRun(record.Id.Value, job); run.Finished += new EventHandler<JobRunEventArgs>(this.JobRunFinished); this.runs.Add(run); run.Start(); } else { record.Status = JobStatus.FailedToLoadType; record.FinishDate = now; record.Exception = new ExceptionXElement(toJobEx).ToString(); } this.store.SaveJob(record, trans); this.RaiseEvent(this.DequeueJob, new JobRecordEventArgs(record)); } this.runs.Flush(); trans.Commit(); } catch { trans.Rollback(); throw; } } } }