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;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
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";
///
/// Registers all five admin-role cluster singletons + their proxies on the AkkaConfigurationBuilder.
/// Must be called against the same builder used by AkkaHostedService so the singletons
/// share the host's ActorSystem.
///
/// The Akka configuration builder.
/// The builder for fluent chaining.
///
/// Wire from the fused Host's Program.cs:
///
/// builder.Services.AddAkka("otopcua", (ab, sp) =>
/// {
/// ab.WithRemoting(/* ... */).WithClustering(/* ... */);
/// ab.WithOtOpcUaControlPlaneSingletons();
/// });
///
///
public static AkkaConfigurationBuilder WithOtOpcUaControlPlaneSingletons(this AkkaConfigurationBuilder builder)
{
var singletonOptions = new ClusterSingletonOptions { Role = AdminRole };
var proxyOptions = new ClusterSingletonOptions { Role = AdminRole };
builder.WithSingleton(
ConfigPublishSingletonName,
(system, registry, resolver) =>
{
var dbFactory = resolver.GetService>();
return ConfigPublishCoordinator.Props(dbFactory);
},
singletonOptions);
builder.WithSingleton(
AdminOperationsSingletonName,
(system, registry, resolver) =>
{
var dbFactory = resolver.GetService>();
var coordinator = registry.Get();
var probes = resolver.GetService>() ?? Enumerable.Empty();
return AdminOperationsActor.Props(dbFactory, coordinator, probes);
},
singletonOptions);
builder.WithSingleton(
AuditWriterSingletonName,
(system, registry, resolver) =>
{
var dbFactory = resolver.GetService>();
return AuditWriterActor.Props(dbFactory);
},
singletonOptions);
builder.WithSingleton(
FleetStatusSingletonName,
(system, registry, resolver) => FleetStatusBroadcaster.Props(),
singletonOptions);
builder.WithSingleton(
RedundancyStateSingletonName,
(system, registry, resolver) => RedundancyStateActor.Props(),
singletonOptions);
return builder;
}
}
/// Marker key types used by Akka.Hosting to resolve singletons from the registry.
public sealed class ConfigPublishCoordinatorKey { }
public sealed class AdminOperationsActorKey { }
public sealed class AuditWriterActorKey { }
public sealed class FleetStatusBroadcasterKey { }
public sealed class RedundancyStateActorKey { }