refactor(host): central singletons via CentralSingletonRegistrar — outbox/audit-ingest gain drain tasks

This commit is contained in:
Joseph Doherty
2026-07-08 16:05:52 -04:00
parent c255ec31c9
commit f7b9d342e4
2 changed files with 78 additions and 205 deletions
@@ -42,6 +42,43 @@ public class CoordinatedShutdownTests
Assert.Contains("run-coordinated-shutdown-when-down = on", content);
}
[Fact]
public void AllCentralSingletons_RegisterThroughRegistrarWithDrain()
{
var hostProjectDir = FindHostProjectDirectory();
Assert.NotNull(hostProjectDir);
var content = File.ReadAllText(Path.Combine(hostProjectDir!, "Actors", "AkkaHostedService.cs"));
// Review 01 [Medium]: notification-outbox and audit-log-ingest were the
// only central singletons WITHOUT a cluster-leave drain task. All seven
// now go through CentralSingletonRegistrar.Start, which always adds the
// PhaseClusterLeave GracefulStop drain.
Assert.Contains("CentralSingletonRegistrar.Start(", content);
foreach (var name in new[] { "notification-outbox", "audit-log-ingest", "site-call-audit",
"audit-log-purge", "site-audit-reconciliation",
"kpi-history-recorder", "pending-deployment-purge" })
{
Assert.Contains($"\"{name}\"", content);
}
// No hand-rolled ClusterSingletonManager registrations remain in the
// CENTRAL branch. The only two left are the SITE singletons
// (deployment-manager, event-log-handler), which stay hand-rolled because
// they are role-scoped (.WithRole(siteRole)).
Assert.Equal(2, CountOccurrences(content, "ClusterSingletonManager.Props("));
}
private static int CountOccurrences(string haystack, string needle)
{
int count = 0, i = 0;
while ((i = haystack.IndexOf(needle, i, StringComparison.Ordinal)) >= 0)
{
count++;
i += needle.Length;
}
return count;
}
private static string? FindHostProjectDirectory()
{
var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;