Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/ScriptRunEventPolicyTests.cs
T
Joseph Doherty c254d0740e perf(sitelog): sampled per-run events; interval run summaries; site_events replication policy pinned
Implements WP3.2 stage (b) per docs/plans/2026-08-15-site-events-policy-design.md.

- Per-run instance-script Started/Completed Info site events are now off by
  default (SiteRuntimeOptions.PerRunScriptEvents=false) instead of firing on
  every run, closing the dominant site_events writer. Gated at the ScriptRunLauncher
  call sites (moved there from ScriptExecutionActor by WP3.1). Error-level events
  (timeout/failure/stuck-watchdog/recursion-limit) remain unconditional.
- ScriptRunSummaryRecorder accumulates per-(instance, script) run counters and a
  new site-only ScriptRunSummaryFlushService emits one aggregate "script" Info
  site event per ScriptRunSummaryIntervalSeconds (default 300s), top-50-script
  breakdown with an "others" rollup, zero-activity intervals emit nothing.
- Per-script opt-in via PerRunScriptEventScripts ("Instance/Script" exact or
  "Instance/*" wildcard), matched by the new pure ScriptRunEventPolicy. All three
  options are read from IOptionsMonitor<SiteRuntimeOptions> per run, so the
  policy is hot-togglable without a restart.
- Fixed the stale "event log is not replicated" comment at AkkaHostedService.cs
  (~905): site_events IS registered in SiteLocalDbSetup.ReplicatedTables — the
  singleton is what makes queries always hit the actively-written copy;
  replication is what gives the singleton history to read after a failover
  (memo Decision (b)). site_events replication itself is unchanged (still
  registered) and already pinned by
  tests/ZB.MOM.WW.ScadaBridge.Host.Tests/SiteLocalDbCdcRegistrationTests.cs.
- Updated Component-SiteEventLogging.md (Volume Policy section, corrected
  Storage/replication rationale) and Component-SiteRuntime.md (Script Run
  Launch + Error Handling sections).
2026-08-14 22:56:08 -04:00

85 lines
2.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;
namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Scripts;
/// <summary>
/// WP3.2 (site_events volume policy — docs/plans/2026-08-15-site-events-policy-design.md,
/// stage (b) test plan items 13): pure unit tests for
/// <see cref="ScriptRunEventPolicy.ShouldEmitPerRun"/>, isolated from any actor or DI
/// plumbing — the actor-level wiring (hot toggle, hosted-service registration) is covered by
/// <c>ScriptRunLauncherParityTests</c>.
/// </summary>
public class ScriptRunEventPolicyTests
{
private static SiteRuntimeOptions Options(
bool perRunScriptEvents = false, string[]? perRunScriptEventScripts = null)
=> new()
{
PerRunScriptEvents = perRunScriptEvents,
PerRunScriptEventScripts = (perRunScriptEventScripts ?? []).ToList()
};
[Fact]
public void DefaultOptions_EmitsNothing()
{
Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(Options(), "Inst1", "Runner"));
}
[Fact]
public void GlobalSwitchOn_EmitsForEveryScript()
{
var options = Options(perRunScriptEvents: true);
Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "Runner"));
Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "AnyOtherInstance", "AnyOtherScript"));
}
[Fact]
public void ExactPerScriptMatch_Emits()
{
var options = Options(perRunScriptEventScripts: ["Inst1/Runner"]);
Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "Runner"));
}
[Fact]
public void ExactPerScriptMatch_DoesNotMatchADifferentScriptOnTheSameInstance()
{
var options = Options(perRunScriptEventScripts: ["Inst1/Runner"]);
Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "OtherScript"));
}
[Fact]
public void ExactPerScriptMatch_DoesNotMatchTheSameScriptNameOnADifferentInstance()
{
var options = Options(perRunScriptEventScripts: ["Inst1/Runner"]);
Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst2", "Runner"));
}
[Fact]
public void InstanceWildcard_EmitsForEveryScriptOnThatInstanceOnly()
{
var options = Options(perRunScriptEventScripts: ["Inst1/*"]);
Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "Runner"));
Assert.True(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst1", "AnotherScript"));
Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst2", "Runner"));
}
[Fact]
public void NonMatchingScript_StaysSilent()
{
var options = Options(perRunScriptEventScripts: ["Inst1/Runner", "Inst2/*"]);
Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(options, "Inst3", "Runner"));
}
[Fact]
public void EmptyOptInList_StaysSilent()
{
Assert.False(ScriptRunEventPolicy.ShouldEmitPerRun(Options(), "Inst1", "Runner"));
}
}