feat(opcua): route AddressSpaceApplier through the classifier — pure-add deploys no longer rebuild (R2-07 T2)

This commit is contained in:
Joseph Doherty
2026-07-13 11:46:24 -04:00
parent bb226f45ed
commit 0d717e4785
5 changed files with 210 additions and 85 deletions
@@ -23,7 +23,7 @@ public sealed class AddressSpaceApplierFailureSurfaceTests
var sink = new ConfigurableThrowingSink { ThrowOnRebuild = true };
var applier = new AddressSpaceApplier(sink, NullLogger<AddressSpaceApplier>.Instance);
var outcome = applier.Apply(AddedEquipmentPlan("new"));
var outcome = applier.Apply(RebuildingPlan("eq-1"));
outcome.RebuildCalled.ShouldBeTrue();
outcome.RebuildFailed.ShouldBeTrue();
@@ -36,7 +36,7 @@ public sealed class AddressSpaceApplierFailureSurfaceTests
var sink = new ConfigurableThrowingSink();
var applier = new AddressSpaceApplier(sink, NullLogger<AddressSpaceApplier>.Instance);
var outcome = applier.Apply(AddedEquipmentPlan("new"));
var outcome = applier.Apply(RebuildingPlan("eq-1"));
outcome.RebuildCalled.ShouldBeTrue();
outcome.RebuildFailed.ShouldBeFalse();
@@ -121,10 +121,18 @@ public sealed class AddressSpaceApplierFailureSurfaceTests
EquipmentScriptedAlarms = alarms,
};
private static AddressSpacePlan AddedEquipmentPlan(string id) => new(
AddedEquipment: new[] { new EquipmentNode(id, id, "line-1") },
// A rebuild-forcing plan: a node-affecting ChangedEquipment delta classifies as Rebuild (R2-07), so
// these tests exercise the SafeRebuild path (RebuildCalled/RebuildFailed) regardless of the pure-add
// routing. A pure-add plan would no longer rebuild, so the failure-surface tests must use a change.
private static AddressSpacePlan RebuildingPlan(string id) => new(
AddedEquipment: Array.Empty<EquipmentNode>(),
RemovedEquipment: Array.Empty<EquipmentNode>(),
ChangedEquipment: Array.Empty<AddressSpacePlan.EquipmentDelta>(),
ChangedEquipment: new[]
{
new AddressSpacePlan.EquipmentDelta(
new EquipmentNode(id, id, "line-1"),
new EquipmentNode(id, id + "-renamed", "line-1")),
},
AddedDrivers: Array.Empty<DriverInstancePlan>(),
RemovedDrivers: Array.Empty<DriverInstancePlan>(),
ChangedDrivers: Array.Empty<AddressSpacePlan.DriverDelta>(),