e427b38fb3
Add a periodic reconciliation tick to SiteCallAuditActor that, per site, pulls changed SiteCall rows since a per-site UpdatedAtUtc cursor and upserts them idempotently (monotonic UpsertAsync) — the documented self-heal for lost best-effort gRPC telemetry. Mirrors SiteAuditReconciliationActor's structure (per-site cursor, per-site try/catch failure isolation, advance cursor by max observed UpdatedAtUtc) minus the stalled-detection EventStream machinery. Dependency wiring: add an acyclic SiteCallAudit -> AuditLog project reference and resolve IPullSiteCallsClient + ISiteEnumerator (central-only singletons registered by AddAuditLogCentralReconciliationClient) from the IServiceProvider the production ctor already holds — no Host Props.Create change needed. The repo-only test ctor injects neither collaborator, so the tick is gated off there. A new public test ctor injects fake client + enumerator + repo so the tick is unit-testable in-memory (public, not internal: Akka's ActivatorProducer uses public-only reflection binding). Options: ReconciliationInterval (default 5 min, clamped >= 1s so a zero config value can't spin the scheduler) + ReconciliationBatchSize (default 500), plus a test-only override that bypasses the clamp for millisecond cadences. Tests (all in-memory, no live MSSQL): absent row is upserted on a tick; second tick advances the cursor past already-pulled rows; one failing site does not sink other sites; repo-only ctor does not start the tick.
48 lines
2.9 KiB
XML
48 lines
2.9 KiB
XML
<Project Sdk="Microsoft.NET.Sdk">
|
|
|
|
<PropertyGroup>
|
|
<TargetFramework>net10.0</TargetFramework>
|
|
<ImplicitUsings>enable</ImplicitUsings>
|
|
<Nullable>enable</Nullable>
|
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<!-- SiteCallAuditActor is an Akka actor (central singleton in Bundle F); Akka is an explicit dependency. -->
|
|
<PackageReference Include="Akka" />
|
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
|
<PackageReference Include="Microsoft.Extensions.Options" />
|
|
<!-- BindConfiguration extension for the SiteCallAuditOptions binding. -->
|
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.Commons/ZB.MOM.WW.ScadaBridge.Commons.csproj" />
|
|
<!-- Site Call Audit (#22) sits alongside Notification Outbox (#21) and Audit Log (#23).
|
|
ISiteCallAuditRepository is registered by ZB.MOM.WW.ScadaBridge.ConfigurationDatabase; the
|
|
project reference is documented here so the actor's scope-per-message
|
|
GetRequiredService<ISiteCallAuditRepository>() compiles. -->
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.csproj" />
|
|
<!-- Task 5 (#22): the central→site Retry/Discard relay routes RetryParkedOperation /
|
|
DiscardParkedOperation to the owning site via SiteEnvelope + CentralCommunicationActor,
|
|
the same transport every other central→site command uses. SiteEnvelope is defined
|
|
in ZB.MOM.WW.ScadaBridge.Communication (no cycle: Communication does not reference SiteCallAudit). -->
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.Communication/ZB.MOM.WW.ScadaBridge.Communication.csproj" />
|
|
<!-- Reconciliation tick (#22): the per-site PullSiteCalls self-heal pull resolves
|
|
IPullSiteCallsClient + ISiteEnumerator (both central-only singletons registered by
|
|
AddAuditLogCentralReconciliationClient) from the actor's root IServiceProvider. They live
|
|
in ZB.MOM.WW.ScadaBridge.AuditLog.Central so the SiteCall pull client reuses the shared
|
|
SiteEntry enumerator the sibling IPullAuditEventsClient already uses. No cycle: AuditLog
|
|
references only Commons / ConfigurationDatabase / Communication — none of which reference
|
|
SiteCallAudit. Preferred over moving the interfaces into Commons (Commons has no Akka /
|
|
Communication dependency and would have to carry a Communication-adjacent message). -->
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.AuditLog/ZB.MOM.WW.ScadaBridge.AuditLog.csproj" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<InternalsVisibleTo Include="ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests" />
|
|
</ItemGroup>
|
|
|
|
</Project>
|