feat(notif): NotificationDetailRequest query for full notification detail

This commit is contained in:
Joseph Doherty
2026-05-21 02:47:43 -04:00
parent 8fd0cf355b
commit 194cae2fbf
4 changed files with 155 additions and 0 deletions

View File

@@ -66,6 +66,7 @@ public class NotificationOutboxActor : ReceiveActor, IWithTimers
Receive<InternalMessages.PurgeComplete>(_ => { });
Receive<NotificationOutboxQueryRequest>(HandleQuery);
Receive<NotificationStatusQuery>(HandleStatusQuery);
Receive<NotificationDetailRequest>(HandleDetailRequest);
Receive<RetryNotificationRequest>(HandleRetry);
Receive<DiscardNotificationRequest>(HandleDiscard);
Receive<NotificationKpiRequest>(HandleKpiRequest);
@@ -674,6 +675,59 @@ public class NotificationOutboxActor : ReceiveActor, IWithTimers
DeliveredAt: notification.DeliveredAt);
}
/// <summary>
/// Handles a full-detail query for a single notification — backs the report detail
/// modal, which needs the Body and resolved recipients that the grid summary omits.
/// </summary>
private void HandleDetailRequest(NotificationDetailRequest request)
{
var sender = Sender;
DetailAsync(request).PipeTo(
sender,
success: response => response,
failure: ex => new NotificationDetailResponse(
request.CorrelationId, Success: false,
ErrorMessage: ex.GetBaseException().Message, Detail: null));
}
private async Task<NotificationDetailResponse> DetailAsync(NotificationDetailRequest request)
{
using var scope = _serviceProvider.CreateScope();
var repository = scope.ServiceProvider.GetRequiredService<INotificationOutboxRepository>();
var notification = await repository.GetByIdAsync(request.NotificationId);
if (notification is null)
{
return new NotificationDetailResponse(
request.CorrelationId, Success: false,
ErrorMessage: "notification not found", Detail: null);
}
var detail = new NotificationDetail(
notification.NotificationId,
notification.Type.ToString(),
notification.ListName,
notification.Subject,
notification.Body,
notification.Status.ToString(),
notification.RetryCount,
notification.LastError,
notification.ResolvedTargets,
notification.TypeData,
notification.SourceSiteId,
notification.SourceInstanceId,
notification.SourceScript,
notification.SiteEnqueuedAt,
notification.CreatedAt,
notification.LastAttemptAt,
notification.NextAttemptAt,
notification.DeliveredAt);
return new NotificationDetailResponse(
request.CorrelationId, Success: true, ErrorMessage: null, detail);
}
/// <summary>
/// Handles a manual retry request. Only a <c>Parked</c> notification can be retried;
/// it is reset to <c>Pending</c> with a cleared retry count, next-attempt time, and