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
@@ -473,6 +473,27 @@ public class CentralHealthAggregatorTests
Assert.False(aggregator.GetSiteState("site-a")!.IsMetricsStale);
}
/// <summary>
/// Review 01 [Low]: <c>_siteStates</c> only ever grew — a site deleted from
/// configuration remained a permanently-offline dashboard tile (and a KPI
/// sample source) forever. Pruning against the known-site set evicts it; the
/// synthetic central id is always retained.
/// </summary>
[Fact]
public void PruneUnknownSites_RemovesDeletedSites_KeepsKnownAndCentral()
{
var (aggregator, _) = NewAggregator();
aggregator.ProcessReport(MakeReport("site-a", 1));
aggregator.ProcessReport(MakeReport("site-b", 1));
aggregator.ProcessReport(MakeReport(CentralHealthReportLoop.CentralSiteId, 1));
aggregator.PruneUnknownSites(new[] { "site-a" });
Assert.NotNull(aggregator.GetSiteState("site-a"));
Assert.Null(aggregator.GetSiteState("site-b"));
Assert.NotNull(aggregator.GetSiteState(CentralHealthReportLoop.CentralSiteId)); // synthetic id always kept
}
/// <summary>
/// Review 01 underdeveloped #7: "when did the site drop" was unanswerable.
/// Every online↔offline flip stamps <see cref="SiteHealthState.LastStatusChangeAt"/>.
@@ -27,6 +27,7 @@ public class CentralHealthReportLoopTests
public IReadOnlyDictionary<string, SiteHealthState> GetAllSiteStates() =>
new Dictionary<string, SiteHealthState>();
public SiteHealthState? GetSiteState(string siteId) => null;
public void PruneUnknownSites(IReadOnlyCollection<string> knownSiteIds) { }
}
/// <summary>
@@ -256,6 +257,7 @@ public class CentralHealthReportLoopTests
public IReadOnlyDictionary<string, SiteHealthState> GetAllSiteStates() =>
new Dictionary<string, SiteHealthState>();
public SiteHealthState? GetSiteState(string siteId) => null;
public void PruneUnknownSites(IReadOnlyCollection<string> knownSiteIds) { }
}
[Fact]
@@ -166,5 +166,8 @@ public class SiteHealthKpiSampleSourceTests
public void MarkHeartbeat(string siteId, DateTimeOffset receivedAt) =>
throw new NotSupportedException();
public void PruneUnknownSites(IReadOnlyCollection<string> knownSiteIds) =>
throw new NotSupportedException();
}
}