/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public virtual void Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; var beginWindow = RockDateTime.Now.AddDays(0 - dataMap.GetInt("ExpirationPeriod")); var endWindow = RockDateTime.Now.AddMinutes(0 - dataMap.GetInt("DelayPeriod")); var communicationQuery = new CommunicationService(new RockContext()).Queryable() .Where(c => c.Status == CommunicationStatus.Approved && c.Recipients.Any(r => r.Status == CommunicationRecipientStatus.Pending) && ( (!c.FutureSendDateTime.HasValue && c.CreatedDateTime.HasValue && c.CreatedDateTime.Value.CompareTo(beginWindow) >= 0 && c.CreatedDateTime.Value.CompareTo(endWindow) <= 0) || (c.FutureSendDateTime.HasValue && c.FutureSendDateTime.Value.CompareTo(beginWindow) >= 0 && c.FutureSendDateTime.Value.CompareTo(endWindow) <= 0) )); var pendingCount = communicationQuery.Count(); var communications = communicationQuery.ToList(); int processedCount = 0; int sendCount = 0; string currentActivityDescription = "Initializing"; try { foreach (var comm in communications) { currentActivityDescription = string.Format("Sending Communication '{0}' [Id={1}]", comm.ToString(), comm.Id); var medium = comm.Medium; if (medium != null) { medium.Send(comm); sendCount++; } processedCount++; } pendingCount = pendingCount - processedCount; string resultDescription = string.Format("Send Communication processing completed.\n[{0} processed, {1} sent, {2} pending].", processedCount, sendCount, pendingCount); // Set the Job result summary. context.Result = RockJobResult.NewSuccessResult(resultDescription); } catch (Exception ex) { throw new Exception(string.Format("Job Execution failed at Processing Task \"{0}\".", currentActivityDescription), ex); } }
public virtual void Execute(IJobExecutionContext context) { // Check that we have at least one active Location Service. bool hasActiveServices = Rock.Address.VerificationContainer.Instance.Components.Any(x => x.Value.Value.IsActive); if (!hasActiveServices) { context.Result = RockJobResult.NewWarningResult("Address Verification canceled. There are no Active Location Services available to process the request."); return; } // Get the Job configuration settings. JobDataMap dataMap = context.JobDetail.JobDataMap; int maxRecords = Int32.Parse(dataMap.GetString("MaxRecordsPerRun")); int throttlePeriod = Int32.Parse(dataMap.GetString("ThrottlePeriod")); int retryPeriod = Int32.Parse(dataMap.GetString("RetryPeriod")); DateTime retryDate = DateTime.Now.Subtract(new TimeSpan(retryPeriod, 0, 0, 0)); using (var rockContext = new RockContext()) { var locationService = new LocationService(rockContext); // Get a set of Locations to process that: // 1. Are Active, Not Locked, and Not a Geofence. // 2. Have Not been previously geocoded or standardized, or are due for a retry. // 3. Are in order of modification date, so that the most recently updated addresses are given priority. var locationQuery = locationService.Queryable() .Where(l => ( (l.IsGeoPointLocked == null || l.IsGeoPointLocked == false) && l.IsActive && l.GeoFence == null && (l.GeocodedDateTime == null && (l.GeocodeAttemptedDateTime == null || l.GeocodeAttemptedDateTime < retryDate)) && (l.StandardizedDateTime == null && (l.StandardizeAttemptedDateTime == null || l.StandardizeAttemptedDateTime < retryDate)) )) .OrderByDescending(x => x.ModifiedDateTime); var pendingCount = locationQuery.Count(); var addresses = locationQuery.Take(maxRecords).ToList(); int processedCount = 0; int verifiedCount = 0; string currentActivityDescription = "Initializing"; try { foreach (var address in addresses) { currentActivityDescription = string.Format("Verifying Location '{0}' [Id={1}]", address, address.Id); DateTime?lastGeocoded = address.GeocodedDateTime; DateTime?lastStandardized = address.StandardizedDateTime; locationService.Verify(address, false); // currently not reverifying rockContext.SaveChanges(); if ((address.GeocodedDateTime.HasValue && address.GeocodedDateTime.Value.Subtract(lastGeocoded.GetValueOrDefault(DateTime.MinValue)).TotalSeconds > 0) || (address.StandardizedDateTime.HasValue && address.StandardizedDateTime.Value.Subtract(lastStandardized.GetValueOrDefault(DateTime.MinValue)).TotalSeconds > 0)) { verifiedCount++; } processedCount++; Thread.Sleep(throttlePeriod); } string resultDescription = string.Format("Job completed.\n[{0} processed, {1} verified, {2} failed, {3} pending].", processedCount, verifiedCount, processedCount - verifiedCount, pendingCount - processedCount); // Set the Job result summary. context.Result = RockJobResult.NewSuccessResult(resultDescription); } catch (Exception ex) { throw new Exception(string.Format("Job failed at Processing Task \"{0}\".", currentActivityDescription), ex); } } }
/// <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); }