/// <summary> /// This method is called when the job is triggered to execute. /// </summary> /// <param name="jobContext"></param> public void Execute(IJobExecutionContext jobContext) { // Initialize and set context var dataMap = jobContext.MergedJobDataMap; var applicationContext = (MansionContext) dataMap["applicationContext"]; var jobNode = (Node) dataMap["jobNode"]; var typeService = applicationContext.Nucleus.ResolveSingle<ITypeService>(); var type = typeService.Load(applicationContext, jobNode.Type); // get all tasks _queuedTaskDescriptors = type.GetDescriptors<RegisterTaskDescriptor>() .Select(descriptor => descriptor).ToList(); // Save the current time as the last run of the current Job var context = new MansionContext(applicationContext.Nucleus); using (RepositoryUtil.Open(context)) { var repository = context.Repository; repository.UpdateNode(context, jobNode, new PropertyBag { {"lastRun", DateTime.Now} }); } // Start tasks that have no dependency on other tasks foreach (var taskDescriptor in _queuedTaskDescriptors .Select(descriptor => descriptor) .Where(descriptor => descriptor.TaskWaitsFor.IsNullOrWhiteSpace())) { var descriptor = taskDescriptor; System.Threading.Tasks.Task.Factory.StartNew(() => ExecuteTask(applicationContext, descriptor, jobNode)); } }
/// <summary> /// Start the given task /// </summary> /// <param name="applicationContext"></param> /// <param name="taskDescriptor"></param> /// <param name="jobNode"></param> private void ExecuteTask(IMansionContext applicationContext, RegisterTaskDescriptor taskDescriptor, Node jobNode) { // Initialize and set context var mailReportWhenFailed = jobNode.Get(applicationContext, "mailReportWhenFailed", false); var context = new MansionContext(applicationContext.Nucleus); var editProperties = new PropertyBag(); var taskOutput = new StringBuilder(); var taskType = taskDescriptor.TaskType; var task = (Task) Activator.CreateInstance(taskType); bool ranSuccessfully = false; using (RepositoryUtil.Open(context)) { var taskStopwatch = new Stopwatch(); try { // Execute the asynchronous task taskStopwatch.Start(); var theActualTask = Task<bool>.Factory.StartNew(() => task.DoExecute(context, jobNode, ref taskOutput)); System.Threading.Tasks.Task.Factory.ContinueWhenAll(new[] {theActualTask}, tasks => taskStopwatch.Stop()); ranSuccessfully = theActualTask.Result; editProperties.Add(taskType.Name + ".exceptionThrown", false); if (!ranSuccessfully) { if (mailReportWhenFailed) SendErrorReportEmail(applicationContext, jobNode, taskType, task, taskOutput); } } catch (Exception e) { // Catch any exception that is thrown by the task and save it on the job node ranSuccessfully = false; editProperties.Add(taskType.Name + ".exceptionThrown", true); editProperties.Add(taskType.Name + ".exceptionMessage", e.InnerException.Message); if (mailReportWhenFailed) SendErrorReportEmail(applicationContext, jobNode, taskType, task, taskOutput, e.InnerException); } finally { // Update job node with task results editProperties.Add(taskType.Name + ".lastRunSuccessfull", ranSuccessfully); editProperties.Add(taskType.Name + ".lastRun", DateTime.Now); editProperties.Add(taskType.Name + ".lastDuration", taskStopwatch.Elapsed); editProperties.Add(taskType.Name + ".taskOutput", taskOutput); editProperties.Add("_scheduleStatusUpdate", taskOutput); lock (_jobLock) { var repository = context.Repository; repository.UpdateNode(context, jobNode, editProperties); } if (ranSuccessfully) { // Find out what tasks can be started next lock (_queueLock) { _queuedTaskDescriptors.Remove(taskDescriptor); _finishedTaskDescriptors.Add(taskDescriptor); // Only loop those tasks that have a dependency on the current task foreach (var descriptor in _queuedTaskDescriptors .Where(descriptor => !descriptor.TaskWaitsFor.IsNullOrWhiteSpace()) .Where(descriptor => descriptor.TaskWaitsFor.Split(',') .Contains(taskDescriptor.TaskId.ToString(CultureInfo.InvariantCulture)))) { var waitsFor = descriptor.TaskWaitsFor.Split(','); // Check if all other dependencies of the queued task are finished var allDependenciesFinished = waitsFor.All(waitFor => _finishedTaskDescriptors .Select(finishedDescriptor => finishedDescriptor) .Count(finishedDescriptor => finishedDescriptor.TaskId.ToString(CultureInfo.InvariantCulture).Equals(waitFor)) != 0); if (allDependenciesFinished) System.Threading.Tasks.Task.Factory.StartNew(() => ExecuteTask(applicationContext, descriptor, jobNode)); } } } } } }