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

View File

@@ -13,6 +13,7 @@ using ScadaLink.Commons.Interfaces.Repositories;
using ScadaLink.Commons.Messages.Management;
using ScadaLink.DeploymentManager;
using ScadaLink.HealthMonitoring;
using ScadaLink.Communication;
using ScadaLink.TemplateEngine;
using ScadaLink.TemplateEngine.Services;
@@ -320,9 +321,16 @@ public class ManagementActor : ReceiveActor
private static async Task<object?> HandleCreateSite(IServiceProvider sp, CreateSiteCommand cmd)
{
var repo = sp.GetRequiredService<ISiteRepository>();
var site = new Site(cmd.Name, cmd.SiteIdentifier) { Description = cmd.Description };
var site = new Site(cmd.Name, cmd.SiteIdentifier)
{
Description = cmd.Description,
NodeAAddress = cmd.NodeAAddress,
NodeBAddress = cmd.NodeBAddress
};
await repo.AddSiteAsync(site);
await repo.SaveChangesAsync();
var commService = sp.GetService<CommunicationService>();
commService?.RefreshSiteAddresses();
return site;
}
@@ -333,8 +341,12 @@ public class ManagementActor : ReceiveActor
?? throw new InvalidOperationException($"Site with ID {cmd.SiteId} not found.");
site.Name = cmd.Name;
site.Description = cmd.Description;
site.NodeAAddress = cmd.NodeAAddress;
site.NodeBAddress = cmd.NodeBAddress;
await repo.UpdateSiteAsync(site);
await repo.SaveChangesAsync();
var commService = sp.GetService<CommunicationService>();
commService?.RefreshSiteAddresses();
return site;
}
@@ -348,6 +360,8 @@ public class ManagementActor : ReceiveActor
$"Cannot delete site {cmd.SiteId}: it has {instances.Count} instance(s).");
await repo.DeleteSiteAsync(cmd.SiteId);
await repo.SaveChangesAsync();
var commService = sp.GetService<CommunicationService>();
commService?.RefreshSiteAddresses();
return true;
}