feat(notif): NotificationDetailRequest query for full notification detail
This commit is contained in:
@@ -76,6 +76,49 @@ public record DiscardNotificationResponse(
|
||||
bool Success,
|
||||
string? ErrorMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: request for the full detail of a single notification
|
||||
/// (including Body and resolved recipients), for the report detail modal.
|
||||
/// </summary>
|
||||
public record NotificationDetailRequest(
|
||||
string CorrelationId,
|
||||
string NotificationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Outbox UI: full detail for one notification. On a repository fault or
|
||||
/// missing row, Success is false / Detail is null and ErrorMessage carries the cause.
|
||||
/// </summary>
|
||||
public record NotificationDetailResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
NotificationDetail? Detail);
|
||||
|
||||
/// <summary>
|
||||
/// Full notification detail for the report detail modal — everything in the grid's
|
||||
/// NotificationSummary plus Body, ResolvedTargets (recipients), TypeData, SourceScript,
|
||||
/// and the additional lifecycle timestamps.
|
||||
/// </summary>
|
||||
public record NotificationDetail(
|
||||
string NotificationId,
|
||||
string Type,
|
||||
string ListName,
|
||||
string Subject,
|
||||
string Body,
|
||||
string Status,
|
||||
int RetryCount,
|
||||
string? LastError,
|
||||
string? ResolvedTargets,
|
||||
string? TypeData,
|
||||
string SourceSiteId,
|
||||
string? SourceInstanceId,
|
||||
string? SourceScript,
|
||||
DateTimeOffset SiteEnqueuedAt,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset? LastAttemptAt,
|
||||
DateTimeOffset? NextAttemptAt,
|
||||
DateTimeOffset? DeliveredAt);
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: request for the notification outbox KPI summary.
|
||||
/// </summary>
|
||||
|
||||
@@ -275,6 +275,13 @@ public class CommunicationService
|
||||
request, _options.QueryTimeout, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<NotificationDetailResponse> GetNotificationDetailAsync(
|
||||
NotificationDetailRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await GetNotificationOutbox().Ask<NotificationDetailResponse>(
|
||||
request, _options.QueryTimeout, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<NotificationKpiResponse> GetNotificationKpisAsync(
|
||||
NotificationKpiRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user