private async Task <SessionRunResult <TIdentifier> > RunDueTasks(ImmutableList <ITaskDefinition <TIdentifier> > candidateTasks, ImmutableList <ISchedule <TIdentifier> > schedules, Guid runId)
        {
            using (runner)
            {
                using (var preconditionEvaluator = new PreconditionEvaluator <TIdentifier>(taskRunnerLogger))
                {
                    var taskDefinitionStates = await taskDefinitionStateReader.GetByTaskDefinitionIds(candidateTasks.Select(a => a.Id).ToImmutableList());

                    var sessionRunResult = new SessionRunResult <TIdentifier>();
                    var preconditions    = await preconditionReader.GetByTaskNameAsync(candidateTasks.Select(a => a.Name).ToImmutableList());

                    var inBuiltPreconditions = inbuiltTaskPreconditionsProvider.GetInBuiltPreconditions(candidateTasks, taskDefinitionStates);
                    preconditions = preconditions.AddRange(inBuiltPreconditions);
                    preconditions = preconditions.GroupBy(a => new { t = a.GetType(), n = a.TaskName })
                                    .Select(a => a.First())
                                    .ToImmutableList();
                    foreach (var singleTaskDefinition in candidateTasks)
                    {
                        var startTime = DateTime.Now;
                        await RunSingleTask(singleTaskDefinition, preconditionEvaluator, schedules, preconditions, sessionRunResult, startTime, runId);
                    }

                    await historyWriter.WriteAsync(sessionRunResult.Histories);

                    await scheduleWriter.WriteAsync(sessionRunResult.Schedules);

                    return(sessionRunResult);
                }
            }
        }
        public virtual Task OnRunCompletedAsync(bool succeeded, SessionRunResult <TIdentifier> sessionRunResult, Exception exception)
        {
            _ = succeeded;
            _ = sessionRunResult;
            _ = exception;
            if (succeeded)
            {
                taskRunnerLogger.LogInformation($"Run completed without exception.");
            }
            else
            {
                taskRunnerLogger.LogError($"Error(s) occured during run");
            }

            return(Task.CompletedTask);
        }
        private async Task RunSingleTask(ITaskDefinition <TIdentifier> singleTaskDefinition, PreconditionEvaluator <TIdentifier> preconditionEvaluator, ImmutableList <ISchedule <TIdentifier> > schedules, ImmutableList <TaskPrecondition <TIdentifier> > preconditions, SessionRunResult <TIdentifier> sessionRunResult, DateTime startTime, Guid runId)
        {
            var taskSchedule = schedules.Single(candidateSchedule => EqualityComparer <TIdentifier> .Default.Equals(candidateSchedule.TaskDefinitionId, singleTaskDefinition.Id));
            var history      = historyReader.GetNew();

            history.StartTime        = startTime;
            history.TaskDefinitionId = singleTaskDefinition.Id;
            history.RunId            = runId;
            var runResult = default(SingleTaskRunResult);

            var failingPrecondition = await preconditionEvaluator.GetFailingPrecondition(singleTaskDefinition, preconditions);

            var allPreconditionsPassed = string.IsNullOrEmpty(failingPrecondition);

            if (allPreconditionsPassed)
            {
                try
                {
                    runResult = await runner.RunAsync(singleTaskDefinition);
                }
                catch (Exception e)
                {
                    await faultHandler.HandleAsync(singleTaskDefinition, e);

                    runResult = new SingleTaskRunResult
                    {
                        Succeeded = false,
                        Remarks   = e.Message,
                    };
                }
                finally
                {
                    if (taskSchedule.IsOnDemand)
                    {
                        onDemandQueueManager.DeQueue(taskSchedule.TaskDefinitionId);
                    }
                }
                history.Remarks = runResult.Remarks;
                history.Status  = runResult.Succeeded ? RunHistoryStatuses.CompletedSuccessfully : RunHistoryStatuses.Failed;
            }
            else
            {
                history.Remarks = $"Precondition '{failingPrecondition}' failed";
                history.Status  = RunHistoryStatuses.PreconditionPreventedRun;
            }
            history.EndTime = taskSchedule.LastRun = DateTime.Now;

            sessionRunResult.Histories = sessionRunResult.Histories.Add(history);
            sessionRunResult.Schedules = sessionRunResult.Schedules.Add(taskSchedule);
        }