diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ClusterNode.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ClusterNode.cs index 1057b1f..5c95ec9 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ClusterNode.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ClusterNode.cs @@ -43,5 +43,4 @@ public sealed class ClusterNode // Navigation public ServerCluster? Cluster { get; set; } public ICollection Credentials { get; set; } = []; - public ClusterNodeGenerationState? GenerationState { get; set; } } diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ClusterNodeGenerationState.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ClusterNodeGenerationState.cs deleted file mode 100644 index f66bc73..0000000 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ClusterNodeGenerationState.cs +++ /dev/null @@ -1,26 +0,0 @@ -using ZB.MOM.WW.OtOpcUa.Configuration.Enums; - -namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities; - -/// -/// Tracks which generation each node has applied. Per-node (not per-cluster) — both nodes of a -/// 2-node cluster track independently per decision #84. -/// -public sealed class ClusterNodeGenerationState -{ - public required string NodeId { get; set; } - - public long? CurrentGenerationId { get; set; } - - public DateTime? LastAppliedAt { get; set; } - - public NodeApplyStatus? LastAppliedStatus { get; set; } - - public string? LastAppliedError { get; set; } - - /// Updated on every poll for liveness detection. - public DateTime? LastSeenAt { get; set; } - - public ClusterNode? Node { get; set; } - public ConfigGeneration? CurrentGeneration { get; set; } -} diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ConfigGeneration.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ConfigGeneration.cs deleted file mode 100644 index eb9da1a..0000000 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ConfigGeneration.cs +++ /dev/null @@ -1,32 +0,0 @@ -using ZB.MOM.WW.OtOpcUa.Configuration.Enums; - -namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities; - -/// -/// Atomic, immutable snapshot of one cluster's configuration. -/// Per decision #82 — cluster-scoped, not fleet-scoped. -/// -public sealed class ConfigGeneration -{ - /// Monotonically increasing ID, generated by IDENTITY(1, 1). - public long GenerationId { get; set; } - - public required string ClusterId { get; set; } - - public required GenerationStatus Status { get; set; } - - public long? ParentGenerationId { get; set; } - - public DateTime? PublishedAt { get; set; } - - public string? PublishedBy { get; set; } - - public string? Notes { get; set; } - - public DateTime CreatedAt { get; set; } = DateTime.UtcNow; - - public required string CreatedBy { get; set; } - - public ServerCluster? Cluster { get; set; } - public ConfigGeneration? Parent { get; set; } -} diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Deployment.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Deployment.cs index 6e618a5..8a4afac 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Deployment.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/Deployment.cs @@ -4,7 +4,7 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities; /// /// Immutable snapshot of a config artifact dispatched to every driver-role node by the -/// ConfigPublishCoordinator. Replaces the v1 draft/publish +/// ConfigPublishCoordinator. Replaces the v1 ConfigGeneration draft/publish /// row; the ArtifactBlob carries the SnapshotAndFlatten() output produced by /// AdminOperationsActor. /// diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/NodeDeploymentState.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/NodeDeploymentState.cs index df20587..0a53094 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/NodeDeploymentState.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/NodeDeploymentState.cs @@ -4,7 +4,7 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities; /// /// Per-(node, deployment) apply progress row owned by the DriverHostActor. Replaces the -/// v1 single-row-per-node model with a history +/// v1 ClusterNodeGenerationState single-row-per-node model with a history /// of every apply attempt so the ConfigPublishCoordinator can reconstruct in-flight state /// after a failover. /// diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs index 08f429a..159bb79 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Entities/ServerCluster.cs @@ -38,5 +38,4 @@ public sealed class ServerCluster // Navigation public ICollection Nodes { get; set; } = []; public ICollection Namespaces { get; set; } = []; - public ICollection Generations { get; set; } = []; } diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/GenerationStatus.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/GenerationStatus.cs deleted file mode 100644 index 1ff8847..0000000 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/GenerationStatus.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ZB.MOM.WW.OtOpcUa.Configuration.Enums; - -/// Generation lifecycle state. Draft → Published → Superseded | RolledBack. -public enum GenerationStatus -{ - Draft, - Published, - Superseded, - RolledBack, -} diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NodeApplyStatus.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NodeApplyStatus.cs deleted file mode 100644 index 44bc0ca..0000000 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Enums/NodeApplyStatus.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ZB.MOM.WW.OtOpcUa.Configuration.Enums; - -/// Status tracked per node in . -public enum NodeApplyStatus -{ - Applied, - RolledBack, - Failed, - InProgress, -} diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/OtOpcUaConfigDbContext.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/OtOpcUaConfigDbContext.cs index 54ba0f6..eef01c5 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/OtOpcUaConfigDbContext.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/OtOpcUaConfigDbContext.cs @@ -15,7 +15,6 @@ public sealed class OtOpcUaConfigDbContext(DbContextOptions ServerClusters => Set(); public DbSet ClusterNodes => Set(); public DbSet ClusterNodeCredentials => Set(); - public DbSet ConfigGenerations => Set(); public DbSet Namespaces => Set(); public DbSet UnsAreas => Set(); public DbSet UnsLines => Set(); @@ -25,7 +24,6 @@ public sealed class OtOpcUaConfigDbContext(DbContextOptions Tags => Set(); public DbSet PollGroups => Set(); public DbSet NodeAcls => Set(); - public DbSet ClusterNodeGenerationStates => Set(); public DbSet ConfigAuditLogs => Set(); public DbSet ExternalIdReservations => Set(); public DbSet DriverHostStatuses => Set(); @@ -38,8 +36,7 @@ public sealed class OtOpcUaConfigDbContext(DbContextOptions ScriptedAlarms => Set(); public DbSet ScriptedAlarmStates => Set(); - // v2 deploy-model tables (Phase 1 of the Akka + fused-hosting alignment). Replace the - // ConfigGeneration/ClusterNodeGenerationState pair when Task 14's migration runs. + // v2 deploy-model tables (Phase 1 of the Akka + fused-hosting alignment). public DbSet Deployments => Set(); public DbSet NodeDeploymentStates => Set(); public DbSet ConfigEdits => Set(); @@ -54,7 +51,6 @@ public sealed class OtOpcUaConfigDbContext(DbContextOptions(e => - { - e.ToTable("ConfigGeneration"); - e.HasKey(x => x.GenerationId); - e.Property(x => x.GenerationId).UseIdentityColumn(seed: 1, increment: 1); - e.Property(x => x.ClusterId).HasMaxLength(64); - e.Property(x => x.Status).HasConversion().HasMaxLength(16); - e.Property(x => x.PublishedAt).HasColumnType("datetime2(3)"); - e.Property(x => x.PublishedBy).HasMaxLength(128); - e.Property(x => x.Notes).HasMaxLength(1024); - e.Property(x => x.CreatedAt).HasColumnType("datetime2(3)").HasDefaultValueSql("SYSUTCDATETIME()"); - e.Property(x => x.CreatedBy).HasMaxLength(128); - - e.HasOne(x => x.Cluster).WithMany(c => c.Generations) - .HasForeignKey(x => x.ClusterId) - .OnDelete(DeleteBehavior.Restrict); - e.HasOne(x => x.Parent).WithMany() - .HasForeignKey(x => x.ParentGenerationId) - .OnDelete(DeleteBehavior.Restrict); - - e.HasIndex(x => new { x.ClusterId, x.Status, x.GenerationId }) - .IsDescending(false, false, true) - .IncludeProperties(x => x.PublishedAt) - .HasDatabaseName("IX_ConfigGeneration_Cluster_Published"); - // One Draft per cluster at a time - e.HasIndex(x => x.ClusterId).IsUnique() - .HasFilter("[Status] = 'Draft'") - .HasDatabaseName("UX_ConfigGeneration_Draft_Per_Cluster"); - }); - } - private static void ConfigureNamespace(ModelBuilder modelBuilder) { modelBuilder.Entity(e => @@ -434,25 +396,6 @@ public sealed class OtOpcUaConfigDbContext(DbContextOptions(e => - { - e.ToTable("ClusterNodeGenerationState"); - e.HasKey(x => x.NodeId); - e.Property(x => x.NodeId).HasMaxLength(64); - e.Property(x => x.LastAppliedAt).HasColumnType("datetime2(3)"); - e.Property(x => x.LastAppliedStatus).HasConversion().HasMaxLength(16); - e.Property(x => x.LastAppliedError).HasMaxLength(2048); - e.Property(x => x.LastSeenAt).HasColumnType("datetime2(3)"); - - e.HasOne(x => x.Node).WithOne(n => n.GenerationState).HasForeignKey(x => x.NodeId).OnDelete(DeleteBehavior.Restrict); - e.HasOne(x => x.CurrentGeneration).WithMany().HasForeignKey(x => x.CurrentGenerationId).OnDelete(DeleteBehavior.Restrict); - - e.HasIndex(x => x.CurrentGenerationId).HasDatabaseName("IX_ClusterNodeGenerationState_Generation"); - }); - } - private static void ConfigureConfigAuditLog(ModelBuilder modelBuilder) { modelBuilder.Entity(e => diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs index 7ed2eea..d0d2833 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs @@ -262,9 +262,8 @@ public static class EquipmentNodeWalker /// /// Pre-loaded + pre-filtered snapshot of one Equipment-kind namespace's worth of Config /// DB rows. All four collections are scoped to the same -/// + the same /// row. The walker assumes this filter -/// was applied by the caller + does no cross-generation or cross-namespace validation. +/// was applied by the caller + does no cross-namespace validation. /// public sealed record EquipmentNamespaceContent( IReadOnlyList Areas,