feat(controlplane): WithOtOpcUaControlPlaneSingletons registration extension (admin role)

This commit is contained in:
Joseph Doherty
2026-05-26 04:57:09 -04:00
parent dd122c4ca9
commit 52bf4b3371

View File

@@ -0,0 +1,91 @@
using Akka.Actor;
using Akka.Cluster.Hosting;
using Akka.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ZB.MOM.WW.OtOpcUa.Configuration;
using ZB.MOM.WW.OtOpcUa.ControlPlane.AdminOperations;
using ZB.MOM.WW.OtOpcUa.ControlPlane.Audit;
using ZB.MOM.WW.OtOpcUa.ControlPlane.Coordinators;
using ZB.MOM.WW.OtOpcUa.ControlPlane.Fleet;
using ZB.MOM.WW.OtOpcUa.ControlPlane.Redundancy;
namespace ZB.MOM.WW.OtOpcUa.ControlPlane;
public static class ServiceCollectionExtensions
{
public const string AdminRole = "admin";
public const string ConfigPublishSingletonName = "config-publish";
public const string AdminOperationsSingletonName = "admin-operations";
public const string AuditWriterSingletonName = "audit-writer";
public const string FleetStatusSingletonName = "fleet-status";
public const string RedundancyStateSingletonName = "redundancy-state";
/// <summary>
/// Registers all five admin-role cluster singletons + their proxies on the AkkaConfigurationBuilder.
/// Must be called against the same builder used by <c>AkkaHostedService</c> so the singletons
/// share the host's ActorSystem.
///
/// Wire from the fused Host's Program.cs:
/// <code>
/// builder.Services.AddAkka("otopcua", (ab, sp) =>
/// {
/// ab.WithRemoting(/* ... */).WithClustering(/* ... */);
/// ab.WithOtOpcUaControlPlaneSingletons();
/// });
/// </code>
/// </summary>
public static AkkaConfigurationBuilder WithOtOpcUaControlPlaneSingletons(this AkkaConfigurationBuilder builder)
{
var singletonOptions = new ClusterSingletonOptions { Role = AdminRole };
var proxyOptions = new ClusterSingletonOptions { Role = AdminRole };
builder.WithSingleton<ConfigPublishCoordinatorKey>(
ConfigPublishSingletonName,
(system, registry, resolver) =>
{
var dbFactory = resolver.GetService<IDbContextFactory<OtOpcUaConfigDbContext>>();
return ConfigPublishCoordinator.Props(dbFactory);
},
singletonOptions);
builder.WithSingleton<AdminOperationsActorKey>(
AdminOperationsSingletonName,
(system, registry, resolver) =>
{
var dbFactory = resolver.GetService<IDbContextFactory<OtOpcUaConfigDbContext>>();
var coordinator = registry.Get<ConfigPublishCoordinatorKey>();
return AdminOperationsActor.Props(dbFactory, coordinator);
},
singletonOptions);
builder.WithSingleton<AuditWriterActorKey>(
AuditWriterSingletonName,
(system, registry, resolver) =>
{
var dbFactory = resolver.GetService<IDbContextFactory<OtOpcUaConfigDbContext>>();
return AuditWriterActor.Props(dbFactory);
},
singletonOptions);
builder.WithSingleton<FleetStatusBroadcasterKey>(
FleetStatusSingletonName,
(system, registry, resolver) => FleetStatusBroadcaster.Props(),
singletonOptions);
builder.WithSingleton<RedundancyStateActorKey>(
RedundancyStateSingletonName,
(system, registry, resolver) => RedundancyStateActor.Props(),
singletonOptions);
return builder;
}
}
/// <summary>Marker key types used by <c>Akka.Hosting</c> to resolve singletons from the registry.</summary>
public sealed class ConfigPublishCoordinatorKey { }
public sealed class AdminOperationsActorKey { }
public sealed class AuditWriterActorKey { }
public sealed class FleetStatusBroadcasterKey { }
public sealed class RedundancyStateActorKey { }