예제 #1
0
        /// <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;
        }
예제 #2
0
        /// <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);
                }
            }
        }
예제 #3
0
        /// <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;
        }
예제 #4
0
        /// <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 );
                }
            }
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        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);
        }
예제 #8
0
        /// <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();
                    }
                }
            }
        }
예제 #9
0
        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());
        }
예제 #10
0
        /// <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 _);
                }
            }
        }
예제 #11
0
        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());
        }
예제 #12
0
        /// <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();
                    }
                }
            }
        }
예제 #13
0
        /// <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();
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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());
            }
        }
예제 #17
0
        /// <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;
        }
예제 #20
0
        /// <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);
            }
        }
예제 #22
0
        /// <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;
        }
예제 #23
0
        /// <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);
        }
예제 #25
0
        /// <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();
                    }
                }
            }
        }
예제 #26
0
        /// <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;
        }
예제 #27
0
        /// <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;
        }
예제 #28
0
        /// <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;
        }
예제 #29
0
        /// <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 );
        }
예제 #30
0
        /// <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 );
            }
        }
예제 #31
0
        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();
        }
예제 #32
0
        /// <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();
        }
예제 #33
0
        /// <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;
        }
예제 #36
0
        /// <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);
        }
예제 #37
0
        /// <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;
                }
            }
        }
예제 #38
0
        /// <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;
        }
예제 #40
0
        /// <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
            }
        }
예제 #41
0
        /// <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;
        }