refactor(mesh-phase4): retire EfAlarmConditionStateStore + drop dead ScriptedAlarmState table (Task 9)
Scripted-alarm condition state lives in LocalDb (Phase 4); the ConfigDb-backed Ef store + ScriptedAlarmState table are now dead. Removes the test-harness Ef fallback (a DB-backed node with no store now skips the alarm host), deletes the store + entity + model config, and drops the table via migration. Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
@@ -113,9 +113,8 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
/// Scripted-alarm condition-state store handed to the ScriptedAlarm engine, or
|
||||
/// <see langword="null"/> when none was wired (per-cluster mesh Phase 4). On a driver-role node
|
||||
/// this is the replicated LocalDb store (<c>LocalDbAlarmConditionStateStore</c>) so condition
|
||||
/// state survives without central SQL; when null the actor falls back to an
|
||||
/// <see cref="EfAlarmConditionStateStore"/> over <see cref="_dbFactory"/> (legacy admin/Direct +
|
||||
/// test harnesses), or — when there is no ConfigDb either — skips spawning the alarm host.
|
||||
/// state survives without central SQL; when null the actor skips spawning the alarm host (the
|
||||
/// ConfigDb-backed EF fallback was retired in Phase 4 Task 9).
|
||||
/// </summary>
|
||||
private readonly IAlarmStateStore? _alarmStateStore;
|
||||
|
||||
@@ -135,7 +134,6 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
private readonly IVirtualTagEvaluator _virtualTagEvaluator;
|
||||
private readonly IHistoryWriter _historyWriter;
|
||||
private readonly IActorRef? _virtualTagHostOverride;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly ScriptRootLogger? _scriptRootLogger;
|
||||
private readonly IActorRef? _scriptedAlarmHostOverride;
|
||||
private readonly ILoggingAdapter _log = Context.GetLogger();
|
||||
@@ -383,9 +381,8 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
/// VirtualTag host instead of spawning a real <see cref="VirtualTagHostActor"/> child, so tests
|
||||
/// can intercept the <see cref="VirtualTagHostActor.ApplyVirtualTags"/> message. Null in
|
||||
/// production (the real host is spawned).</param>
|
||||
/// <param name="loggerFactory">Optional logger factory used to create the
|
||||
/// <see cref="EfAlarmConditionStateStore"/>'s logger when spawning the ScriptedAlarm host;
|
||||
/// defaults to <see cref="NullLoggerFactory"/> when not provided.</param>
|
||||
/// <param name="loggerFactory">Retained for constructor-signature stability; unused since Phase 4
|
||||
/// Task 9 retired the <c>EfAlarmConditionStateStore</c> fallback that consumed it. Defaults to null.</param>
|
||||
/// <param name="scriptRootLogger">Optional root script logger required to spawn the ScriptedAlarm
|
||||
/// host (the engine + its script logging hang off it). When null the ScriptedAlarm host is left
|
||||
/// unspawned — the graceful dev/None-deployment path.</param>
|
||||
@@ -398,9 +395,8 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
/// <see cref="NullDriverCapabilityInvokerFactory"/> (pass-through) when not supplied.</param>
|
||||
/// <param name="alarmStateStore">Per-cluster mesh Phase 4: scripted-alarm condition-state store. On a
|
||||
/// driver-role node this is the replicated LocalDb store, so condition state persists with no
|
||||
/// ConfigDb; null falls back to an <see cref="EfAlarmConditionStateStore"/> over
|
||||
/// <paramref name="dbFactory"/> (legacy admin/Direct + test harnesses), or skips the alarm host when
|
||||
/// there is no ConfigDb either. Defaults to null.</param>
|
||||
/// ConfigDb; null skips spawning the alarm host (the ConfigDb-backed EF fallback was retired in
|
||||
/// Phase 4 Task 9). Defaults to null.</param>
|
||||
/// <returns>The Akka.NET <see cref="Akka.Actor.Props"/> used to spawn this actor.</returns>
|
||||
public static Props Props(
|
||||
IDbContextFactory<OtOpcUaConfigDbContext>? dbFactory,
|
||||
@@ -454,8 +450,8 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
/// for historized VirtualTag results; defaults to <see cref="NullHistoryWriter"/>.</param>
|
||||
/// <param name="virtualTagHostOverride">Test seam: when supplied, used as the VirtualTag host
|
||||
/// instead of spawning a real <see cref="VirtualTagHostActor"/> child.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory used to create the
|
||||
/// <see cref="EfAlarmConditionStateStore"/>'s logger; defaults to <see cref="NullLoggerFactory"/>.</param>
|
||||
/// <param name="loggerFactory">Retained for constructor-signature stability; unused since Phase 4
|
||||
/// Task 9 retired the <c>EfAlarmConditionStateStore</c> fallback that consumed it. Defaults to null.</param>
|
||||
/// <param name="scriptRootLogger">Optional root script logger required to spawn the ScriptedAlarm
|
||||
/// host; when null the host is left unspawned.</param>
|
||||
/// <param name="scriptedAlarmHostOverride">Test seam: when supplied, used as the ScriptedAlarm host
|
||||
@@ -471,9 +467,8 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
/// last-known-good configuration while central SQL is unreachable. Null on admin-only nodes and in
|
||||
/// tests that do not exercise the cache — caching is then simply skipped.</param>
|
||||
/// <param name="alarmStateStore">Per-cluster mesh Phase 4: scripted-alarm condition-state store. On a
|
||||
/// driver-role node this is the replicated LocalDb store; null falls back to an
|
||||
/// <see cref="EfAlarmConditionStateStore"/> over <paramref name="dbFactory"/>, or skips the alarm
|
||||
/// host when there is no ConfigDb either.</param>
|
||||
/// driver-role node this is the replicated LocalDb store; null skips spawning the alarm host (the
|
||||
/// ConfigDb-backed EF fallback was retired in Phase 4 Task 9).</param>
|
||||
public DriverHostActor(
|
||||
IDbContextFactory<OtOpcUaConfigDbContext>? dbFactory,
|
||||
CommonsNodeId localNode,
|
||||
@@ -517,7 +512,6 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
_virtualTagEvaluator = virtualTagEvaluator ?? NullVirtualTagEvaluator.Instance;
|
||||
_historyWriter = historyWriter ?? NullHistoryWriter.Instance;
|
||||
_virtualTagHostOverride = virtualTagHostOverride;
|
||||
_loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
|
||||
_scriptRootLogger = scriptRootLogger;
|
||||
_scriptedAlarmHostOverride = scriptedAlarmHostOverride;
|
||||
|
||||
@@ -597,9 +591,10 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
/// <see cref="_scriptRootLogger"/> (the engine + its script logging hang off it); when either
|
||||
/// is missing (legacy ControlPlane test harnesses, dev/None deployments) the host is left
|
||||
/// null and ApplyScriptedAlarms becomes a no-op. The engine is built around a fresh
|
||||
/// <see cref="DependencyMuxTagUpstreamSource"/> + an <see cref="EfAlarmConditionStateStore"/>;
|
||||
/// the host (spawned as a child) owns + disposes the engine in its PostStop, so it stops with
|
||||
/// the driver host.
|
||||
/// <see cref="DependencyMuxTagUpstreamSource"/> + the wired <see cref="IAlarmStateStore"/> (the
|
||||
/// replicated <c>LocalDbAlarmConditionStateStore</c> on a driver-role node); when no store was
|
||||
/// wired the host is skipped. The host (spawned as a child) owns + disposes the engine in its
|
||||
/// PostStop, so it stops with the driver host.
|
||||
/// </summary>
|
||||
private void SpawnScriptedAlarmHost()
|
||||
{
|
||||
@@ -617,30 +612,20 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
return;
|
||||
}
|
||||
|
||||
// Per-cluster mesh Phase 4: prefer the wired condition-state store (the replicated LocalDb store
|
||||
// on a driver-role node — it persists with no ConfigDb). Only when no store was wired do we fall
|
||||
// back to the ConfigDb-backed EF store, and only if there IS a ConfigDb (legacy admin/Direct +
|
||||
// test harnesses). A driver-only node has neither — nowhere to persist condition state — so it
|
||||
// skips the alarm host outright rather than constructing an EF store over a null factory that
|
||||
// would NRE the moment the engine touched it (mirrors the _opcUaPublishActor-null skip above).
|
||||
IAlarmStateStore store;
|
||||
if (_alarmStateStore is not null)
|
||||
{
|
||||
store = _alarmStateStore;
|
||||
}
|
||||
else if (_dbFactory is not null)
|
||||
{
|
||||
store = new EfAlarmConditionStateStore(
|
||||
_dbFactory, _loggerFactory.CreateLogger<EfAlarmConditionStateStore>());
|
||||
}
|
||||
else
|
||||
// Per-cluster mesh Phase 4: condition state lives in the wired store — the replicated LocalDb
|
||||
// store on a driver-role node, which persists with no ConfigDb. The ConfigDb-backed EF fallback
|
||||
// was retired (Task 9); when no store was wired there is nowhere to persist condition state, so
|
||||
// we skip the alarm host outright rather than run the engine against a store it can never save to
|
||||
// (mirrors the _opcUaPublishActor-null skip above).
|
||||
if (_alarmStateStore is null)
|
||||
{
|
||||
_log.Debug(
|
||||
"DriverHost {Node}: skipping ScriptedAlarm host spawn (no condition-state store and no ConfigDb)",
|
||||
"DriverHost {Node}: skipping ScriptedAlarm host spawn (no condition-state store)",
|
||||
_localNode);
|
||||
return;
|
||||
}
|
||||
|
||||
var store = _alarmStateStore;
|
||||
var upstream = new DependencyMuxTagUpstreamSource();
|
||||
var engine = new ScriptedAlarmEngine(
|
||||
upstream, store, new ScriptLoggerFactory(_scriptRootLogger.Logger), _scriptRootLogger.Logger);
|
||||
|
||||
Reference in New Issue
Block a user