From 3cf2b4d47e9f35d348a1ee6ae56d807726c30edc Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 21 May 2026 04:43:48 -0400 Subject: [PATCH] fix(sitecallaudit): correct stale relay docs and clarify ack switch --- src/ScadaLink.Host/Actors/AkkaHostedService.cs | 8 +++++--- src/ScadaLink.SiteCallAudit/SiteCallAuditActor.cs | 14 ++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/ScadaLink.Host/Actors/AkkaHostedService.cs b/src/ScadaLink.Host/Actors/AkkaHostedService.cs index 90dda17..85934b4 100644 --- a/src/ScadaLink.Host/Actors/AkkaHostedService.cs +++ b/src/ScadaLink.Host/Actors/AkkaHostedService.cs @@ -415,9 +415,11 @@ akka {{ // and NotificationOutbox patterns. M3's dual-write transaction routes // SiteCalls upserts through AuditLogIngestActor's own scope-per-message // ISiteCallAuditRepository resolution, so this singleton is not on the - // M3 happy-path hot path; it exists so future direct-write callers - // (reconciliation puller, central→site Retry/Discard relay, KPI - // projector) Ask through a stable cluster proxy without further wiring. + // M3 happy-path hot path; it exists so direct-write callers Ask through + // a stable cluster proxy without further wiring. The central→site + // Retry/Discard relay now lives in this actor (see the + // RegisterCentralCommunication wiring below); the reconciliation puller + // is the remaining deferred direct-write caller. // Like AuditLogIngestActor, the actor takes the root IServiceProvider // and creates a fresh scope per message because ISiteCallAuditRepository // is a scoped EF Core service. diff --git a/src/ScadaLink.SiteCallAudit/SiteCallAuditActor.cs b/src/ScadaLink.SiteCallAudit/SiteCallAuditActor.cs index e338b05..8078060 100644 --- a/src/ScadaLink.SiteCallAudit/SiteCallAuditActor.cs +++ b/src/ScadaLink.SiteCallAudit/SiteCallAuditActor.cs @@ -23,9 +23,10 @@ namespace ScadaLink.SiteCallAudit; /// /// /// -/// Query, detail and KPIs land in Task 4; reconciliation and the central→site -/// Retry/Discard relay remain deferred (per CLAUDE.md scope discipline — they -/// land in a later follow-up). +/// Query, detail and KPIs (Task 4) and the central→site Retry/Discard relay +/// (Task 5 — the relay handlers live in this actor) are implemented; only +/// reconciliation remains deferred (per CLAUDE.md scope discipline — it lands +/// in a later follow-up). /// /// /// Per CLAUDE.md "audit-write failure NEVER aborts the user-facing action" — @@ -550,7 +551,12 @@ public class SiteCallAuditActor : ReceiveActor SiteCallRelayOutcome.NotParked => "The operation is no longer parked at the site (already delivered, discarded, or retrying).", SiteCallRelayOutcome.OperationFailed => ack.ErrorMessage, - _ => ack.ErrorMessage, + // SiteUnreachable is never produced from a ParkedOperationActionAck — + // unreachable responses are built by UnreachableRetry/UnreachableDiscard + // before any ack is classified, so this arm is unreachable by construction. + SiteCallRelayOutcome.SiteUnreachable => ack.ErrorMessage, + _ => throw new ArgumentOutOfRangeException( + nameof(outcome), outcome, "unknown SiteCallRelayOutcome"), }; }