fix(health): evict deleted sites from the aggregator on the periodic site refresh

This commit is contained in:
Joseph Doherty
2026-07-08 16:27:38 -04:00
parent 87c7255912
commit d962c77bb7
7 changed files with 99 additions and 3 deletions
@@ -10,6 +10,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Entities.Sites;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
using ZB.MOM.WW.ScadaBridge.Communication;
using ZB.MOM.WW.ScadaBridge.Communication.Actors;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;
namespace ZB.MOM.WW.ScadaBridge.Communication.Tests;
@@ -37,7 +38,37 @@ public class CentralCommunicationActorClientLifecycleTests : TestKit
private static SiteAddressCacheLoaded Load(string siteId, params string[] addrs) =>
new(new Dictionary<string, IReadOnlyList<string>>
{ [siteId] = addrs.ToList().AsReadOnly() });
{ [siteId] = addrs.ToList().AsReadOnly() },
new[] { siteId });
[Fact]
public void PeriodicRefresh_PrunesDeletedSites_FromHealthAggregator()
{
// PLAN-01 Task 18: the periodic site refresh feeds the currently-configured
// site ids to the aggregator so a deleted site is evicted within one
// refresh interval. Repo returns only "site-a".
var siteRepo = Substitute.For<ISiteRepository>();
siteRepo.GetAllSitesAsync(Arg.Any<CancellationToken>())
.Returns(new List<Site> { new("Site A", "site-a") });
var aggregator = Substitute.For<ICentralHealthAggregator>();
var services = new ServiceCollection();
services.AddScoped(_ => siteRepo);
services.AddSingleton(aggregator);
var provider = services.BuildServiceProvider();
var actor = Sys.ActorOf(Props.Create(() => new CentralCommunicationActor(
provider, new DefaultSiteClientFactory(), null)));
// Trigger the refresh (also fires at PreStart, but drive it explicitly so
// the assertion is deterministic). The load runs on a detached task and
// pipes SiteAddressCacheLoaded back to the actor, which then prunes.
actor.Tell(new RefreshSiteAddresses());
AwaitAssert(
() => aggregator.Received().PruneUnknownSites(
Arg.Is<IReadOnlyCollection<string>>(ids => ids.Contains("site-a"))),
TimeSpan.FromSeconds(3));
}
[Fact]
public void AddressEdit_RecreatesClient_WithoutRestartLoop()