private void PostRunActions(JobRunStatus runStatus)
        {
            if (runStatus.IsClose)
            {
                var finalStatus = runStatus.IsSuccess
                                        ? CustomJob.StatusReasonEnum.Success
                                        : CustomJob.StatusReasonEnum.Failure;

                Close(Service, finalStatus, Job.Id);
            }

            if (Job.DeleteOnSuccess == true &&
                runStatus.IsSuccess && runStatus.IsClose && runStatus.RunTargetFailures?.Any() != true)
            {
                log.Log("Checking target failures ...");
                var job = new CustomJob {
                    Id = Job.Id
                };
                job.LoadRelation(CustomJob.RelationNames.CustomJobFailedTargetsOfCustomJob, Service, false, 1);
                var isFailedExist = job.CustomJobFailedTargetsOfCustomJob?.Any() == true;
                log.Log($"Failed exist: {isFailedExist}.");

                if (!isFailedExist)
                {
                    log.Log("Deleting job ...", LogLevel.Debug);
                    Service.Delete(CustomJob.EntityLogicalName, Job.Id);
                    log.Log("Deleted job.");
                }
            }
        }
        private void LogRunStatus(JobRunStatus runStatus)
        {
            if (!runStatus.IsSuccess && runStatus.RunTargetFailures?.Any() == true)
            {
                runStatus.LatestRunMessage = "Failed run.\r\n\r\nFirst Exception: " +
                                             runStatus.RunTargetFailures.FirstOrDefault()?.FailureMessage;
            }
            else
            {
                runStatus.LatestRunMessage = runStatus.LatestRunMessage
                                             ?? (runStatus.IsSuccess ? "Successful run." : "Failed run.");
            }

            log.Log($"Updating latest run message: '{runStatus.LatestRunMessage}' ...", LogLevel.Debug);
            log.Log($"Updating latest date: '{Job.TargetDate ?? DateTime.UtcNow}' UTC ...", LogLevel.Debug);
            Service.Update(
                new CustomJob
            {
                Id = Job.Id,
                LatestRunMessage   = runStatus.LatestRunMessage,
                PreviousTargetDate = Job.TargetDate ?? DateTime.UtcNow
            });
            log.Log($"Updated latest run message: '{runStatus.LatestRunMessage}'.");
            log.Log($"Updated latest date: '{Job.TargetDate ?? DateTime.UtcNow}' UTC.");

            if (Job.GenerateLogs == true)
            {
                log.Log("Creating log entry ...", LogLevel.Debug);
                var logEntry =
                    new CustomJobLog
                {
                    Message              = DateTime.Now + ": " + (runStatus.IsSuccess ? "Successful run." : "Failed run."),
                    ExecutionDate        = Job.TargetDate ?? DateTime.UtcNow,
                    ExecutionFullMessage = runStatus.LatestRunMessage,
                    CustomJob            = Job.Id,
                    StatusReason         = runStatus.IsSuccess
                                                        ? CustomJobLog.StatusReasonEnum.Success
                                                        : CustomJobLog.StatusReasonEnum.Failure
                };

                if (runStatus.RunTargetFailures?.Any() == true)
                {
                    runStatus.RunTargetFailures.ForEach(failure => failure.CustomJob = null);
                    logEntry.CustomJobFailedTargetsOfLogEntry = runStatus.RunTargetFailures.ToArray();
                }

                Service.Create(logEntry);
                log.Log("Created log entry.");

                if (runStatus.ParentId.HasValue)
                {
                    logEntry.Message  += " [Sub-Job]";
                    logEntry.CustomJob = runStatus.ParentId.Value;
                    Service.Create(logEntry);
                    log.Log("Created log entry in parent.");
                }
            }
        }
        protected virtual JobRunStatus ProcessFailure(ExecutionFailures executionResult)
        {
            var status = new JobRunStatus();

            if (IsNoRetry())
            {
                if (IsSubJob())
                {
                    var parentId = Job.ParentJob.Value;

                    if (IsWaitingOnSubJobs(Service, parentId))
                    {
                        if (Job.IgnoreFailure == true)
                        {
                            log.Log($"Setting status of parent '{parentId}' to 'waiting' ...", LogLevel.Debug);
                            SetStatus(Service, CustomJob.StatusReasonEnum.Waiting, parentId, IsParentRecurrentJob());
                            log.Log($"Set status of parent '{parentId}' to 'waiting'.");
                        }
                        else
                        {
                            log.Log($"Setting status of parent '{parentId}' to 'failed' ...", LogLevel.Debug);
                            Close(Service, CustomJob.StatusReasonEnum.Failure, parentId, true);
                            log.Log($"Set status of parent '{parentId}' to 'failed'.");
                        }
                    }

                    status.ParentId = parentId;
                }

                if (Job.FailureAction != null)
                {
                    log.Log("Running failure action ...");

                    try
                    {
                        Service.Execute(
                            new ExecuteWorkflowRequest
                        {
                            EntityId   = Job.Id,
                            WorkflowId = Job.FailureAction.Value
                        });
                    }
                    catch (Exception exception)
                    {
                        log.Log(exception);
                    }

                    log.Log("Finished running failure action.");
                }

                status.IsClose = true;
            }
            else
            {
                if (Job.RetrySchedule != null)
                {
                    UpdateRetryTargetDate(Service, Job, log);
                }

                IncrementRetry(Job.CurrentRetryRun ?? 0);
                log.Log($"Setting status of job to 'retry' ...", LogLevel.Debug);
                SetStatus(Service, CustomJob.StatusReasonEnum.Retry, Job.Id, false);
                log.Log($"Set status of job to 'retry'.");
            }

            var failures = executionResult.Exceptions
                           .Select(failure =>
                                   new CustomJobFailedTarget
            {
                ID             = failure.Key.ToString(),
                FailureMessage = BuildNoTraceExceptionMessage(failure.Value)
            });

            status.IsSuccess         = false;
            status.RunTargetFailures = failures.ToList();

            return(status);
        }