refactor(opcuaserver): rename Phase7* address-space pipeline to AddressSpace*
v2-ci / build (push) Failing after 37s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
v2-ci / build (push) Failing after 37s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
The OPC UA address-space build pipeline was named after a v2-roadmap milestone number rather than its domain. Rename the family to describe what it does (build/diff/apply the OPC UA address space): Phase7Composer -> AddressSpaceComposer Phase7CompositionResult -> AddressSpaceComposition Phase7Planner -> AddressSpacePlanner Phase7Plan -> AddressSpacePlan Phase7Applier -> AddressSpaceApplier Phase7ApplyOutcome -> AddressSpaceApplyOutcome The 9 Phase7*Tests suites follow suit; Phase7ScriptingEntitiesTests -> ScriptingEntitiesTests (it tests the scripting migration, not the pipeline). Log-message prefixes move to the new class names. Pure mechanical rename, no behavioral change. EF migration classes/IDs (AddPhase7ScriptingTables, ExtendComputeGenerationDiffWithPhase7) are immutable and left untouched, as are historical design docs. Build clean; OpcUaServer 261/261, Runtime 272/272, ScriptingEntities 12/12 green.
This commit is contained in:
@@ -169,8 +169,8 @@ public static class DeploymentArtifact
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the artifact into the projected <see cref="Phase7CompositionResult"/> used by
|
||||
/// <c>Phase7Planner</c> + <c>Phase7Applier</c>. Returns an empty composition for empty/
|
||||
/// Parse the artifact into the projected <see cref="AddressSpaceComposition"/> used by
|
||||
/// <c>AddressSpacePlanner</c> + <c>AddressSpaceApplier</c>. Returns an empty composition for empty/
|
||||
/// malformed blobs so callers can treat parse failure as a no-op deploy.
|
||||
///
|
||||
/// The artifact JSON is produced by <c>ConfigComposer.SnapshotAndFlattenAsync</c> in the
|
||||
@@ -179,7 +179,7 @@ public static class DeploymentArtifact
|
||||
/// nodes.
|
||||
/// </summary>
|
||||
/// <param name="blob">The deployment artifact blob to parse.</param>
|
||||
public static Phase7CompositionResult ParseComposition(ReadOnlySpan<byte> blob)
|
||||
public static AddressSpaceComposition ParseComposition(ReadOnlySpan<byte> blob)
|
||||
{
|
||||
if (blob.IsEmpty) return Empty();
|
||||
|
||||
@@ -197,7 +197,7 @@ public static class DeploymentArtifact
|
||||
var equipmentVirtualTags = BuildEquipmentVirtualTagPlans(root, equipmentTags);
|
||||
var equipmentScriptedAlarms = BuildEquipmentScriptedAlarmPlans(root);
|
||||
|
||||
return new Phase7CompositionResult(areas, lines, equipment, drivers, alarms)
|
||||
return new AddressSpaceComposition(areas, lines, equipment, drivers, alarms)
|
||||
{
|
||||
EquipmentTags = equipmentTags,
|
||||
EquipmentVirtualTags = equipmentVirtualTags,
|
||||
@@ -224,7 +224,7 @@ public static class DeploymentArtifact
|
||||
/// <param name="nodeId">This node's identity in "host:port" form.</param>
|
||||
/// <param name="onInconsistency">Optional diagnostic callback for cross-cluster orphan bindings; null disables the check.</param>
|
||||
/// <returns>The filtered composition per the node's scoping decision.</returns>
|
||||
public static Phase7CompositionResult ParseComposition(
|
||||
public static AddressSpaceComposition ParseComposition(
|
||||
ReadOnlySpan<byte> blob, string nodeId, Action<string>? onInconsistency = null)
|
||||
{
|
||||
var scope = ResolveClusterScope(blob, nodeId);
|
||||
@@ -253,7 +253,7 @@ public static class DeploymentArtifact
|
||||
}
|
||||
}
|
||||
|
||||
return new Phase7CompositionResult(
|
||||
return new AddressSpaceComposition(
|
||||
full.UnsAreas.Where(a => sets.AreaIds.Contains(a.UnsAreaId)).ToArray(),
|
||||
keptLines,
|
||||
keptEquipment,
|
||||
@@ -348,7 +348,7 @@ public static class DeploymentArtifact
|
||||
}
|
||||
}
|
||||
|
||||
private static Phase7CompositionResult Empty() => new(
|
||||
private static AddressSpaceComposition Empty() => new(
|
||||
Array.Empty<UnsAreaProjection>(),
|
||||
Array.Empty<UnsLineProjection>(),
|
||||
Array.Empty<EquipmentNode>(),
|
||||
@@ -359,7 +359,7 @@ public static class DeploymentArtifact
|
||||
/// Cross-reference the artifact's Tags + Namespaces + DriverInstances arrays to find
|
||||
/// Equipment-namespace tags (non-null EquipmentId, owning namespace Kind == Equipment), then
|
||||
/// emit one <see cref="EquipmentTagPlan"/> per qualifying tag. The artifact-decode mirror of
|
||||
/// <c>Phase7Composer.Compose</c>'s equipment filter — so the compose-side + artifact-decode
|
||||
/// <c>AddressSpaceComposer.Compose</c>'s equipment filter — so the compose-side + artifact-decode
|
||||
/// plans agree on the same set of tags. FullName is read from each tag's TagConfig blob
|
||||
/// (top-level "FullName" field).
|
||||
/// </summary>
|
||||
@@ -421,7 +421,7 @@ public static class DeploymentArtifact
|
||||
// AccessLevel → Writable. ConfigComposer serialises the TagAccessLevel enum WITHOUT a
|
||||
// string converter, so it lands as a number (Read = 0, ReadWrite = 1); tolerate the string
|
||||
// form ("ReadWrite") too — same defensive both-forms parse as the Kind gate above. MUST match
|
||||
// Phase7Composer's `AccessLevel == TagAccessLevel.ReadWrite` exactly (byte-parity). A missing
|
||||
// AddressSpaceComposer's `AccessLevel == TagAccessLevel.ReadWrite` exactly (byte-parity). A missing
|
||||
// field defaults to non-writable (read-only).
|
||||
var writable = el.TryGetProperty("AccessLevel", out var alEl) && alEl.ValueKind switch
|
||||
{
|
||||
@@ -469,7 +469,7 @@ public static class DeploymentArtifact
|
||||
/// <summary>
|
||||
/// Join the artifact's VirtualTags array to its Scripts array (by ScriptId) to emit one
|
||||
/// <see cref="EquipmentVirtualTagPlan"/> per VirtualTag. The artifact-decode mirror of
|
||||
/// <c>Phase7Composer.Compose</c>'s VirtualTag producer — so the compose-side + artifact-decode
|
||||
/// <c>AddressSpaceComposer.Compose</c>'s VirtualTag producer — so the compose-side + artifact-decode
|
||||
/// plans agree. The reserved <c>{{equip}}</c> token in the joined Script's <c>SourceCode</c> is
|
||||
/// substituted with the owning equipment's tag base (derived from <paramref name="equipmentTags"/>'
|
||||
/// FullNames) BEFORE refs are extracted, byte-parity with the composer. <c>Expression</c> = the
|
||||
@@ -529,14 +529,14 @@ public static class DeploymentArtifact
|
||||
// Historize: the artifact carries a Pascal-case "Historize" bool (ConfigComposer serialises
|
||||
// the whole VirtualTag entity with DefaultIgnoreCondition.Never). Robust parse — default
|
||||
// false; only honoured when the JSON value is an actual boolean — so absent/non-bool ⇒ false,
|
||||
// byte-parity with Phase7Composer's entity-default-false behaviour.
|
||||
// byte-parity with AddressSpaceComposer's entity-default-false behaviour.
|
||||
var historize = el.TryGetProperty("Historize", out var hEl)
|
||||
&& (hEl.ValueKind == JsonValueKind.True || hEl.ValueKind == JsonValueKind.False)
|
||||
&& hEl.GetBoolean();
|
||||
|
||||
// Substitute the {{equip}} token with the owning equipment's tag base BEFORE extracting
|
||||
// refs, so both Expression and DependencyRefs are machine-specific — byte-parity with
|
||||
// Phase7Composer.Compose.
|
||||
// AddressSpaceComposer.Compose.
|
||||
var expanded = EquipmentScriptPaths.SubstituteEquipmentToken(
|
||||
source, baseByEquip.GetValueOrDefault(equipmentId!));
|
||||
|
||||
@@ -562,7 +562,7 @@ public static class DeploymentArtifact
|
||||
/// <summary>
|
||||
/// Join the artifact's ScriptedAlarms array to its Scripts array (by PredicateScriptId) to emit
|
||||
/// one <see cref="EquipmentScriptedAlarmPlan"/> per alarm. The artifact-decode mirror of
|
||||
/// <c>Phase7Composer.Compose</c>'s scripted-alarm producer — so the compose-side + artifact-decode
|
||||
/// <c>AddressSpaceComposer.Compose</c>'s scripted-alarm producer — so the compose-side + artifact-decode
|
||||
/// plans agree byte-for-byte. An alarm whose <c>PredicateScriptId</c> has no matching Script row is
|
||||
/// SKIPPED (matching the composer's skip behaviour) to preserve parity. <c>PredicateSource</c> = the
|
||||
/// joined script source ("" when missing — but such alarms are skipped above); <c>DependencyRefs</c>
|
||||
@@ -616,7 +616,7 @@ public static class DeploymentArtifact
|
||||
|
||||
if (string.IsNullOrWhiteSpace(scriptedAlarmId)) continue;
|
||||
|
||||
// Skip alarms whose predicate script is missing — matching Phase7Composer's skip behaviour
|
||||
// Skip alarms whose predicate script is missing — matching AddressSpaceComposer's skip behaviour
|
||||
// so both sides emit the same set (byte-parity).
|
||||
if (predicateScriptId is null || !scriptSourceById.TryGetValue(predicateScriptId, out var source))
|
||||
continue;
|
||||
@@ -646,7 +646,7 @@ public static class DeploymentArtifact
|
||||
|
||||
/// <summary>
|
||||
/// Extract the driver-side full reference from a tag's TagConfig JSON (top-level "FullName"
|
||||
/// field). The artifact-decode mirror of <c>Phase7Composer.ExtractTagFullName</c> /
|
||||
/// field). The artifact-decode mirror of <c>AddressSpaceComposer.ExtractTagFullName</c> /
|
||||
/// <c>EquipmentNodeWalker.ExtractFullName</c> — replicated because Runtime does not reference
|
||||
/// the Core driver assembly. Falls back to the raw blob when absent or non-JSON.
|
||||
/// </summary>
|
||||
@@ -669,7 +669,7 @@ public static class DeploymentArtifact
|
||||
|
||||
/// <summary>Parses the optional <c>alarm</c> object from a tag's <c>TagConfig</c> JSON. Returns null
|
||||
/// when absent, non-object, or non-JSON (the tag is then a plain variable). Never throws. The
|
||||
/// live-edit side (<c>Phase7Composer.ExtractTagAlarm</c>) MUST parse identically (byte-parity).</summary>
|
||||
/// live-edit side (<c>AddressSpaceComposer.ExtractTagAlarm</c>) MUST parse identically (byte-parity).</summary>
|
||||
private static EquipmentTagAlarmInfo? ExtractTagAlarm(string? tagConfig)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tagConfig)) return null;
|
||||
@@ -683,7 +683,7 @@ public static class DeploymentArtifact
|
||||
var sev = a.TryGetProperty("severity", out var sEl) && sEl.ValueKind == JsonValueKind.Number
|
||||
&& sEl.TryGetInt32(out var sv) ? sv : 500;
|
||||
// historizeToAveva (bool?, absent ⇒ null ⇒ historize): byte-parity with
|
||||
// Phase7Composer.ExtractTagAlarm — only an explicit false suppresses the durable AVEVA write.
|
||||
// AddressSpaceComposer.ExtractTagAlarm — only an explicit false suppresses the durable AVEVA write.
|
||||
bool? historize = a.TryGetProperty("historizeToAveva", out var hEl)
|
||||
&& hEl.ValueKind is JsonValueKind.True or JsonValueKind.False
|
||||
? hEl.GetBoolean()
|
||||
@@ -699,7 +699,7 @@ public static class DeploymentArtifact
|
||||
/// whitespace-or-empty ⇒ <c>null</c>, meaning the historian tagname defaults to the tag's FullName,
|
||||
/// resolved later). The raw string value is used — not trimmed — matching <c>ExtractTagFullName</c> /
|
||||
/// <c>ExtractTagAlarm</c>. Never throws. The live-edit composer side
|
||||
/// (<c>Phase7Composer.ExtractTagHistorize</c>) MUST parse identically (byte-parity).</summary>
|
||||
/// (<c>AddressSpaceComposer.ExtractTagHistorize</c>) MUST parse identically (byte-parity).</summary>
|
||||
private static (bool IsHistorized, string? HistorianTagname) ExtractTagHistorize(string? tagConfig)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tagConfig)) return (false, null);
|
||||
@@ -727,7 +727,7 @@ public static class DeploymentArtifact
|
||||
/// <c>arrayLength</c> uint (honoured ONLY when <c>isArray</c> is true AND the prop is a JSON number
|
||||
/// that fits <c>uint</c>; else <c>null</c>). Mirrors <see cref="ExtractTagHistorize"/> in structure +
|
||||
/// null/blank/non-object/malformed-JSON tolerance. Never throws. The live-edit composer side
|
||||
/// (<c>Phase7Composer.ExtractTagArray</c>) MUST parse identically (byte-parity).</summary>
|
||||
/// (<c>AddressSpaceComposer.ExtractTagArray</c>) MUST parse identically (byte-parity).</summary>
|
||||
private static (bool IsArray, uint? ArrayLength) ExtractTagArray(string? tagConfig)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tagConfig)) return (false, null);
|
||||
@@ -764,7 +764,7 @@ public static class DeploymentArtifact
|
||||
var item = reader(el);
|
||||
if (item is not null) result.Add(item);
|
||||
}
|
||||
// Match Phase7Composer's natural-key sort so plan diffs are deterministic across
|
||||
// Match AddressSpaceComposer's natural-key sort so plan diffs are deterministic across
|
||||
// artifact-decode + composer-compose passes.
|
||||
return result.OrderBy(IdentityOf, StringComparer.Ordinal).ToList();
|
||||
}
|
||||
|
||||
@@ -939,7 +939,7 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
||||
return;
|
||||
}
|
||||
|
||||
Phase7CompositionResult composition;
|
||||
AddressSpaceComposition composition;
|
||||
try
|
||||
{
|
||||
composition = DeploymentArtifact.ParseComposition(blob, _localNode.Value);
|
||||
|
||||
Reference in New Issue
Block a user