feat(deploy): add PendingDeployment entity + migration
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
namespace ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A flattened instance config staged for a single in-flight deployment, fetched
|
||||||
|
/// by the site over HTTP instead of being shipped inside an Akka message (avoids
|
||||||
|
/// the 128 KB frame limit). Keyed by DeploymentId; at most one row per InstanceId
|
||||||
|
/// (a newer deploy supersedes the prior pending row). Carries a per-deployment
|
||||||
|
/// fetch token and a TTL. Promoted to DeployedConfigSnapshot on success; purged
|
||||||
|
/// on failure/timeout/TTL.
|
||||||
|
/// </summary>
|
||||||
|
public class PendingDeployment
|
||||||
|
{
|
||||||
|
/// <summary>Primary key.</summary>
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Unique deployment identifier assigned at deploy time; the fetch key for the staged config.</summary>
|
||||||
|
public string DeploymentId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Foreign key to the owning <c>Instance</c> entity. At most one pending row per instance.</summary>
|
||||||
|
public int InstanceId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Revision hash of the flattened configuration, used for staleness detection.</summary>
|
||||||
|
public string RevisionHash { get; set; }
|
||||||
|
|
||||||
|
/// <summary>JSON-serialized flattened configuration staged for the site to fetch.</summary>
|
||||||
|
public string ConfigurationJson { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Per-deployment fetch token presented by the site to authorize the HTTP fetch.</summary>
|
||||||
|
public string Token { get; set; }
|
||||||
|
|
||||||
|
/// <summary>UTC timestamp when this pending row was created.</summary>
|
||||||
|
public DateTimeOffset CreatedAtUtc { get; set; }
|
||||||
|
|
||||||
|
/// <summary>UTC timestamp after which this pending row is considered expired (TTL) and may be purged.</summary>
|
||||||
|
public DateTimeOffset ExpiresAtUtc { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new pending deployment with its identity, staged configuration, fetch token, and TTL.</summary>
|
||||||
|
/// <param name="deploymentId">Unique deployment identifier (fetch key).</param>
|
||||||
|
/// <param name="instanceId">Owning instance identifier.</param>
|
||||||
|
/// <param name="revisionHash">Revision hash of the flattened configuration.</param>
|
||||||
|
/// <param name="configurationJson">JSON-serialized flattened configuration.</param>
|
||||||
|
/// <param name="token">Per-deployment fetch token.</param>
|
||||||
|
/// <param name="createdAtUtc">UTC creation timestamp.</param>
|
||||||
|
/// <param name="expiresAtUtc">UTC expiry timestamp (TTL).</param>
|
||||||
|
public PendingDeployment(
|
||||||
|
string deploymentId, int instanceId, string revisionHash,
|
||||||
|
string configurationJson, string token,
|
||||||
|
DateTimeOffset createdAtUtc, DateTimeOffset expiresAtUtc)
|
||||||
|
{
|
||||||
|
DeploymentId = deploymentId ?? throw new ArgumentNullException(nameof(deploymentId));
|
||||||
|
InstanceId = instanceId;
|
||||||
|
RevisionHash = revisionHash ?? throw new ArgumentNullException(nameof(revisionHash));
|
||||||
|
ConfigurationJson = configurationJson ?? throw new ArgumentNullException(nameof(configurationJson));
|
||||||
|
Token = token ?? throw new ArgumentNullException(nameof(token));
|
||||||
|
CreatedAtUtc = createdAtUtc;
|
||||||
|
ExpiresAtUtc = expiresAtUtc;
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment;
|
||||||
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances;
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Configurations;
|
||||||
|
|
||||||
|
public class PendingDeploymentConfiguration : IEntityTypeConfiguration<PendingDeployment>
|
||||||
|
{
|
||||||
|
/// <summary>Configures the EF Core mapping for <see cref="PendingDeployment"/>.</summary>
|
||||||
|
/// <param name="builder">The entity type builder.</param>
|
||||||
|
public void Configure(EntityTypeBuilder<PendingDeployment> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("PendingDeployments");
|
||||||
|
builder.HasKey(x => x.Id);
|
||||||
|
builder.Property(x => x.DeploymentId).IsRequired().HasMaxLength(100);
|
||||||
|
builder.HasIndex(x => x.DeploymentId).IsUnique();
|
||||||
|
builder.HasIndex(x => x.InstanceId);
|
||||||
|
builder.HasIndex(x => x.ExpiresAtUtc);
|
||||||
|
builder.Property(x => x.RevisionHash).IsRequired().HasMaxLength(100);
|
||||||
|
builder.Property(x => x.ConfigurationJson).IsRequired(); // nvarchar(max)
|
||||||
|
builder.Property(x => x.Token).IsRequired().HasMaxLength(128);
|
||||||
|
|
||||||
|
builder.HasOne<Instance>().WithMany()
|
||||||
|
.HasForeignKey(x => x.InstanceId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2009
File diff suppressed because it is too large
Load Diff
+63
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddPendingDeployment : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PendingDeployments",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
DeploymentId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
InstanceId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
RevisionHash = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
ConfigurationJson = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
Token = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
||||||
|
CreatedAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
|
||||||
|
ExpiresAtUtc = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_PendingDeployments", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_PendingDeployments_Instances_InstanceId",
|
||||||
|
column: x => x.InstanceId,
|
||||||
|
principalTable: "Instances",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PendingDeployments_DeploymentId",
|
||||||
|
table: "PendingDeployments",
|
||||||
|
column: "DeploymentId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PendingDeployments_ExpiresAtUtc",
|
||||||
|
table: "PendingDeployments",
|
||||||
|
column: "ExpiresAtUtc");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PendingDeployments_InstanceId",
|
||||||
|
table: "PendingDeployments",
|
||||||
|
column: "InstanceId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PendingDeployments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+57
@@ -267,6 +267,54 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations
|
|||||||
b.ToTable("DeploymentRecords");
|
b.ToTable("DeploymentRecords");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment.PendingDeployment", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ConfigurationJson")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("DeploymentId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("ExpiresAtUtc")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<int>("InstanceId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("RevisionHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<string>("Token")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("DeploymentId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("ExpiresAtUtc");
|
||||||
|
|
||||||
|
b.HasIndex("InstanceId");
|
||||||
|
|
||||||
|
b.ToTable("PendingDeployments", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment.SystemArtifactDeploymentRecord", b =>
|
modelBuilder.Entity("ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment.SystemArtifactDeploymentRecord", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -1720,6 +1768,15 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations
|
|||||||
.IsRequired();
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment.PendingDeployment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances.Instance", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("InstanceId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems.ExternalSystemMethod", b =>
|
modelBuilder.Entity("ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems.ExternalSystemMethod", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems.ExternalSystemDefinition", null)
|
b.HasOne("ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems.ExternalSystemDefinition", null)
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ public class ScadaBridgeDbContext : DbContext, IDataProtectionKeyContext
|
|||||||
public DbSet<SystemArtifactDeploymentRecord> SystemArtifactDeploymentRecords => Set<SystemArtifactDeploymentRecord>();
|
public DbSet<SystemArtifactDeploymentRecord> SystemArtifactDeploymentRecords => Set<SystemArtifactDeploymentRecord>();
|
||||||
/// <summary>Gets the set of deployed configuration snapshots.</summary>
|
/// <summary>Gets the set of deployed configuration snapshots.</summary>
|
||||||
public DbSet<DeployedConfigSnapshot> DeployedConfigSnapshots => Set<DeployedConfigSnapshot>();
|
public DbSet<DeployedConfigSnapshot> DeployedConfigSnapshots => Set<DeployedConfigSnapshot>();
|
||||||
|
/// <summary>Gets the set of pending deployments staged for HTTP fetch by sites.</summary>
|
||||||
|
public DbSet<PendingDeployment> PendingDeployments => Set<PendingDeployment>();
|
||||||
|
|
||||||
// External Systems
|
// External Systems
|
||||||
/// <summary>Gets the set of external system definitions.</summary>
|
/// <summary>Gets the set of external system definitions.</summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user