/// <summary> /// Cleanups the job history /// </summary> private void CleanupJobHistory() { using (RockContext rockContext = new RockContext()) { ServiceJobHistoryService serviceJobHistoryService = new ServiceJobHistoryService(rockContext); serviceJobHistoryService.DeleteMoreThanMax(); } }
/// <summary> /// Binds the scheduled jobs. /// </summary> private void BindGrid() { int?scheduledJobId = PageParameter("ScheduledJobId").AsIntegerOrNull(); if (scheduledJobId == null) { return; } var rockContext = new RockContext(); ServiceJobService jobService = new ServiceJobService(rockContext); var job = jobService.Get(scheduledJobId.Value); lJobName.Text = job.Name; var jobHistoryService = new ServiceJobHistoryService(rockContext); SortProperty sortProperty = gScheduledJobHistory.SortProperty; var qry = jobHistoryService.GetServiceJobHistory(scheduledJobId); if (sortProperty != null) { if (sortProperty.Property == "DurationSeconds") { if (sortProperty.Direction == SortDirection.Ascending) { qry = qry.OrderBy(a => System.Data.Entity.DbFunctions.DiffSeconds(a.StopDateTime, a.StartDateTime)); } else { qry = qry.OrderByDescending(a => System.Data.Entity.DbFunctions.DiffSeconds(a.StopDateTime, a.StartDateTime)); } } else { qry = qry.Sort(sortProperty); } } else { qry = qry.OrderByDescending(a => a.StartDateTime); } gScheduledJobHistory.SetLinqDataSource(qry); gScheduledJobHistory.DataBind(); }
/// <summary> /// Adds the service job history. /// </summary> /// <param name="job">The job.</param> /// <param name="rockContext">The rock context.</param> private void AddServiceJobHistory(ServiceJob job, RockContext rockContext) { var jobHistoryService = new ServiceJobHistoryService(rockContext); var jobHistory = new ServiceJobHistory() { ServiceJobId = job.Id, StartDateTime = job.LastRunDateTime?.AddSeconds(0.0d - ( double )job.LastRunDurationSeconds), StopDateTime = job.LastRunDateTime, Status = job.LastStatus, StatusMessage = job.LastStatusMessage, ServiceWorker = Environment.MachineName.ToLower() }; jobHistoryService.Add(jobHistory); rockContext.SaveChanges(); }
/// <summary> /// Starts the job scheduler. /// </summary> private static void StartJobScheduler() { using (var rockContext = new RockContext()) { // create scheduler ISchedulerFactory schedulerFactory = new StdSchedulerFactory(); QuartzScheduler = schedulerFactory.GetScheduler(); // get list of active jobs ServiceJobService jobService = new ServiceJobService(rockContext); var activeJobList = jobService.GetActiveJobs().OrderBy(a => a.Name).ToList(); foreach (ServiceJob job in activeJobList) { const string ErrorLoadingStatus = "Error Loading Job"; try { IJobDetail jobDetail = jobService.BuildQuartzJob(job); ITrigger jobTrigger = jobService.BuildQuartzTrigger(job); // Schedule the job (unless the cron expression is set to never run for an on-demand job like rebuild streaks) if (job.CronExpression != ServiceJob.NeverScheduledCronExpression) { QuartzScheduler.ScheduleJob(jobDetail, jobTrigger); } //// if the last status was an error, but we now loaded successful, clear the error // also, if the last status was 'Running', clear that status because it would have stopped if the app restarted if (job.LastStatus == ErrorLoadingStatus || job.LastStatus == "Running") { job.LastStatusMessage = string.Empty; job.LastStatus = string.Empty; rockContext.SaveChanges(); } } catch (Exception exception) { // create a friendly error message string message = $"Error loading the job: {job.Name}.\n\n{exception.Message}"; // log the error var startupException = new RockStartupException(message, exception); LogError(startupException, null); job.LastStatusMessage = message; job.LastStatus = ErrorLoadingStatus; job.LastStatus = ErrorLoadingStatus; rockContext.SaveChanges(); var jobHistoryService = new ServiceJobHistoryService(rockContext); var jobHistory = new ServiceJobHistory() { ServiceJobId = job.Id, StartDateTime = RockDateTime.Now, StopDateTime = RockDateTime.Now, Status = job.LastStatus, StatusMessage = job.LastStatusMessage }; jobHistoryService.Add(jobHistory); rockContext.SaveChanges(); } } // set up the listener to report back from jobs as they complete QuartzScheduler.ListenerManager.AddJobListener(new RockJobListener(), EverythingMatcher <JobKey> .AllJobs()); // set up a trigger listener that can prevent a job from running if another scheduler is // already running it (i.e., someone running it manually). QuartzScheduler.ListenerManager.AddTriggerListener(new RockTriggerListener(), EverythingMatcher <JobKey> .AllTriggers()); // start the scheduler QuartzScheduler.Start(); } }
/// <summary> /// Executes this instance. /// </summary> public void Execute() { using (var rockContext = new RockContext()) { var jobService = new ServiceJobService(rockContext); ServiceJob job = jobService.Get(JobId); if (job != null) { try { // create a scheduler specific for the job var scheduleConfig = new System.Collections.Specialized.NameValueCollection(); var runNowSchedulerName = ("RunNow:" + job.Guid.ToString("N")).Truncate(40); scheduleConfig.Add(StdSchedulerFactory.PropertySchedulerInstanceName, runNowSchedulerName); var schedulerFactory = new StdSchedulerFactory(scheduleConfig); var sched = new StdSchedulerFactory(scheduleConfig).GetScheduler(); if (sched.IsStarted) { // the job is currently running as a RunNow job return; } // create the quartz job and trigger IJobDetail jobDetail = jobService.BuildQuartzJob(job); var jobTrigger = TriggerBuilder.Create() .WithIdentity(job.Guid.ToString(), job.Name) .StartNow() .Build(); // schedule the job sched.ScheduleJob(jobDetail, jobTrigger); // set up the listener to report back from the job when it completes sched.ListenerManager.AddJobListener(new RockJobListener(), EverythingMatcher <JobKey> .AllJobs()); // start the scheduler sched.Start(); // Wait 10secs to give job chance to start System.Threading.Tasks.Task.Delay(new TimeSpan(0, 0, 10)).Wait(); // stop the scheduler when done with job sched.Shutdown(true); } catch (Exception ex) { // create a friendly error message ExceptionLogService.LogException(ex, null); string message = string.Format("Error doing a 'Run Now' on job: {0}. \n\n{2}", job.Name, job.Assembly, ex.Message); job.LastStatusMessage = message; job.LastStatus = "Error Loading Job"; rockContext.SaveChanges(); var jobHistoryService = new ServiceJobHistoryService(rockContext); var jobHistory = new ServiceJobHistory() { ServiceJobId = job.Id, StartDateTime = RockDateTime.Now, StopDateTime = RockDateTime.Now, Status = job.LastStatus, StatusMessage = job.LastStatusMessage }; jobHistoryService.Add(jobHistory); rockContext.SaveChanges(); } } } }
/// <summary> /// Executes this instance. /// </summary> public void Execute() { using (var rockContext = new RockContext()) { var jobService = new ServiceJobService(rockContext); ServiceJob job = jobService.Get(JobId); if (job != null) { try { // create a scheduler specific for the job var scheduleConfig = new System.Collections.Specialized.NameValueCollection(); var runNowSchedulerName = ("RunNow:" + job.Guid.ToString("N")).Truncate(40); scheduleConfig.Add(StdSchedulerFactory.PropertySchedulerInstanceName, runNowSchedulerName); var schedulerFactory = new StdSchedulerFactory(scheduleConfig); var sched = new StdSchedulerFactory(scheduleConfig).GetScheduler(); if (sched.IsStarted) { // the job is currently running as a RunNow job return; } // Check if another scheduler is running this job try { var otherSchedulers = new Quartz.Impl.StdSchedulerFactory().AllSchedulers .Where(s => s.SchedulerName != runNowSchedulerName); foreach (var scheduler in otherSchedulers) { if (scheduler.GetCurrentlyExecutingJobs().Where(j => j.JobDetail.Description == JobId.ToString() && j.JobDetail.ConcurrentExectionDisallowed).Any()) { // A job with that Id is already running and ConcurrentExectionDisallowed is true System.Diagnostics.Debug.WriteLine(RockDateTime.Now.ToString() + $" Scheduler '{scheduler.SchedulerName}' is already executing job Id '{JobId}' (name: {job.Name})"); return; } } } catch { } // create the quartz job and trigger IJobDetail jobDetail = jobService.BuildQuartzJob(job); if (_jobDataMapDictionary != null) { // Force the <string, string> dictionary so that within Jobs, it is always okay to use // JobDataMap.GetString(). This mimics Rock attributes always being stored as strings. // If we allow non-strings, like integers, then JobDataMap.GetString() throws an exception. jobDetail.JobDataMap.PutAll(_jobDataMapDictionary.ToDictionary(kvp => kvp.Key, kvp => ( object )kvp.Value)); } var jobTrigger = TriggerBuilder.Create() .WithIdentity(job.Guid.ToString(), job.Name) .StartNow() .Build(); // schedule the job sched.ScheduleJob(jobDetail, jobTrigger); // set up the listener to report back from the job when it completes sched.ListenerManager.AddJobListener(new RockJobListener(), EverythingMatcher <JobKey> .AllJobs()); // start the scheduler sched.Start(); // Wait 10secs to give job chance to start System.Threading.Tasks.Task.Delay(new TimeSpan(0, 0, 10)).Wait(); // stop the scheduler when done with job sched.Shutdown(true); } catch (Exception ex) { // create a friendly error message ExceptionLogService.LogException(ex, null); string message = string.Format("Error doing a 'Run Now' on job: {0}. \n\n{2}", job.Name, job.Assembly, ex.Message); job.LastStatusMessage = message; job.LastStatus = "Error Loading Job"; rockContext.SaveChanges(); var jobHistoryService = new ServiceJobHistoryService(rockContext); var jobHistory = new ServiceJobHistory() { ServiceJobId = job.Id, StartDateTime = RockDateTime.Now, StopDateTime = RockDateTime.Now, Status = job.LastStatus, StatusMessage = job.LastStatusMessage }; jobHistoryService.Add(jobHistory); rockContext.SaveChanges(); } } } }