feat: replace site registration with database-driven site addressing

Central now resolves site Akka remoting addresses from the Sites DB table
(NodeAAddress/NodeBAddress) instead of relying on runtime RegisterSite
messages. Eliminates the race condition where sites starting before central
had their registration dead-lettered. Addresses are cached in
CentralCommunicationActor with 60s periodic refresh and on-demand refresh
when sites are added/edited/deleted via UI or CLI.
This commit is contained in:
Joseph Doherty
2026-03-17 23:13:10 -04:00
parent eb8d5ca2c0
commit 9e97c1acd2
21 changed files with 1641 additions and 92 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace ScadaLink.ConfigurationDatabase.Migrations
{
/// <inheritdoc />
public partial class AddSiteNodeAddresses : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "NodeAAddress",
table: "Sites",
type: "nvarchar(500)",
maxLength: 500,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "NodeBAddress",
table: "Sites",
type: "nvarchar(500)",
maxLength: 500,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "NodeAAddress",
table: "Sites");
migrationBuilder.DropColumn(
name: "NodeBAddress",
table: "Sites");
}
}
}

View File

@@ -699,6 +699,24 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
Id = 1,
LdapGroupName = "SCADA-Admins",
Role = "Admin"
},
new
{
Id = 2,
LdapGroupName = "SCADA-Designers",
Role = "Design"
},
new
{
Id = 3,
LdapGroupName = "SCADA-Deploy-All",
Role = "Deployment"
},
new
{
Id = 4,
LdapGroupName = "SCADA-Deploy-SiteA",
Role = "Deployment"
});
});
@@ -773,6 +791,14 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("NodeAAddress")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<string>("NodeBAddress")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<string>("SiteIdentifier")
.IsRequired()
.HasMaxLength(100)