using ScadaLink.Communication.Grpc; namespace ScadaLink.AuditLog.Site.Telemetry; /// /// Default registered by /// . /// It is a no-op binding for composition roots that have no /// SiteCommunicationActor — central and test roots. Site roles override /// it in the Host with the ClusterClient-based /// , which actually forwards audit /// telemetry to central. /// /// /// /// Returns an empty so the /// doesn't flip any rows to /// Forwarded when this NoOp is in effect — rows stay Pending /// until a real client (or a test stub) takes over. /// /// /// Audit-write paths are best-effort by contract: a NoOp client keeps the /// host running cleanly and is consistent with "audit-write failures never /// abort the user-facing action". /// /// public sealed class NoOpSiteStreamAuditClient : ISiteStreamAuditClient { private static readonly IngestAck EmptyAck = new(); /// public Task IngestAuditEventsAsync(AuditEventBatch batch, CancellationToken ct) { ArgumentNullException.ThrowIfNull(batch); // Empty ack — no EventIds will be flipped to Forwarded, so rows stay // Pending until the real ClusterClientSiteAuditClient (or a test stub) // takes over. return Task.FromResult(EmptyAck); } /// public Task IngestCachedTelemetryAsync(CachedTelemetryBatch batch, CancellationToken ct) { ArgumentNullException.ThrowIfNull(batch); // Empty ack — same rationale as IngestAuditEventsAsync. The site still // writes the audit + tracking rows to its SQLite stores authoritatively; // central-side state only materialises once the real // ClusterClientSiteAuditClient (or a test stub) is wired in. return Task.FromResult(EmptyAck); } }