Skip to content

Commit 89dfeea

Browse files
committed
Add endpoint for new analysis for inspection record
1 parent 1c999f2 commit 89dfeea

5 files changed

Lines changed: 98 additions & 3 deletions

File tree

api.Tests/Services/WorkflowServiceTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ public async Task TriggerWorkflow_ArgoReturnsError_MarksWorkflowAndRunFailed()
181181
outputBlobStorageLocation: _db.NewBlobStorageLocation()
182182
);
183183

184-
await TriggerWorkflowInScope(workflow.Id);
184+
await Assert.ThrowsAsync<WorkflowTriggerFailedException>(
185+
() => TriggerWorkflowInScope(workflow.Id)
186+
);
185187

186188
await _context.Entry(workflow).ReloadAsync(TestContext.Current.CancellationToken);
187189
await _context.Entry(run).ReloadAsync(TestContext.Current.CancellationToken);

api/Controllers/AnalysisController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public async Task<IActionResult> Delete([FromRoute] Guid id)
143143
[Authorize(Roles = Role.Any)]
144144
[Route("available")]
145145
[ProducesResponseType(StatusCodes.Status200OK)]
146-
public async Task<IActionResult> GetAvailableAnalyses()
146+
public async Task<ActionResult<List<string>>> GetAvailableAnalyses()
147147
{
148148
try
149149
{

api/Controllers/InspectionRecordController.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,4 +360,48 @@ public async Task<IActionResult> Delete([FromRoute] Guid id)
360360
return NotFound(ex.Message);
361361
}
362362
}
363+
364+
[HttpPost]
365+
[Authorize(Roles = Role.Any)]
366+
[Route("id/{id:guid}/analyses")]
367+
[ProducesResponseType(StatusCodes.Status202Accepted)]
368+
[ProducesResponseType(StatusCodes.Status400BadRequest)]
369+
[ProducesResponseType(StatusCodes.Status404NotFound)]
370+
[ProducesResponseType(StatusCodes.Status409Conflict)]
371+
[ProducesResponseType(StatusCodes.Status502BadGateway)]
372+
public async Task<IActionResult> AddAnalysis(
373+
[FromRoute] Guid id,
374+
[FromBody] AddAnalysisRequest request
375+
)
376+
{
377+
request.AnalysisName = Sanitize.SanitizeUserInput(request.AnalysisName);
378+
try
379+
{
380+
await inspectionRecordService.AddAnalysis(id, request.AnalysisName);
381+
return AcceptedAtAction(nameof(GetById), new { id }, null);
382+
}
383+
catch (KeyNotFoundException ex)
384+
{
385+
return NotFound(ex.Message);
386+
}
387+
catch (WorkflowTriggerFailedException ex)
388+
{
389+
logger.LogError(ex, "Upstream workflow trigger failed for inspection record {Id}", id);
390+
return StatusCode(StatusCodes.Status502BadGateway, ex.Message);
391+
}
392+
catch (InvalidOperationException ex)
393+
{
394+
return Conflict(ex.Message);
395+
}
396+
catch (Exception e)
397+
{
398+
logger.LogError(e, "Error adding analysis to inspection record");
399+
throw;
400+
}
401+
}
402+
}
403+
404+
public class AddAnalysisRequest
405+
{
406+
public required string AnalysisName { get; set; }
363407
}

api/Services/InspectionRecordService.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
using api.Configurations;
12
using api.Database.Context;
23
using api.Database.Models;
34
using api.MQTT;
45
using api.Utilities;
56
using Microsoft.EntityFrameworkCore;
7+
using Microsoft.Extensions.Options;
68

79
namespace api.Services;
810

@@ -30,6 +32,8 @@ int pageSize
3032
);
3133

3234
public Task Delete(Guid id);
35+
36+
public Task<InspectionRecord> AddAnalysis(Guid inspectionRecordId, string analysisName);
3337
}
3438

3539
public class InspectionRecordParameters
@@ -65,9 +69,12 @@ public class CreateInspectionRecordAnalysisGroup
6569
public class InspectionRecordService(
6670
SaraDbContext context,
6771
IAnalysisTriggerService analysisTriggerService,
72+
IOptions<AnalysisOptions> analysisOptions,
6873
ILogger<InspectionRecordService> logger
6974
) : IInspectionRecordService
7075
{
76+
private readonly AnalysisOptions _analysisOptions = analysisOptions.Value;
77+
7178
public async Task<InspectionRecord> CreateFromMqttMessage(IsarInspectionResultMessage message)
7279
{
7380
var inspectionId = Sanitize.SanitizeUserInput(message.InspectionId);
@@ -285,4 +292,31 @@ InspectionRecordParameters parameters
285292
parameters.PageSize
286293
);
287294
}
295+
296+
public async Task<InspectionRecord> AddAnalysis(Guid inspectionRecordId, string analysisName)
297+
{
298+
if (!_analysisOptions.Analyses.ContainsKey(analysisName))
299+
{
300+
throw new InvalidOperationException(
301+
$"Unknown analysis '{analysisName}'. Valid analyses are: "
302+
+ string.Join(", ", _analysisOptions.Analyses.Keys)
303+
);
304+
}
305+
306+
var record =
307+
await ReadById(inspectionRecordId)
308+
?? throw new KeyNotFoundException(
309+
$"Inspection record with id {inspectionRecordId} not found"
310+
);
311+
312+
await analysisTriggerService.OnInspectionRecordCreated(
313+
new InspectionRecordCreatedEvent
314+
{
315+
InspectionRecordId = record.Id,
316+
RequiredAnalysis = [analysisName],
317+
}
318+
);
319+
320+
return record;
321+
}
288322
}

api/Services/WorkflowService.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace api.Services;
1313

14+
public class WorkflowTriggerFailedException(string message, Exception? innerException = null)
15+
: Exception(message, innerException);
16+
1417
public interface IWorkflowService
1518
{
1619
public Task TriggerWorkflow(Guid workflowId);
@@ -168,6 +171,11 @@ public async Task TriggerWorkflow(Guid workflowId)
168171
);
169172

170173
await MarkWorkflowFailed(workflow, ex.Message);
174+
175+
throw new WorkflowTriggerFailedException(
176+
$"Failed to trigger workflow '{workflow.WorkflowType}'",
177+
ex
178+
);
171179
}
172180
}
173181

@@ -236,7 +244,14 @@ public async Task OnWorkflowCompleted(Guid workflowId)
236244
nextWorkflow.StepNumber
237245
);
238246

239-
await TriggerWorkflow(nextWorkflow.Id);
247+
try
248+
{
249+
await TriggerWorkflow(nextWorkflow.Id);
250+
}
251+
catch (WorkflowTriggerFailedException)
252+
{
253+
// Already logged and persisted inside TriggerWorkflow.
254+
}
240255
}
241256

242257
private async Task MarkWorkflowFailed(Workflow workflow, string errorMessage)

0 commit comments

Comments
 (0)