Backend/e-suite.Service.WorkflowProcessor/WorkflowProcessor.cs

107 lines
4.1 KiB
C#

using e_suite.API.Common.repository;
using e_suite.Database.Audit;
using e_suite.Database.Core.Tables.Activity;
using e_suite.Workflow.Core;
using e_suite.Workflow.Core.Interfaces;
using eSuite.Core.Clock;
using eSuite.Core.Enums;
using eSuite.Core.Miscellaneous;
using Microsoft.Extensions.Logging;
namespace e_suite.Service.WorkflowProcessor;
public class WorkflowProcessor : IWorkflowProcessor
{
private readonly ILogger _logger;
private readonly IClock _clock;
private readonly IWorkflowTemplateRepository _workflowTemplateRepository;
private readonly IWorkflowConverter _workflowConverter;
private readonly IActivityRepository _activityRepository;
public WorkflowProcessor(ILogger logger, IClock clock, IWorkflowTemplateRepository workflowTemplateRepository, IActivityRepository activityRepository, IWorkflowConverter workflowConverter)
{
_logger = logger;
_clock = clock;
_workflowTemplateRepository = workflowTemplateRepository;
_activityRepository = activityRepository;
_workflowConverter = workflowConverter;
}
public async Task ProgressActivity(
AuditUserDetails auditUserDetails,
GeneralIdRef activityId,
CancellationToken cancellationToken
)
{
_logger.LogInformation("{DateTime}: Progressing Activity {messageId}", _clock.GetNow, activityId);
var activityInstance = await _activityRepository.GetActivityInstanceAsync(activityId, cancellationToken);
if (activityInstance == null)
{
_logger.LogInformation("{DateTime}: Unable to find activity {messageId}", _clock.GetNow, activityId);
throw new InvalidDataException("activityInstance not found");
}
if (activityInstance.ActivityState == ActivityState.Cancelled)
{
_logger.LogInformation("{DateTime}: Activity {messageId} is cancelled, skipping", _clock.GetNow,
activityId);
return;
}
if (activityInstance.ActivityState == ActivityState.Completed)
{
_logger.LogInformation("{DateTime}: Activity {messageId} is already completed, skipping", _clock.GetNow,
activityId);
return;
}
var workflowVersion = _workflowConverter.DeserialiseFromDatabase(activityInstance.WorkflowVersion);
await _activityRepository.TransactionAsync(async () =>
{
ICollection<ActivityTask> tasks;
if (activityInstance.ActivityState == ActivityState.Pending)
{
activityInstance.ActivityState = ActivityState.Active;
await _activityRepository.UpdateActivityInstanceAsync(auditUserDetails, activityInstance,
cancellationToken);
tasks = await PlanTaskExecution(auditUserDetails, activityInstance, workflowVersion, cancellationToken);
}
else
{
tasks = activityInstance.Tasks;
}
//Invoke startable tasks.
});
}
private async Task<ICollection<ActivityTask>> PlanTaskExecution(AuditUserDetails auditUserDetails, Activity activityInstance, WorkflowVersion workflowVersion, CancellationToken cancellationToken)
{
var activityOrdinalCounter = 1;
//Create task instances for the activity
var activityTasks = new List<ActivityTask>();
foreach (var task in workflowVersion.Tasks)
{
var activityTask = new ActivityTask
{
Guid = Guid.NewGuid(),
Activity = activityInstance,
ActivityState = ActivityState.Pending,
TaskGuid = task.Guid,
ActivityOrdinal = activityOrdinalCounter++,
TaskName = task.Name,
};
activityTasks.Add(activityTask);
}
await _activityRepository.AddActivityTasksAsync(auditUserDetails, activityTasks, cancellationToken);
return activityTasks;
}
}