feat: add batch action execution response tracking

- Introduce BatchRecActionViewResponse to track execution metrics
- Add SuccessCount and FailureCount properties to monitor execution results
- Change InvokeBatchRecActionViewsCommand to return response data
- Update RecActionController to return Ok with response instead of Accepted
- Improve error handling to distinguish RecActionException from unexpected errors
- Consolidate exception handling logic for ErrorAction.Continue scenarios
This commit is contained in:
2026-08-03 17:11:25 +02:00
parent 003f4c60f6
commit 8e0ee6fbfa
2 changed files with 26 additions and 19 deletions

View File

@@ -21,12 +21,11 @@ public class RecActionController(IMediator mediator) : ControllerBase
[ProducesResponseType(StatusCodes.Status202Accepted)]
public async Task<IActionResult> Invoke([FromRoute] long profileId, [FromBody] InvokeReferences references, CancellationToken cancel = default)
{
await mediator.Send(new InvokeBatchRecActionViewsCommand
return Ok(await mediator.Send(new InvokeBatchRecActionViewsCommand
{
ProfileId = profileId,
References = references
}, cancel);
return Accepted();
}, cancel));
}
#region CRUD

View File

@@ -6,16 +6,26 @@ using ReC.Domain.Constants;
namespace ReC.Application.RecActions.Commands;
public record InvokeBatchRecActionViewsCommand : IRequest
public record InvokeBatchRecActionViewsCommand : IRequest<BatchRecActionViewResponse>
{
public long ProfileId { get; init; }
public required InvokeReferences References { get; init; }
}
public class InvokeRecActionViewsCommandHandler(ISender sender, ILogger<InvokeRecActionViewsCommandHandler>? logger = null) : IRequestHandler<InvokeBatchRecActionViewsCommand>
public record BatchRecActionViewResponse
{
public async Task Handle(InvokeBatchRecActionViewsCommand request, CancellationToken cancel)
public int TotalActionCount => SuccessCount + FailureCount;
public int SuccessCount { get; internal set; } = 0;
public int FailureCount { get; internal set; } = 0;
}
public class InvokeRecActionViewsCommandHandler(ISender sender, ILogger<InvokeRecActionViewsCommandHandler>? logger = null) : IRequestHandler<InvokeBatchRecActionViewsCommand, BatchRecActionViewResponse>
{
public async Task<BatchRecActionViewResponse> Handle(InvokeBatchRecActionViewsCommand request, CancellationToken cancel)
{
var res = new BatchRecActionViewResponse();
var actions = await sender.Send(new ReadRecActionViewQuery() { ProfileId = request.ProfileId }, cancel);
foreach (var action in actions)
@@ -27,31 +37,29 @@ public class InvokeRecActionViewsCommandHandler(ISender sender, ILogger<InvokeRe
Action = action,
References = request.References
}, cancel);
}
catch (RecActionException ex)
{
switch (action.ErrorAction)
{
case ErrorAction.Continue:
logger?.LogWarning(ex, "Rec action failed but continuing. ActionId: {ActionId}, ProfileId: {ProfileId}", ex.ActionId, ex.ProfileId);
break;
default:
// Rethrow the exception to stop processing further actions
throw;
}
res.SuccessCount += 1;
}
catch (Exception ex)
{
switch (action.ErrorAction)
{
case ErrorAction.Continue:
if (ex is RecActionException recEx)
logger?.LogWarning(ex, "Rec action failed but continuing. ActionId: {ActionId}, ProfileId: {ProfileId}", recEx.ActionId, recEx.ProfileId);
else
logger?.LogError(ex, "Unexpected error during rec action. ActionId: {ActionId}, ProfileId: {ProfileId}", action.Id, action.ProfileId);
break;
default:
// Rethrow the exception to stop processing further actions
throw;
}
res.FailureCount += 1;
}
}
return res;
}
}