M3 Bundle F (Task F1) wires the cached-call audit pipeline through the composition roots: - Central: register SiteCallAuditActor as a cluster singleton + proxy (mirrors AuditLogIngestActor and NotificationOutboxActor). Program.cs calls .AddSiteCallAudit() on the central role. - Site: register ICachedCallTelemetryForwarder + CachedCallLifecycleBridge in AddAuditLog (lazy factory — Central nodes degrade to audit-only emission because IOperationTrackingStore is site-only). - Site: bind CachedCallLifecycleBridge to ICachedCallLifecycleObserver so StoreAndForwardService picks it up via DI. - Site: introduce IStoreAndForwardSiteContext + Host adapter to surface the site id to StoreAndForwardService without creating a StoreAndForward -> HealthMonitoring project-reference cycle. - ScriptExecutionActor resolves ICachedCallTelemetryForwarder per script scope and threads it into ScriptRuntimeContext. CachedCallTelemetryForwarder's IOperationTrackingStore dependency is now nullable so Central DI validation succeeds with the lazy registration; the forwarder's tracking-half emission is a no-op when the store is absent. Tests: - AkkaHostedServiceAuditWiringTests: Central host builds with AddSiteCallAudit and resolves ICachedCallTelemetryForwarder; Site resolves the forwarder + bridge + observer + IStoreAndForwardSiteContext. - Full solution: 194 Host tests green, 241 SiteRuntime tests green, every other suite unchanged.
33 lines
1.4 KiB
C#
33 lines
1.4 KiB
C#
using Microsoft.Extensions.Options;
|
|
using ScadaLink.StoreAndForward;
|
|
|
|
namespace ScadaLink.Host;
|
|
|
|
/// <summary>
|
|
/// Audit Log #23 (M3 Bundle F): Host-side adapter implementing the
|
|
/// optional <see cref="IStoreAndForwardSiteContext"/> the Store-and-Forward
|
|
/// service consults to stamp cached-call audit telemetry with the site id.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Forwards <see cref="NodeOptions.SiteId"/> verbatim — the same value
|
|
/// <see cref="SiteIdentityProvider"/> exposes to HealthMonitoring. Defined as
|
|
/// a separate adapter (rather than reusing <see cref="SiteIdentityProvider"/>)
|
|
/// to avoid pulling HealthMonitoring into the StoreAndForward project's
|
|
/// dependency graph, which would create a project-reference cycle.
|
|
/// </remarks>
|
|
public class StoreAndForwardSiteContext : IStoreAndForwardSiteContext
|
|
{
|
|
public string SiteId { get; }
|
|
|
|
public StoreAndForwardSiteContext(IOptions<NodeOptions> nodeOptions)
|
|
{
|
|
// NodeOptions.SiteId is nullable; SiteServiceRegistration ONLY adds
|
|
// this binding on the site role, so a non-null site id is expected
|
|
// here. Mirror SiteIdentityProvider's hard fail so a missing site id
|
|
// surfaces at composition time rather than at the first cached call.
|
|
SiteId = nodeOptions.Value.SiteId
|
|
?? throw new InvalidOperationException(
|
|
"ScadaLink:Node:SiteId is required for the site role's StoreAndForward wiring.");
|
|
}
|
|
}
|