/// <summary> /// Shows the edit. /// </summary> /// <param name="jobId">The job id.</param> protected void ShowEdit(int jobId) { pnlDetails.Visible = true; pnlGrid.Visible = false; hfId.Value = jobId.ToString(); ServiceJob job = null; if (jobId != 0) { job = ServiceJob.Read(jobId); lActionTitle.Text = ActionTitle.Edit(ServiceJob.FriendlyTypeName); } else { job = new ServiceJob { IsActive = true }; lActionTitle.Text = ActionTitle.Add(ServiceJob.FriendlyTypeName); } tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; tbAssembly.Text = job.Assembly; tbClass.Text = job.Class; tbNotificationEmails.Text = job.NotificationEmails; drpNotificationStatus.SetValue((int)job.NotificationStatus); tbCronExpression.Text = job.CronExpression; }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Load" /> event. /// </summary> /// <param name="e">The <see cref="T:System.EventArgs" /> object that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (!Page.IsPostBack) { string itemId = PageParameter("serviceJobId"); if (!string.IsNullOrWhiteSpace(itemId)) { ShowDetail("serviceJobId", int.Parse(itemId)); } else { pnlDetails.Visible = false; } } if (pnlDetails.Visible) { var job = new ServiceJob { Id = int.Parse(hfId.Value), Class = ddlJobTypes.SelectedValue ?? "Rock.Jobs.JobPulse" }; if (job.Id > 0) { job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls(job, phAttributes, true); } } }
/// <summary> /// Builds a Quartz Job for a specified <see cref="Rock.Model.ServiceJob">Job</see> /// </summary> /// <param name="job">The <see cref="Rock.Model.ServiceJob"/> to create a Quarts Job for.</param> /// <returns>A object that implements the <see cref="Quartz.IJobDetail"/> interface</returns> public IJobDetail BuildQuartzJob( ServiceJob job ) { // build the type object, will depend if the class is in an assembly or the App_Code folder Type type = null; if ( job.Assembly == string.Empty || job.Assembly == null ) { type = BuildManager.GetType( job.Class, false ); } else { string thetype = string.Format( "{0}, {1}", job.Class, job.Assembly ); type = Type.GetType( thetype ); } // load up job attributes (parameters) job.LoadAttributes(); JobDataMap map = new JobDataMap(); foreach ( KeyValuePair<string, List<Rock.Model.AttributeValue>> attrib in job.AttributeValues ) { map.Add( attrib.Key, attrib.Value[0].Value ); } // create the quartz job object IJobDetail jobDetail = JobBuilder.Create( type ) .WithDescription( job.Id.ToString() ) .WithIdentity( new Guid().ToString(), job.Name ) .UsingJobData( map ) .Build(); return jobDetail; }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Load" /> event. /// </summary> /// <param name="e">The <see cref="T:System.EventArgs" /> object that contains the event data.</param> protected override void OnLoad( EventArgs e ) { base.OnLoad( e ); if ( !Page.IsPostBack ) { string itemId = PageParameter( "serviceJobId" ); if ( !string.IsNullOrWhiteSpace( itemId ) ) { ShowDetail( "serviceJobId", int.Parse( itemId ) ); } else { pnlDetails.Visible = false; } } if ( pnlDetails.Visible ) { var job = new ServiceJob { Id = int.Parse( hfId.Value ), Class = ddlJobTypes.SelectedValue ?? "Rock.Jobs.JobPulse" }; if ( job.Id > 0 ) { job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls( job, phAttributes, true ); } } }
/// <summary> /// Add the named job to the service given the execution step to perform with the specified schedule. /// </summary> /// <param name="name">The name of the job.</param> /// <param name="schedule">The schedule defining function.</param> /// <param name="executionStep">The step to perform on execution.</param> public void AddJob(string name, Func <DateTime, DateTime> schedule, Action executionStep) { this._log.Debug(string.Format("SchedulingService.AddJob({0})", name)); if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException("name", "Job Name cannot be null"); } if (schedule == null) { throw new ArgumentNullException("schedule", "The scheduling function cannot be null"); } if (executionStep == null) { throw new ArgumentNullException("executionStep", "The exectution step cannot be null"); } if (this._jobs.Any(i => JobComparison(i.Key, name))) { throw new ArgumentException("An job with the same name already exists in SchedulingService"); } IServiceJob job = new ServiceJob(name, schedule, executionStep); this._jobs.Add(job, null); this.ScheduleNextExecution(job); }
public ServiceJob GetAddTestJob(JobNotificationStatus jobNotificationStatus = JobNotificationStatus.None) { var testJob = new ServiceJob { IsSystem = true, IsActive = true, Name = "Test Job", Description = "This job is used for testing RockJobListener", Class = "Rock.Tests.Integration.Jobs.RockJobListenerTestJob", CronExpression = "0 0 1 * * ?", NotificationStatus = jobNotificationStatus, Guid = "84AE12A7-968B-4D28-AB39-81D36D1F230E".AsGuid(), NotificationEmails = "*****@*****.**" }; using (var rockContext = new RockContext()) { var serviceJobService = new ServiceJobService(rockContext); var job = serviceJobService.Get(testJob.Guid); if (job != null) { testJobId = job.Id; return(job); } serviceJobService.Add(testJob); rockContext.SaveChanges(); } testJobId = testJob.Id; return(testJob); }
/// <summary> /// Handles the SelectedIndexChanged event of the ddlJobTypes control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void ddlJobTypes_SelectedIndexChanged(object sender, EventArgs e) { ServiceJob job; var itemId = PageParameter("serviceJobId").AsInteger(); if (itemId == 0) { job = new ServiceJob { Id = 0, IsActive = true }; } else { job = new ServiceJobService(new RockContext()).Get(itemId); } job.Class = ddlJobTypes.SelectedValue; job.LoadAttributes(); if (tbDescription.Text.IsNullOrWhiteSpace() && tbName.Text.IsNullOrWhiteSpace()) { try { Type selectedJobType = Rock.Reflection.FindType(typeof(Quartz.IJob), job.Class); tbName.Text = Rock.Reflection.GetDisplayName(selectedJobType); tbDescription.Text = Rock.Reflection.GetDescription(selectedJobType); } catch { // ignore if there is a problem getting the description from the selected job.class } } phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls(job, phAttributes, true, BlockValidationGroup); }
/// <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 Thread.Sleep(new TimeSpan(0, 0, 10)); // 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(); } } } }
private void ProcessNotificationMessage(IJobExecutionContext context, ServiceJob job, IRockJobResult resultInfo) { bool sendMessage = (job.NotificationStatus == JobNotificationStatus.All); var result = resultInfo.Result.GetValueOrDefault(RockJobResultSpecifier.Succeeded); if (result == RockJobResultSpecifier.Failed) { if (job.NotificationStatus == JobNotificationStatus.Error) { sendMessage = true; } } if (!sendMessage) { return; } // Create a notification message. StringBuilder message = new StringBuilder(); message.Append(string.Format("The job {0} ran for {1} seconds on {2}. Below is the results:<p>", job.Name, context.JobRunTime.TotalSeconds, context.FireTimeUtc.Value.DateTime.ToLocalTime())); string resultStatusDescription; switch (resultInfo.Result.GetValueOrDefault(RockJobResultSpecifier.Failed)) { case RockJobResultSpecifier.Succeeded: resultStatusDescription = "Succeeded"; break; case RockJobResultSpecifier.CompletedWithWarnings: resultStatusDescription = "Completed with Warnings"; break; case RockJobResultSpecifier.Failed: default: resultStatusDescription = "Failed"; break; } message.Append("<p>Result:<br>" + resultStatusDescription); message.Append("<p>Message:<br>" + job.LastStatusMessage); if (result == RockJobResultSpecifier.Failed) { message.Append("<p>Inner Exception:<br>" + resultInfo.ResultDetails); } this.SendNotification(message.ToString()); }
/// <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) { jobService.RunNow(job, out _); } } }
public void TestGetCode() { var job = new ServiceJob { Command = "process.exe", Settings = new Settings { Home = "c:\\windows", Timeout = 86400 } }; Assert.AreEqual("ServiceJob,process.exe,c:\\windows,False,,,,,,,False,", job.GetJobCode()); }
/// <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 var scheduleConfig = new System.Collections.Specialized.NameValueCollection(); scheduleConfig.Add("org.quartz.scheduler.instanceName", "RunNow"); var sched = new StdSchedulerFactory(scheduleConfig).GetScheduler(); // 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 Thread.Sleep(new TimeSpan(0, 0, 10)); // stop the scheduler when done with job sched.Shutdown(true); } catch (Exception ex) { // create a friendly error message string message = string.Format("Error loading the job: {0}. Ensure that the correct version of the job's assembly ({1}.dll) in the websites App_Code directory. \n\n\n\n{2}", job.Name, job.Assembly, ex.Message); job.LastStatusMessage = message; job.LastStatus = "Error Loading Job"; rockContext.SaveChanges(); } } } }
/// <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(); }
private void ConfigReaderOnJobRead(object sender, ConfigReader.JobArgs jobArgs) { var job = jobArgs.Service ? (Job)ServiceJob.Parse(jobArgs, Settings) : CronJob.Parse(jobArgs, Settings); if (job == null) { return; } if (string.IsNullOrEmpty(job.Settings.Home)) { job.Settings.Home = Path.FullName; } job.VerifyExecutableExists(); Jobs.Add(job); }
private ServiceJob ConvertJob(Model.Job job) { ServiceJob serviceJob = new ServiceJob(); serviceJob.completed = job.Completed == true; serviceJob.description = job.Description; serviceJob.ID = job.ID; serviceJob.jobName = job.JobName; serviceJob.latitude = job.Latitude; serviceJob.longitude = job.Longitude; foreach (Model.JobAssignment assignment in job.JobAssignments) { serviceJob.jobAssignments.Add(ConvertJobAssignment(assignment)); } return(serviceJob); }
public ServiceJob[] GetJobs() { using (var db = new CoordinationDbContext()) { List <ServiceJob> serviceJobs = new List <ServiceJob>(); List <Model.Job> jobs = db.Jobs.Where(job => job.Completed == false).ToList(); foreach (Model.Job job in jobs) { ServiceJob servicejob = ConvertJob(job); //servicejob.assigned = job.Assigned == true; TODO:get from jobAssignments and request current user as parameter serviceJobs.Add(servicejob); } return(serviceJobs.ToArray()); } }
/// <summary> /// Handles the Delete event of the grdScheduledJobs control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param> protected void gScheduledJobs_Delete(object sender, RowEventArgs e) { ServiceJobService jobService = new ServiceJobService(); ServiceJob job = jobService.Get((int)e.RowKeyValue); string errorMessage; if (!jobService.CanDelete(job, out errorMessage)) { mdGridWarning.Show(errorMessage, ModalAlertType.Information); return; } jobService.Delete(job, CurrentPersonId); jobService.Save(job, CurrentPersonId); BindGrid(); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { ServiceJob job; var rockContext = new RockContext(); ServiceJobService jobService = new ServiceJobService(rockContext); int jobId = int.Parse(hfId.Value); if (jobId == 0) { job = new ServiceJob(); jobService.Add(job); } else { job = jobService.Get(jobId); } job.Name = tbName.Text; job.Description = tbDescription.Text; job.IsActive = cbActive.Checked; job.Class = ddlJobTypes.SelectedValue; job.NotificationEmails = tbNotificationEmails.Text; job.NotificationStatus = (JobNotificationStatus)int.Parse(ddlNotificationStatus.SelectedValue); job.CronExpression = tbCronExpression.Text; if (!job.IsValid) { // Controls will render the error messages return; } RockTransactionScope.WrapTransaction(() => { rockContext.SaveChanges(); job.LoadAttributes(rockContext); Rock.Attribute.Helper.GetEditValues(phAttributes, job); job.SaveAttributeValues(rockContext); }); NavigateToParentPage(); }
/// <summary> /// Builds a Quartz Job for a specified <see cref="Rock.Model.ServiceJob">Job</see> /// </summary> /// <param name="job">The <see cref="Rock.Model.ServiceJob"/> to create a Quarts Job for.</param> /// <returns>A object that implements the <see cref="Quartz.IJobDetail"/> interface</returns> public IJobDetail BuildQuartzJob( ServiceJob job ) { // build the type object, will depend if the class is in an assembly or the App_Code folder Type type = null; if ( string.IsNullOrWhiteSpace(job.Assembly) ) { // first try to load the job type from the App_Code folder type = BuildManager.GetType( job.Class, false ); if (type == null) { // if it couldn't be loaded from the app_code folder, look in Rock.dll string thetype = string.Format( "{0}, {1}", job.Class, this.GetType().Assembly.FullName ); type = Type.GetType( thetype ); } } else { // if an assembly is specified, load the type from that string thetype = string.Format( "{0}, {1}", job.Class, job.Assembly ); type = Type.GetType( thetype ); } // load up job attributes (parameters) job.LoadAttributes(); JobDataMap map = new JobDataMap(); foreach ( var attrib in job.AttributeValues ) { map.Add( attrib.Key, attrib.Value.Value ); } // create the quartz job object IJobDetail jobDetail = JobBuilder.Create( type ) .WithDescription( job.Id.ToString() ) .WithIdentity( job.Guid.ToString(), job.Name ) .UsingJobData( map ) .Build(); return jobDetail; }
/// <summary> /// Handles the Delete event of the grdScheduledJobs control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="RowEventArgs" /> instance containing the event data.</param> protected void gScheduledJobs_Delete(object sender, RowEventArgs e) { var rockContext = new RockContext(); var jobService = new ServiceJobService(rockContext); ServiceJob job = jobService.Get(e.RowKeyId); string errorMessage; if (!jobService.CanDelete(job, out errorMessage)) { mdGridWarning.Show(errorMessage, ModalAlertType.Information); return; } jobService.Delete(job); rockContext.SaveChanges(); BindGrid(); }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Load" /> event. /// </summary> /// <param name="e">The <see cref="T:System.EventArgs" /> object that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (!Page.IsPostBack) { ShowDetail(PageParameter("serviceJobId").AsInteger()); } if (pnlDetails.Visible) { var job = new ServiceJob { Id = int.Parse(hfId.Value), Class = ddlJobTypes.SelectedValue ?? "Rock.Jobs.JobPulse" }; job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls(job, phAttributes, true, BlockValidationGroup); } }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click( object sender, EventArgs e ) { ServiceJob job; ServiceJobService jobService = new ServiceJobService(); int jobId = int.Parse( hfId.Value ); if ( jobId == 0 ) { job = new ServiceJob(); jobService.Add( job, CurrentPersonId ); } else { job = jobService.Get( jobId ); } job.Name = tbName.Text; job.Description = tbDescription.Text; job.IsActive = cbActive.Checked; job.Assembly = tbAssembly.Text; job.Class = tbClass.Text; job.NotificationEmails = tbNotificationEmails.Text; job.NotificationStatus = (JobNotificationStatus)int.Parse( drpNotificationStatus.SelectedValue ); job.CronExpression = tbCronExpression.Text; if ( !job.IsValid ) { // Controls will render the error messages return; } RockTransactionScope.WrapTransaction( () => { jobService.Save( job, CurrentPersonId ); } ); BindGrid(); pnlDetails.Visible = false; pnlGrid.Visible = true; }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { ServiceJob job; ServiceJobService jobService = new ServiceJobService(); int jobId = int.Parse(hfId.Value); if (jobId == 0) { job = new ServiceJob(); jobService.Add(job, CurrentPersonId); } else { job = jobService.Get(jobId); } job.Name = tbName.Text; job.Description = tbDescription.Text; job.IsActive = cbActive.Checked; job.Assembly = tbAssembly.Text; job.Class = tbClass.Text; job.NotificationEmails = tbNotificationEmails.Text; job.NotificationStatus = (JobNotificationStatus)int.Parse(drpNotificationStatus.SelectedValue); job.CronExpression = tbCronExpression.Text; if (!job.IsValid) { // Controls will render the error messages return; } RockTransactionScope.WrapTransaction(() => { jobService.Save(job, CurrentPersonId); }); BindGrid(); pnlDetails.Visible = false; pnlGrid.Visible = true; }
/// <summary> /// Handles the SelectedIndexChanged event of the ddlJobTypes control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void ddlJobTypes_SelectedIndexChanged(object sender, EventArgs e) { ServiceJob job; var itemId = PageParameter("serviceJobId").AsInteger(); if (itemId == 0) { job = new ServiceJob { Id = 0, IsActive = true }; } else { job = new ServiceJobService(new RockContext()).Get(itemId); } job.Class = ddlJobTypes.SelectedValue; job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls(job, phAttributes, true, BlockValidationGroup); }
/// <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(); } } } }
/// <summary> /// Shows the edit. /// </summary> /// <param name="jobId">The job id.</param> protected void ShowEdit( int jobId ) { pnlDetails.Visible = true; pnlGrid.Visible = false; hfId.Value = jobId.ToString(); ServiceJob job = null; if ( jobId != 0 ) { job = ServiceJob.Read( jobId ); lActionTitle.Text = ActionTitle.Edit( ServiceJob.FriendlyTypeName ); } else { job = new ServiceJob { IsActive = true }; lActionTitle.Text = ActionTitle.Add( ServiceJob.FriendlyTypeName ); } tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; tbAssembly.Text = job.Assembly; tbClass.Text = job.Class; tbNotificationEmails.Text = job.NotificationEmails; drpNotificationStatus.SetValue( (int)job.NotificationStatus ); tbCronExpression.Text = job.CronExpression; }
/// <summary> /// Shows the detail. /// </summary> /// <param name="serviceJobId">The service job identifier.</param> public void ShowDetail( int serviceJobId ) { pnlDetails.Visible = true; LoadDropDowns(); // Load depending on Add(0) or Edit ServiceJob job = null; if ( !serviceJobId.Equals( 0 ) ) { job = new ServiceJobService( new RockContext() ).Get( serviceJobId ); lActionTitle.Text = ActionTitle.Edit( ServiceJob.FriendlyTypeName ).FormatAsHtmlTitle(); pdAuditDetails.SetEntity( job, ResolveRockUrl( "~" ) ); } if ( job == null ) { job = new ServiceJob { Id = 0, IsActive = true }; lActionTitle.Text = ActionTitle.Add( ServiceJob.FriendlyTypeName ).FormatAsHtmlTitle(); // hide the panel drawer that show created and last modified dates pdAuditDetails.Visible = false; } hfId.Value = job.Id.ToString(); tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; ddlJobTypes.SelectedValue = job.Class; tbNotificationEmails.Text = job.NotificationEmails; ddlNotificationStatus.SetValue( (int)job.NotificationStatus ); tbCronExpression.Text = job.CronExpression; if (job.Id == 0) { job.Class = ddlJobTypes.SelectedValue; lCronExpressionDesc.Visible = false; lLastStatusMessage.Visible = false; } else { lCronExpressionDesc.Text = ExpressionDescriptor.GetDescription( job.CronExpression, new Options { ThrowExceptionOnParseError = false } ); lCronExpressionDesc.Visible = true; lLastStatusMessage.Text = job.LastStatusMessage.ConvertCrLfToHtmlBr(); lLastStatusMessage.Visible = true; } job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls( job, phAttributes, true, BlockValidationGroup ); // render UI based on Authorized and IsSystem bool readOnly = false; nbEditModeMessage.Text = string.Empty; if ( !IsUserAuthorized( Authorization.EDIT ) ) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( ServiceJob.FriendlyTypeName ); } if ( job.IsSystem ) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlySystem( ServiceJob.FriendlyTypeName ); } if ( readOnly ) { lActionTitle.Text = ActionTitle.View( ServiceJob.FriendlyTypeName ).FormatAsHtmlTitle(); btnCancel.Text = "Close"; Rock.Attribute.Helper.AddDisplayControls( job, phAttributesReadOnly ); phAttributesReadOnly.Visible = true; phAttributes.Visible = false; tbCronExpression.Text = job.CronExpression; } tbName.ReadOnly = readOnly; tbDescription.ReadOnly = readOnly; cbActive.Enabled = !readOnly; ddlJobTypes.Enabled = !readOnly; tbNotificationEmails.ReadOnly = readOnly; ddlNotificationStatus.Enabled = !readOnly; tbCronExpression.ReadOnly = readOnly; btnSave.Visible = !readOnly; }
/// <summary> /// Shows the edit. /// </summary> /// <param name="jobId">The job id.</param> public void ShowDetail(string itemKey, int itemKeyValue) { // return if unexpected itemKey if (itemKey != "serviceJobId") { return; } pnlDetails.Visible = true; LoadDropDowns(); // Load depending on Add(0) or Edit ServiceJob job = null; if (!itemKeyValue.Equals(0)) { job = new ServiceJobService().Get(itemKeyValue); lActionTitle.Text = ActionTitle.Edit(ServiceJob.FriendlyTypeName); } else { job = new ServiceJob { Id = 0, IsActive = true }; lActionTitle.Text = ActionTitle.Add(ServiceJob.FriendlyTypeName); } hfId.Value = job.Id.ToString(); tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; tbAssembly.Text = job.Assembly; tbClass.Text = job.Class; tbNotificationEmails.Text = job.NotificationEmails; drpNotificationStatus.SetValue((int)job.NotificationStatus); tbCronExpression.Text = job.CronExpression; // render UI based on Authorized and IsSystem bool readOnly = false; nbEditModeMessage.Text = string.Empty; if (!IsUserAuthorized("Edit")) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed(ServiceJob.FriendlyTypeName); } if (job.IsSystem) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlySystem(ServiceJob.FriendlyTypeName); } if (readOnly) { lActionTitle.Text = ActionTitle.View(ServiceJob.FriendlyTypeName); btnCancel.Text = "Close"; } tbName.ReadOnly = readOnly; tbDescription.ReadOnly = readOnly; cbActive.Enabled = !readOnly; tbAssembly.ReadOnly = readOnly; tbClass.ReadOnly = readOnly; tbNotificationEmails.ReadOnly = readOnly; drpNotificationStatus.Enabled = !readOnly; tbCronExpression.ReadOnly = readOnly; btnSave.Visible = !readOnly; }
/// <summary> /// Handles the SelectedIndexChanged event of the ddlJobTypes control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void ddlJobTypes_SelectedIndexChanged( object sender, EventArgs e ) { ServiceJob job; var itemId = PageParameter( "serviceJobId" ).AsInteger(); if ( itemId == 0 ) { job = new ServiceJob { Id = 0, IsActive = true }; } else { job = new ServiceJobService( new RockContext() ).Get( itemId ); } job.Class = ddlJobTypes.SelectedValue; job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls( job, phAttributes, true, BlockValidationGroup ); }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Load" /> event. /// </summary> /// <param name="e">The <see cref="T:System.EventArgs" /> object that contains the event data.</param> protected override void OnLoad( EventArgs e ) { base.OnLoad( e ); if ( !Page.IsPostBack ) { ShowDetail( PageParameter( "serviceJobId" ).AsInteger() ); } if ( pnlDetails.Visible ) { var job = new ServiceJob { Id = int.Parse( hfId.Value ), Class = ddlJobTypes.SelectedValue ?? "Rock.Jobs.JobPulse" }; job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls( job, phAttributes, true, BlockValidationGroup ); } }
private static void SendNotificationMessage(JobExecutionException jobException, ServiceJob job) { var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null, null, new Lava.CommonMergeFieldsOptions { GetLegacyGlobalMergeFields = false }); mergeFields.Add("Job", job); try { if (jobException != null) { if (LavaService.RockLiquidIsEnabled) { mergeFields.Add("Exception", Hash.FromAnonymousObject(jobException)); } else { mergeFields.Add("Exception", LavaDataObject.FromAnonymousObject(jobException)); } } } catch { // ignore } var notificationEmailAddresses = job.NotificationEmails.ResolveMergeFields(mergeFields).SplitDelimitedValues().ToList(); var emailMessage = new RockEmailMessage(Rock.SystemGuid.SystemCommunication.CONFIG_JOB_NOTIFICATION.AsGuid()); emailMessage.AdditionalMergeFields = mergeFields; emailMessage.CreateCommunicationRecord = false; // NOTE: the EmailTemplate may also have TO: defined, so even if there are no notificationEmailAddress defined for this specific job, we still should send the mail foreach (var notificationEmailAddress in notificationEmailAddresses) { emailMessage.AddRecipient(RockEmailMessageRecipient.CreateAnonymous(notificationEmailAddress, null)); } emailMessage.Send(); }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click( object sender, EventArgs e ) { try { ExpressionDescriptor.GetDescription( tbCronExpression.Text ); } catch (Exception ex) { tbCronExpression.ShowErrorMessage( "Invalid Cron Expression: " + ex.Message ); return; } ServiceJob job; var rockContext = new RockContext(); ServiceJobService jobService = new ServiceJobService( rockContext ); int jobId = int.Parse( hfId.Value ); if ( jobId == 0 ) { job = new ServiceJob(); jobService.Add( job ); } else { job = jobService.Get( jobId ); } job.Name = tbName.Text; job.Description = tbDescription.Text; job.IsActive = cbActive.Checked; if (job.Class != ddlJobTypes.SelectedValue) { job.Class = ddlJobTypes.SelectedValue; //// if the Class has changed, the current Assembly value might not match, //// so set the Assembly to null to have Rock figure it out automatically job.Assembly = null; } job.NotificationEmails = tbNotificationEmails.Text; job.NotificationStatus = (JobNotificationStatus)int.Parse( ddlNotificationStatus.SelectedValue ); job.CronExpression = tbCronExpression.Text; if ( !job.IsValid ) { // Controls will render the error messages return; } rockContext.WrapTransaction( () => { rockContext.SaveChanges(); job.LoadAttributes( rockContext ); Rock.Attribute.Helper.GetEditValues( phAttributes, job ); job.SaveAttributeValues( rockContext ); } ); NavigateToParentPage(); }
/// <summary> /// Builds a Quartz schedule trigger /// </summary> /// <param name="job">The <see cref="Rock.Model.ServiceJob">Job</see> to create a <see cref="Quartz.ITrigger"/> compatible Trigger.</param> /// <returns>A Quartz trigger that implements <see cref="Quartz.ITrigger"/> for the specified job.</returns> public ITrigger BuildQuartzTrigger( ServiceJob job ) { // create quartz trigger ITrigger trigger = ( ICronTrigger )TriggerBuilder.Create() .WithIdentity( new Guid().ToString(), job.Name ) .WithCronSchedule( job.CronExpression ) .StartNow() .Build(); return trigger; }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click(object sender, EventArgs e) { try { ExpressionDescriptor.GetDescription(tbCronExpression.Text); } catch (Exception ex) { tbCronExpression.ShowErrorMessage("Invalid Cron Expression: " + ex.Message); return; } ServiceJob job; var rockContext = new RockContext(); ServiceJobService jobService = new ServiceJobService(rockContext); int jobId = int.Parse(hfId.Value); if (jobId == 0) { job = new ServiceJob(); jobService.Add(job); } else { job = jobService.Get(jobId); } job.Name = tbName.Text; job.Description = tbDescription.Text; job.IsActive = cbActive.Checked; if (job.Class != ddlJobTypes.SelectedValue) { job.Class = ddlJobTypes.SelectedValue; //// if the Class has changed, the current Assembly value might not match, //// so set the Assembly to null to have Rock figure it out automatically job.Assembly = null; } job.NotificationEmails = tbNotificationEmails.Text; job.NotificationStatus = (JobNotificationStatus)int.Parse(ddlNotificationStatus.SelectedValue); job.CronExpression = tbCronExpression.Text; if (!job.IsValid) { // Controls will render the error messages return; } rockContext.WrapTransaction(() => { rockContext.SaveChanges(); job.LoadAttributes(rockContext); Rock.Attribute.Helper.GetEditValues(phAttributes, job); job.SaveAttributeValues(rockContext); }); NavigateToParentPage(); }
/// <summary> /// Shows the detail. /// </summary> /// <param name="serviceJobId">The service job identifier.</param> public void ShowDetail(int serviceJobId) { pnlDetails.Visible = true; LoadDropDowns(); // Load depending on Add(0) or Edit ServiceJob job = null; if (!serviceJobId.Equals(0)) { job = new ServiceJobService(new RockContext()).Get(serviceJobId); lActionTitle.Text = ActionTitle.Edit(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); } if (job == null) { job = new ServiceJob { Id = 0, IsActive = true }; lActionTitle.Text = ActionTitle.Add(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); } hfId.Value = job.Id.ToString(); tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; ddlJobTypes.SelectedValue = job.Class; tbNotificationEmails.Text = job.NotificationEmails; ddlNotificationStatus.SetValue((int)job.NotificationStatus); tbCronExpression.Text = job.CronExpression; if (job.Id == 0) { job.Class = ddlJobTypes.SelectedValue; lCronExpressionDesc.Visible = false; lLastStatusMessage.Visible = false; } else { lCronExpressionDesc.Text = ExpressionDescriptor.GetDescription(job.CronExpression, new Options { ThrowExceptionOnParseError = false }); lCronExpressionDesc.Visible = true; lLastStatusMessage.Text = job.LastStatusMessage.ConvertCrLfToHtmlBr(); lLastStatusMessage.Visible = true; } job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls(job, phAttributes, true, BlockValidationGroup); // render UI based on Authorized and IsSystem bool readOnly = false; nbEditModeMessage.Text = string.Empty; if (!IsUserAuthorized(Authorization.EDIT)) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed(ServiceJob.FriendlyTypeName); } if (job.IsSystem) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlySystem(ServiceJob.FriendlyTypeName); } if (readOnly) { lActionTitle.Text = ActionTitle.View(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); btnCancel.Text = "Close"; Rock.Attribute.Helper.AddDisplayControls(job, phAttributesReadOnly); phAttributesReadOnly.Visible = true; phAttributes.Visible = false; tbCronExpression.Text = job.CronExpression; } tbName.ReadOnly = readOnly; tbDescription.ReadOnly = readOnly; cbActive.Enabled = !readOnly; ddlJobTypes.Enabled = !readOnly; tbNotificationEmails.ReadOnly = readOnly; ddlNotificationStatus.Enabled = !readOnly; tbCronExpression.ReadOnly = readOnly; btnSave.Visible = !readOnly; }
/// <summary> /// Called by the <see cref="IScheduler"/> after a <see cref="IJobDetail"/> /// has been executed, and before the associated <see cref="Quartz.Spi.IOperableTrigger"/>'s /// <see cref="Quartz.Spi.IOperableTrigger.Triggered"/> method has been called. /// </summary> /// <param name="context"></param> /// <param name="jobException"></param> public void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException) { RockJobResultSpecifier result; IRockJobResult resultInfo; Exception exceptionToLog = null; ServiceJob job = null; // If the Job threw an Exception, create a corresponding RockJobResult object and find the appropriate Exception to log. if (jobException != null) { exceptionToLog = jobException; resultInfo = new RockJobResult(); resultInfo.Result = RockJobResultSpecifier.Failed; // Unpack the Scheduler Exceptions to get the Exception thrown by the Task itself. while (exceptionToLog is SchedulerException && exceptionToLog.InnerException != null) { exceptionToLog = exceptionToLog.InnerException; } var summaryException = exceptionToLog; if (summaryException is AggregateException) { var aggregateException = (AggregateException)summaryException; if (aggregateException.InnerExceptions != null) { if (aggregateException.InnerExceptions.Count == 1) { // if it's an aggregate, but there is only one, convert it to a single exception summaryException = aggregateException.InnerExceptions[0]; } else { summaryException = aggregateException.Flatten(); } } } resultInfo.ResultDescription = summaryException.Message; var ex = summaryException.InnerException; string details = string.Empty;; while (ex != null) { details += "\n--> " + ex.Message; ex = ex.InnerException; } resultInfo.ResultDetails = details.Trim('\n'); } else { resultInfo = context.Result as IRockJobResult; // If the Job did not return a result object and did not throw an Exception, assume success. if (resultInfo == null) { resultInfo = new RockJobResult(); resultInfo.Result = RockJobResultSpecifier.Succeeded; } else { // If the Job returned a failure in the result object, create a corresponding Exception for logging purposes. if (resultInfo.Result.HasValue && resultInfo.Result.Value == RockJobResultSpecifier.Failed) { exceptionToLog = new Exception(resultInfo.ResultDescription); } } } // Update the Job with the most recent result. result = resultInfo.Result.GetValueOrDefault(RockJobResultSpecifier.Succeeded); // Retrieve the Job details. int jobId = Convert.ToInt16(context.JobDetail.Description); using (var rockContext = new RockContext()) { var jobService = new ServiceJobService(rockContext); job = jobService.Get(jobId); // set last run date job.LastRunDateTime = RockDateTime.Now; // set run time job.LastRunDurationSeconds = Convert.ToInt32(context.JobRunTime.TotalSeconds); // set the scheduler name job.LastRunSchedulerName = context.Scheduler.SchedulerName; switch (result) { case RockJobResultSpecifier.Succeeded: job.LastStatus = "Success"; job.LastSuccessfulRunDateTime = job.LastRunDateTime; break; case RockJobResultSpecifier.CompletedWithWarnings: job.LastStatus = "Warning"; job.LastSuccessfulRunDateTime = job.LastRunDateTime; break; case RockJobResultSpecifier.Failed: job.LastStatus = "Exception"; break; } job.LastStatusMessage = resultInfo.ResultDescription; if (!string.IsNullOrEmpty(resultInfo.ResultDetails)) { job.LastStatusMessage += "\n" + resultInfo.ResultDetails; } // Save changes to the Job. rockContext.SaveChanges(); } if (result == RockJobResultSpecifier.Failed) { // log the exception to the database ExceptionLogService.LogException(exceptionToLog, null); } this.ProcessNotificationMessage(context, job, resultInfo); }
/// <summary> /// Handles the RowDataBound event of the gScheduledJobs control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewRowEventArgs"/> instance containing the event data.</param> protected void gScheduledJobs_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e) { var site = RockPage.Site; if (e.Row.RowType == DataControlRowType.DataRow) { ServiceJob serviceJob = e.Row.DataItem as ServiceJob; if (serviceJob == null) { return; } // Remove the "Run Now" option and "History" button from the Job Pulse job Guid?jobGuid = serviceJob.Guid; if (jobGuid.HasValue && jobGuid.Value.Equals(Rock.SystemGuid.ServiceJob.JOB_PULSE.AsGuid())) { var runNowColumn = gScheduledJobs.ColumnsOfType <EditField>().Where(a => a.HeaderText == "Run Now").FirstOrDefault(); e.Row.Cells[gScheduledJobs.GetColumnIndex(runNowColumn)].Text = string.Empty; var historyColumn = gScheduledJobs.ColumnsOfType <LinkButtonField>().Where(a => a.HeaderText == "History").FirstOrDefault(); e.Row.Cells[gScheduledJobs.GetColumnIndex(historyColumn)].Text = string.Empty; } // format duration if (serviceJob.LastRunDurationSeconds.HasValue) { int durationSeconds = serviceJob.LastRunDurationSeconds.Value; TimeSpan duration = TimeSpan.FromSeconds(durationSeconds); var lLastRunDurationSeconds = e.Row.FindControl("lLastRunDurationSeconds") as Literal; if (lLastRunDurationSeconds != null) { if (duration.Days > 0) { lLastRunDurationSeconds.Text = duration.TotalHours.ToString("F2") + " hours"; } else if (duration.Hours > 0) { lLastRunDurationSeconds.Text = String.Format("{0:%h}h {0:%m}m {0:%s}s", duration); } else if (duration.Minutes > 0) { lLastRunDurationSeconds.Text = String.Format("{0:%m}m {0:%s}s", duration); } else { lLastRunDurationSeconds.Text = String.Format("{0:%s}s", duration); } } } // format inactive jobs if (serviceJob.IsActive == false) { e.Row.AddCssClass("inactive"); } // format last status var lLastStatus = e.Row.FindControl("lLastStatus") as Literal; if (serviceJob.LastStatus.IsNotNullOrWhiteSpace()) { string lastStatus = serviceJob.LastStatus; switch (lastStatus) { case "Success": lLastStatus.Text = "<span class='label label-success'>Success</span>"; break; case "Running": lLastStatus.Text = "<span class='label label-info'>Running</span>"; break; case "Exception": lLastStatus.Text = "<span class='label label-danger'>Failed</span>"; break; case "Warning": lLastStatus.Text = "<span class='label label-warning'>Warning</span>"; break; case "": lLastStatus.Text = ""; break; default: lLastStatus.Text = String.Format("<span class='label label-warning'>{0}</span>", lastStatus); break; } } var lLastStatusMessageAsHtml = e.Row.FindControl("lLastStatusMessageAsHtml") as Literal; if (lLastStatusMessageAsHtml != null) { lLastStatusMessageAsHtml.Text = serviceJob.LastStatusMessageAsHtml; } } }
/// <summary> /// Shows the detail. /// </summary> /// <param name="itemKey">The item key.</param> /// <param name="itemKeyValue">The item key value.</param> public void ShowDetail(string itemKey, int itemKeyValue) { // return if unexpected itemKey if (itemKey != "serviceJobId") { return; } pnlDetails.Visible = true; LoadDropDowns(); // Load depending on Add(0) or Edit ServiceJob job; if (!itemKeyValue.Equals(0)) { job = new ServiceJobService().Get(itemKeyValue); lActionTitle.Text = ActionTitle.Edit(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); } else { job = new ServiceJob { Id = 0, IsActive = true }; lActionTitle.Text = ActionTitle.Add(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); } hfId.Value = job.Id.ToString(); tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; ddlJobTypes.SelectedValue = job.Class; tbNotificationEmails.Text = job.NotificationEmails; ddlNotificationStatus.SetValue((int)job.NotificationStatus); tbCronExpression.Text = job.CronExpression; if (job.Id == 0) { job.Class = ddlJobTypes.SelectedValue; } job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls(job, phAttributes, true); // render UI based on Authorized and IsSystem bool readOnly = false; nbEditModeMessage.Text = string.Empty; if (!IsUserAuthorized("Edit")) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed(ServiceJob.FriendlyTypeName); } if (job.IsSystem) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlySystem(ServiceJob.FriendlyTypeName); } if (readOnly) { lActionTitle.Text = ActionTitle.View(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); btnCancel.Text = "Close"; Rock.Attribute.Helper.AddDisplayControls(job, phAttributesReadOnly); phAttributesReadOnly.Visible = true; phAttributes.Visible = false; tbCronExpression.Text = ExpressionDescriptor.GetDescription(job.CronExpression); } tbName.ReadOnly = readOnly; tbDescription.ReadOnly = readOnly; cbActive.Enabled = !readOnly; ddlJobTypes.Enabled = !readOnly; tbNotificationEmails.ReadOnly = readOnly; ddlNotificationStatus.Enabled = !readOnly; tbCronExpression.ReadOnly = readOnly; btnSave.Visible = !readOnly; }
/// <summary> /// Shows the detail. /// </summary> /// <param name="itemKey">The item key.</param> /// <param name="itemKeyValue">The item key value.</param> public void ShowDetail( string itemKey, int itemKeyValue ) { // return if unexpected itemKey if ( itemKey != "serviceJobId" ) { return; } pnlDetails.Visible = true; LoadDropDowns(); // Load depending on Add(0) or Edit ServiceJob job; if ( !itemKeyValue.Equals( 0 ) ) { job = new ServiceJobService( new RockContext() ).Get( itemKeyValue ); lActionTitle.Text = ActionTitle.Edit( ServiceJob.FriendlyTypeName ).FormatAsHtmlTitle(); } else { job = new ServiceJob { Id = 0, IsActive = true }; lActionTitle.Text = ActionTitle.Add( ServiceJob.FriendlyTypeName ).FormatAsHtmlTitle(); } hfId.Value = job.Id.ToString(); tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; ddlJobTypes.SelectedValue = job.Class; tbNotificationEmails.Text = job.NotificationEmails; ddlNotificationStatus.SetValue( (int)job.NotificationStatus ); tbCronExpression.Text = job.CronExpression; if (job.Id == 0) { job.Class = ddlJobTypes.SelectedValue; lCronExpressionDesc.Visible = false; } else { lCronExpressionDesc.Text = ExpressionDescriptor.GetDescription( job.CronExpression ); lCronExpressionDesc.Visible = true; } job.LoadAttributes(); phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls( job, phAttributes, true ); // render UI based on Authorized and IsSystem bool readOnly = false; nbEditModeMessage.Text = string.Empty; if ( !IsUserAuthorized( Authorization.EDIT ) ) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( ServiceJob.FriendlyTypeName ); } if ( job.IsSystem ) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlySystem( ServiceJob.FriendlyTypeName ); } if ( readOnly ) { lActionTitle.Text = ActionTitle.View( ServiceJob.FriendlyTypeName ).FormatAsHtmlTitle(); btnCancel.Text = "Close"; Rock.Attribute.Helper.AddDisplayControls( job, phAttributesReadOnly ); phAttributesReadOnly.Visible = true; phAttributes.Visible = false; tbCronExpression.Text = job.CronExpression; } tbName.ReadOnly = readOnly; tbDescription.ReadOnly = readOnly; cbActive.Enabled = !readOnly; ddlJobTypes.Enabled = !readOnly; tbNotificationEmails.ReadOnly = readOnly; ddlNotificationStatus.Enabled = !readOnly; tbCronExpression.ReadOnly = readOnly; btnSave.Visible = !readOnly; }
/// <summary> /// Called by the <see cref="IScheduler"/> after a <see cref="IJobDetail"/> /// has been executed, and before the associated <see cref="Quartz.Spi.IOperableTrigger"/>'s /// <see cref="Quartz.Spi.IOperableTrigger.Triggered"/> method has been called. /// </summary> /// <param name="context"></param> /// <param name="jobException"></param> public void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException) { StringBuilder message = new StringBuilder(); bool sendMessage = false; // get job type id int jobId = Convert.ToInt16(context.JobDetail.Description); // load job ServiceJobService jobService = new ServiceJobService(); ServiceJob job = jobService.Get(jobId); // format the message message.Append(String.Format("The job {0} ran for {1} seconds on {2}. Below is the results:<p>", job.Name, context.JobRunTime.TotalSeconds, context.FireTimeUtc.Value.DateTime.ToLocalTime())); // if noticiation staus is all set flag to send message if (job.NotificationStatus == JobNotificationStatus.All) { sendMessage = true; } // set last run date job.LastRunDateTime = context.FireTimeUtc.Value.DateTime.ToLocalTime(); // set run time job.LastRunDurationSeconds = Convert.ToInt32(context.JobRunTime.TotalSeconds); // set the scheduler name job.LastRunSchedulerName = context.Scheduler.SchedulerName; // determine if an error occured if (jobException == null) { job.LastSuccessfulRunDateTime = job.LastRunDateTime; job.LastStatus = "Success"; job.LastStatusMessage = ""; message.Append("Result: Success"); // determine if message should be sent if (job.NotificationStatus == JobNotificationStatus.Success) { sendMessage = true; } } else { // put the exception into the status job.LastStatus = "Exception"; job.LastStatusMessage = jobException.Message; message.Append("Result: Exception<p>Message:<br>" + jobException.Message); if (jobException.InnerException != null) { job.LastStatusMessage += " Inner Exception: " + jobException.InnerException.Message; message.Append("<p>Inner Exception:<br>" + jobException.InnerException.Message); } if (job.NotificationStatus == JobNotificationStatus.Error) { sendMessage = true; } } jobService.Save(job, null); // send notification if (sendMessage) { // TODO: implement email send once it's available } }
/// <summary> /// Handles the Click event of the btnSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> protected void btnSave_Click( object sender, EventArgs e ) { ServiceJob job; var rockContext = new RockContext(); ServiceJobService jobService = new ServiceJobService( rockContext ); int jobId = int.Parse( hfId.Value ); if ( jobId == 0 ) { job = new ServiceJob(); jobService.Add( job ); } else { job = jobService.Get( jobId ); } job.Name = tbName.Text; job.Description = tbDescription.Text; job.IsActive = cbActive.Checked; job.Class = ddlJobTypes.SelectedValue; job.NotificationEmails = tbNotificationEmails.Text; job.NotificationStatus = (JobNotificationStatus)int.Parse( ddlNotificationStatus.SelectedValue ); job.CronExpression = tbCronExpression.Text; if ( !job.IsValid ) { // Controls will render the error messages return; } rockContext.WrapTransaction( () => { rockContext.SaveChanges(); job.LoadAttributes( rockContext ); Rock.Attribute.Helper.GetEditValues( phAttributes, job ); job.SaveAttributeValues( rockContext ); } ); NavigateToParentPage(); }
/// <summary> /// Builds a Quartz schedule trigger /// </summary> /// <param name="job">The <see cref="Rock.Model.ServiceJob">Job</see> to create a <see cref="Quartz.ITrigger"/> compatible Trigger.</param> /// <returns>A Quartz trigger that implements <see cref="Quartz.ITrigger"/> for the specified job.</returns> public ITrigger BuildQuartzTrigger( ServiceJob job ) { // create quartz trigger ITrigger trigger = (ICronTrigger)TriggerBuilder.Create() .WithIdentity( job.Guid.ToString(), job.Name ) .WithCronSchedule( job.CronExpression, x => { x.InTimeZone( RockDateTime.OrgTimeZoneInfo ); x.WithMisfireHandlingInstructionDoNothing(); } ) .StartNow() .Build(); return trigger; }
/// <summary> /// Shows the detail. /// </summary> /// <param name="serviceJobId">The service job identifier.</param> public void ShowDetail(int serviceJobId) { pnlDetails.Visible = true; LoadDropDowns(); // Load depending on Add(0) or Edit ServiceJob job = null; if (!serviceJobId.Equals(0)) { job = new ServiceJobService(new RockContext()).Get(serviceJobId); lActionTitle.Text = ActionTitle.Edit(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); pdAuditDetails.SetEntity(job, ResolveRockUrl("~")); } if (job == null) { job = new ServiceJob { Id = 0, IsActive = true }; lActionTitle.Text = ActionTitle.Add(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); // hide the panel drawer that show created and last modified dates pdAuditDetails.Visible = false; } hfId.Value = job.Id.ToString(); tbName.Text = job.Name; tbDescription.Text = job.Description; cbActive.Checked = job.IsActive.HasValue ? job.IsActive.Value : false; if (job.Class.IsNotNullOrWhiteSpace()) { if (ddlJobTypes.Items.FindByValue(job.Class) == null) { nbJobTypeError.NotificationBoxType = Rock.Web.UI.Controls.NotificationBoxType.Danger; nbJobTypeError.Text = "Unable to find Job Type: " + job.Class; nbJobTypeError.Visible = true; } } ddlJobTypes.SetValue(job.Class); tbNotificationEmails.Text = job.NotificationEmails; ddlNotificationStatus.SetValue((int)job.NotificationStatus); tbCronExpression.Text = job.CronExpression; nbHistoryCount.Text = job.HistoryCount.ToString(); if (job.Id == 0) { job.Class = ddlJobTypes.SelectedValue; lCronExpressionDesc.Visible = false; lLastStatusMessage.Visible = false; } else { lCronExpressionDesc.Text = ExpressionDescriptor.GetDescription(job.CronExpression, new Options { ThrowExceptionOnParseError = false }); lCronExpressionDesc.Visible = true; lLastStatusMessage.Text = job.LastStatusMessage.ConvertCrLfToHtmlBr(); lLastStatusMessage.Visible = true; } job.LoadAttributes(); avcAttributes.AddEditControls(job); // render UI based on Authorized and IsSystem bool readOnly = false; nbEditModeMessage.Text = string.Empty; if (!IsUserAuthorized(Authorization.EDIT)) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed(ServiceJob.FriendlyTypeName); } if (job.IsSystem) { nbEditModeMessage.Text = EditModeMessage.System(ServiceJob.FriendlyTypeName); } if (readOnly) { lActionTitle.Text = ActionTitle.View(ServiceJob.FriendlyTypeName).FormatAsHtmlTitle(); btnCancel.Text = "Close"; avcAttributesReadOnly.AddDisplayControls(job); avcAttributesReadOnly.Visible = true; avcAttributes.Visible = false; tbCronExpression.Text = job.CronExpression; } tbName.ReadOnly = readOnly || job.IsSystem; tbDescription.ReadOnly = readOnly || job.IsSystem; cbActive.Enabled = !(readOnly || job.IsSystem); ddlJobTypes.Enabled = !(readOnly || job.IsSystem); tbNotificationEmails.ReadOnly = readOnly; ddlNotificationStatus.Enabled = !readOnly; tbCronExpression.ReadOnly = readOnly || job.IsSystem; btnSave.Visible = !readOnly; }