Skip to content

Commit ad7c23d

Browse files
codureMichel Roosgoomens
authored
Fix/dn 3864 parallel step conditions (#191)
* DN-3864 Updated StepVersionService for parallel child steps * DN-3864 Made step versions be based on previous event history * DN-3864 Unit tests for step versions based on event history * DN-3864 Added icon to Assessment step for RMSS * DN-3864 Added Condition 'isMet' overload for event ids * DN-3864 WorkflowInstanceService refactor for history - Added WorkflowInstanceHistory which fetches the instance journal and eventLogs. - Updated StepVersion flow to use journal and eventLogs. - Added more Unit Tests for StepVersion cases. * DN-3864 Cleaned up WorkflowInstanceService * DN-3864 Removed unused GetEventLogEntriesForInstanceUntil function * DN-3864 Updated silent return to NotSupportedException. * DN-3864 fix: unit tests * DN-3864 Refactored the StepVersionService to Single or Multi event versioning * DN-3864 Moved the step version 'skip' and 'sort' to Controller and Dto * DN-3864 Removed deprecated GetStepVersions * DN-3864 Fixed some unit tests after merging --------- Co-authored-by: Michel Roos <m.roos3@uva.nl> Co-authored-by: Gerrit Oomens <g.oomens@uva.nl>
1 parent 76f6f2a commit ad7c23d

23 files changed

Lines changed: 950 additions & 518 deletions

UvA.Workflow.Api/Steps/StepsController.cs

Lines changed: 0 additions & 43 deletions
This file was deleted.

UvA.Workflow.Api/WorkflowInstances/Dtos/WorkflowInstanceDtoFactory.cs

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using UvA.Workflow.Api.Submissions.Dtos;
22
using UvA.Workflow.Api.Users.Dtos;
33
using UvA.Workflow.Api.WorkflowDefinitions.Dtos;
4+
using UvA.Workflow.Events;
45
using UvA.Workflow.Submissions;
56
using UvA.Workflow.Versioning;
67
using UvA.Workflow.WorkflowModel;
@@ -26,8 +27,6 @@ public async Task<WorkflowInstanceDto> Create(WorkflowInstance instance, Cancell
2627
{
2728
var actions = await instanceService.GetAllowedActions(instance, ct);
2829
var submissions = await instanceService.GetAllowedSubmissions(instance, ct);
29-
var allowedForms = (await rightsService.GetAllowedActions(instance, RoleAction.View))
30-
.SelectMany(a => a.AllForms).ToArray();
3130
var workflowDefinition = modelService.WorkflowDefinitions[instance.WorkflowDefinition];
3231
var permissions = await rightsService.GetAllowedActions(instance, RoleAction.ViewAdminTools, RoleAction.Edit);
3332
// Both admin-tool and impersonation visibility are evaluated against the real user (ignoring any
@@ -50,7 +49,11 @@ await instanceService.Enrich(workflowDefinition, [context],
5049
workflowDefinition.Steps.SelectMany(f => f.Lookups).Concat(relatedUserLookups).Concat(resourceLookups), ct);
5150

5251
// Fetch versions for all steps
53-
var stepVersionsMap = await GetStepVersionsMap(instance, workflowDefinition.AllSteps, ct);
52+
var instanceHistory = await workflowInstanceService.GetInstanceHistory(instance.Id, ct);
53+
var stepVersionsMap = GetStepVersionsMap(instance, workflowDefinition.AllSteps, instanceHistory.EventLogs);
54+
var steps = await Task.WhenAll(workflowDefinition.Steps
55+
.Where(s => s.Condition.IsMet(context))
56+
.Select(s => CreateStepDto(s, instance, stepVersionsMap, instanceHistory, context, ct)));
5457

5558
var editActions = permissions.Where(a => a.Type == RoleAction.Edit).ToArray();
5659
var canEditByProperty = rightsService.CanEditProperties(
@@ -72,10 +75,7 @@ await instanceService.Enrich(workflowDefinition, [context],
7275
instance.ParentId,
7376
actions.Select(ActionDto.Create).ToArray(),
7477
CreateFields(workflowDefinition, instance.Id, ct).Result ?? [],
75-
workflowDefinition.Steps
76-
.Where(s => s.Condition.IsMet(context))
77-
.Select(s => CreateStepDto(s, instance, stepVersionsMap, context, allowedForms))
78-
.ToArray(),
78+
steps,
7979
submissions
8080
.Select(s => submissionDtoFactory.Create(instance, s.Form, s.SubmissionState, s.QuestionStatus,
8181
permissions.Where(p => p.MatchesForm(s.Form.Name)).Select(p => p.Type).ToArray()))
@@ -115,20 +115,21 @@ await instanceService.Enrich(workflowDefinition, [context],
115115
}
116116

117117
/// <summary>
118-
/// Fetches versions for all steps and returns a dictionary keyed by step name
118+
/// Creates versions for all steps from a preloaded instance-wide event log.
119119
/// </summary>
120-
private async Task<Dictionary<string, List<StepVersion>>> GetStepVersionsMap(
120+
private Dictionary<string, List<StepVersion>> GetStepVersionsMap(
121121
WorkflowInstance instance,
122122
IEnumerable<Step> steps,
123-
CancellationToken ct)
123+
IEnumerable<InstanceEventLogEntry> eventLogs)
124124
{
125+
var eventLogList = eventLogs.ToList();
125126
var stepVersionsMap = new Dictionary<string, List<StepVersion>>();
126127

127128
foreach (var step in steps)
128129
{
129130
try
130131
{
131-
var versions = await stepVersionService.GetStepVersions(instance, step.Name, ct);
132+
var versions = stepVersionService.GetStepVersions(instance, step, eventLogList);
132133
if (versions.Any())
133134
{
134135
stepVersionsMap[step.Name] = versions;
@@ -147,15 +148,31 @@ private async Task<Dictionary<string, List<StepVersion>>> GetStepVersionsMap(
147148
/// <summary>
148149
/// Creates a StepDto with versions from the map, recursively handling child steps
149150
/// </summary>
150-
private StepDto CreateStepDto(
151+
private async Task<StepDto> CreateStepDto(
151152
Step step,
152153
WorkflowInstance instance,
153154
Dictionary<string, List<StepVersion>> stepVersionsMap,
155+
WorkflowInstanceHistory instanceHistory,
154156
ObjectContext context,
155-
string[] allowedForms)
157+
CancellationToken ct)
156158
{
157159
var workflowDef = modelService.WorkflowDefinitions[instance.WorkflowDefinition];
158-
var versions = stepVersionsMap.GetValueOrDefault(step.Name);
160+
161+
// The newest version is the step's live state, already rendered as the current submission.
162+
var versions = stepVersionsMap.GetValueOrDefault(step.Name)
163+
?.OrderByDescending(version => version.SubmittedAt)
164+
.Skip(step.HasEnded(context) ? 1 : 0);
165+
166+
var children = step.Children.Length != 0
167+
? await Task.WhenAll(step.Children
168+
.Where(s => s.Condition.IsMet(context))
169+
.Select(s => CreateStepDto(s, instance, stepVersionsMap, instanceHistory, context, ct)))
170+
: null;
171+
var versionDtos = versions != null
172+
? await Task.WhenAll(versions
173+
.OrderByDescending(version => version.SubmittedAt)
174+
.Select(version => CreateStepVersionDto(version, instance, instanceHistory, ct)))
175+
: null;
159176

160177
return new StepDto(
161178
step.Name,
@@ -164,32 +181,31 @@ private StepDto CreateStepDto(
164181
step.EndEvent,
165182
step.GetEndDate(instance, workflowDef),
166183
step.GetDeadline(instance, modelService),
167-
step.Children.Length != 0
168-
? step.Children
169-
.Where(s => s.Condition.IsMet(context))
170-
.Select(s => CreateStepDto(s, instance, stepVersionsMap, context, allowedForms))
171-
.ToArray()
172-
: null,
184+
children,
173185
stepHeaderStatusResolver.Resolve(step, instance),
174186
step.ResultsType,
175187
step.HierarchyMode,
176-
versions?.Select(v => CreateStepVersionDto(v, instance, allowedForms)).ToList()
188+
versionDtos?.ToList()
177189
);
178190
}
179191

180192
/// <summary>
181193
/// Creates a StepVersionDto with properly constructed SubmissionDtos for all events in the version
182194
/// </summary>
183-
private StepVersionDto CreateStepVersionDto(StepVersion stepVersion, WorkflowInstance instance,
184-
string[] allowedForms)
195+
private async Task<StepVersionDto> CreateStepVersionDto(
196+
StepVersion stepVersion,
197+
WorkflowInstance instance,
198+
WorkflowInstanceHistory instanceHistory,
199+
CancellationToken ct)
185200
{
186201
try
187202
{
188203
var submissions = new List<SubmissionDto>();
189204

190205
// Get the instance at the version timestamp
191206
var instanceAtVersion = workflowInstanceService
192-
.GetAsOfTimestamp(instance.Id, stepVersion.SubmittedAt, CancellationToken.None).Result;
207+
.GetAsOfTimestamp(instance, stepVersion.SubmittedAt, instanceHistory);
208+
var allowedViewActions = await rightsService.GetAllowedActions(instanceAtVersion, RoleAction.View);
193209

194210
// Create a submission for each event in the version
195211
foreach (var eventId in stepVersion.EventIds)
@@ -202,7 +218,7 @@ private StepVersionDto CreateStepVersionDto(StepVersion stepVersion, WorkflowIns
202218
continue;
203219
}
204220

205-
if (!allowedForms.Contains(form.Name))
221+
if (!allowedViewActions.Any(action => action.MatchesForm(form.Name)))
206222
continue;
207223

208224
// Get question status with all fields visible (historical view)

UvA.Workflow.Persistence.Mongo/InstanceEventRepository.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,19 @@ public async Task<List<InstanceEventLogEntry>> GetEventLogEntriesForInstance(
131131
.SortBy(e => e.Timestamp)
132132
.ToListAsync(ct);
133133
}
134+
135+
/// <summary>
136+
/// Gets all event log entries for an instance.
137+
/// </summary>
138+
public async Task<List<InstanceEventLogEntry>> GetEventLogEntriesForInstance(
139+
string instanceId,
140+
CancellationToken ct)
141+
{
142+
var filter = Builders<InstanceEventLogEntry>.Filter.Eq(e => e.WorkflowInstanceId, instanceId);
143+
144+
return await _eventLogCollection
145+
.Find(filter)
146+
.SortBy(e => e.Timestamp)
147+
.ToListAsync(ct);
148+
}
134149
}

UvA.Workflow.Tests/Controllers/ActionsControllerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public ActionsControllerTests() : base()
3535
submissionDtoFactory,
3636
_workflowInstanceRepoMock.Object,
3737
_rightsService,
38-
new StepVersionService(_modelService, _eventRepoMock.Object),
38+
new StepVersionService(),
3939
new StepHeaderStatusResolver(_modelService),
4040
_workflowInstanceService,
4141
_loggerFactory.CreateLogger<WorkflowInstanceDtoFactory>());

UvA.Workflow.Tests/Controllers/AnswersControllerTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using UvA.Workflow.Api.WorkflowInstances.Dtos;
1212
using UvA.Workflow.Infrastructure;
1313
using UvA.Workflow.Organizations;
14-
using UvA.Workflow.Persistence;
1514
using UvA.Workflow.Submissions;
1615
using UvA.Workflow.Tests.Controllers.Helpers;
1716
using UvA.Workflow.Tests.Helpers;
@@ -35,7 +34,7 @@ public AnswersControllerTests() : base()
3534
{
3635
_artifactTokenService = new ArtifactTokenService(UnitTestsHelpers.TestS3Config);
3736
_workflowInstanceService = new WorkflowInstanceService(_modelService, _workflowInstanceRepoMock.Object,
38-
_instanceJournalServiceMock.Object, _userServiceMock.Object);
37+
_instanceJournalServiceMock.Object, _eventRepoMock.Object, _userServiceMock.Object);
3938
_submissionDtoFactory =
4039
new SubmissionDtoFactory(_artifactTokenService, _modelService);
4140
_workflowInstanceDtoFactory =
@@ -45,7 +44,7 @@ public AnswersControllerTests() : base()
4544
_submissionDtoFactory,
4645
_workflowInstanceRepoMock.Object,
4746
_rightsService,
48-
new StepVersionService(_modelService, _eventRepoMock.Object),
47+
new StepVersionService(),
4948
new StepHeaderStatusResolver(_modelService),
5049
_workflowInstanceService,
5150
_loggerFactory.CreateLogger<WorkflowInstanceDtoFactory>());

UvA.Workflow.Tests/Controllers/StepsControllerTests.cs

Lines changed: 0 additions & 143 deletions
This file was deleted.

0 commit comments

Comments
 (0)