test(auditlog): pin OriginExecutionId preservation in forwarder + Parked NotifyDeliver
This commit is contained in:
@@ -212,6 +212,31 @@ public class NotificationOutboxActorTerminalEmissionTests : TestKit
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Terminal_Parked_CarriesOriginExecutionId_AsExecutionId()
|
||||||
|
{
|
||||||
|
// Audit Log #23: the Parked terminal NotifyDeliver row flows through the
|
||||||
|
// same BuildNotifyDeliverEvent path as the Delivered row, so it must
|
||||||
|
// likewise echo the notification's OriginExecutionId — sharing the
|
||||||
|
// per-run id with the site-emitted NotifySend row.
|
||||||
|
SetupSmtpRetryPolicy(maxRetries: 5, retryDelay: TimeSpan.FromMinutes(1));
|
||||||
|
var executionId = Guid.NewGuid();
|
||||||
|
var notification = MakeNotification(originExecutionId: executionId);
|
||||||
|
_outboxRepository.GetDueAsync(Arg.Any<DateTimeOffset>(), Arg.Any<int>(), Arg.Any<CancellationToken>())
|
||||||
|
.Returns(new[] { notification });
|
||||||
|
var adapter = new StubAdapter(() => DeliveryOutcome.Permanent("invalid recipient address"));
|
||||||
|
var actor = CreateActor([adapter]);
|
||||||
|
|
||||||
|
actor.Tell(InternalMessages.DispatchTick.Instance);
|
||||||
|
|
||||||
|
AwaitAssert(() =>
|
||||||
|
{
|
||||||
|
var parked = EventsByStatus(AuditStatus.Parked);
|
||||||
|
Assert.Single(parked);
|
||||||
|
Assert.Equal(executionId, parked[0].ExecutionId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Terminal_Parked_OnTransientReachingMaxRetries_EmitsEvent_StatusParked()
|
public void Terminal_Parked_OnTransientReachingMaxRetries_EmitsEvent_StatusParked()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ public class NotificationForwarderTests : TestKit
|
|||||||
private static StoreAndForwardMessage BufferedNotification(
|
private static StoreAndForwardMessage BufferedNotification(
|
||||||
string id = "msg-1", string listName = "Operators",
|
string id = "msg-1", string listName = "Operators",
|
||||||
string subject = "Pump alarm", string message = "Pump 3 tripped",
|
string subject = "Pump alarm", string message = "Pump 3 tripped",
|
||||||
string? originInstance = "Plant.Pump3", string? sourceScript = "alarmScript")
|
string? originInstance = "Plant.Pump3", string? sourceScript = "alarmScript",
|
||||||
|
Guid? originExecutionId = null)
|
||||||
{
|
{
|
||||||
var payload = JsonSerializer.Serialize(new NotificationSubmit(
|
var payload = JsonSerializer.Serialize(new NotificationSubmit(
|
||||||
NotificationId: id,
|
NotificationId: id,
|
||||||
@@ -37,7 +38,8 @@ public class NotificationForwarderTests : TestKit
|
|||||||
SourceSiteId: string.Empty,
|
SourceSiteId: string.Empty,
|
||||||
SourceInstanceId: originInstance,
|
SourceInstanceId: originInstance,
|
||||||
SourceScript: sourceScript,
|
SourceScript: sourceScript,
|
||||||
SiteEnqueuedAt: DateTimeOffset.UtcNow));
|
SiteEnqueuedAt: DateTimeOffset.UtcNow,
|
||||||
|
OriginExecutionId: originExecutionId));
|
||||||
return new StoreAndForwardMessage
|
return new StoreAndForwardMessage
|
||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
@@ -78,6 +80,33 @@ public class NotificationForwarderTests : TestKit
|
|||||||
Assert.True(await deliverTask);
|
Assert.True(await deliverTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Deliver_PreservesOriginExecutionId_FromBufferedPayload()
|
||||||
|
{
|
||||||
|
// Audit Log #23: the buffered payload's OriginExecutionId is the per-run
|
||||||
|
// id stamped at Notify.Send time. The forwarder re-stamps only the four
|
||||||
|
// fields it authoritatively owns (NotificationId, ListName, SourceSiteId,
|
||||||
|
// SourceInstanceId) via the `with` expression — OriginExecutionId is
|
||||||
|
// preserved precisely BY being absent from that `with` block. This test
|
||||||
|
// pins that: if OriginExecutionId is ever added to the `with` expression
|
||||||
|
// (e.g. reset to null), the forwarded NotificationSubmit would lose the
|
||||||
|
// per-run id and central could not echo it onto NotifyDeliver rows.
|
||||||
|
var centralProbe = CreateTestProbe();
|
||||||
|
var forwarder = new NotificationForwarder(
|
||||||
|
centralProbe.Ref, "site-7", ForwardTimeout);
|
||||||
|
|
||||||
|
var executionId = Guid.NewGuid();
|
||||||
|
var msg = BufferedNotification(id: "msg-exec", originExecutionId: executionId);
|
||||||
|
|
||||||
|
var deliverTask = forwarder.DeliverAsync(msg);
|
||||||
|
|
||||||
|
var submit = centralProbe.ExpectMsg<NotificationSubmit>();
|
||||||
|
Assert.Equal(executionId, submit.OriginExecutionId);
|
||||||
|
centralProbe.Reply(new NotificationSubmitAck(submit.NotificationId, Accepted: true, Error: null));
|
||||||
|
|
||||||
|
Assert.True(await deliverTask);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Deliver_FallsBackToTarget_WhenPayloadListNameIsEmpty()
|
public async Task Deliver_FallsBackToTarget_WhenPayloadListNameIsEmpty()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user