Files
ScadaBridge/src/ScadaLink.CLI/ClusterConnection.cs
T

64 lines
2.0 KiB
C#

using System.Collections.Immutable;
using Akka.Actor;
using Akka.Cluster.Tools.Client;
using Akka.Configuration;
using ScadaLink.Commons.Messages.Management;
namespace ScadaLink.CLI;
public class ClusterConnection : IAsyncDisposable
{
private ActorSystem? _system;
private IActorRef? _clusterClient;
public async Task ConnectAsync(IReadOnlyList<string> contactPoints, TimeSpan timeout)
{
var seedNodes = string.Join(",", contactPoints.Select(cp => $"\"{cp}\""));
var config = ConfigurationFactory.ParseString($@"
akka {{
actor.provider = remote
remote.dot-netty.tcp {{
hostname = ""127.0.0.1""
port = 0
}}
}}
");
_system = ActorSystem.Create("scadalink-cli", config);
var initialContacts = contactPoints
.Select(cp => $"{cp}/system/receptionist")
.Select(path => ActorPath.Parse(path))
.ToImmutableHashSet();
var clientSettings = ClusterClientSettings.Create(_system)
.WithInitialContacts(initialContacts);
_clusterClient = _system.ActorOf(ClusterClient.Props(clientSettings), "cluster-client");
// Wait for connection by sending a ping
// ClusterClient doesn't have a direct "connected" signal, so we rely on the first Ask succeeding
await Task.CompletedTask;
}
public async Task<object> AskManagementAsync(ManagementEnvelope envelope, TimeSpan timeout)
{
if (_clusterClient == null) throw new InvalidOperationException("Not connected");
var response = await _clusterClient.Ask(
new ClusterClient.Send("/user/management", envelope),
timeout);
return response;
}
public async ValueTask DisposeAsync()
{
if (_system != null)
{
await CoordinatedShutdown.Get(_system).Run(CoordinatedShutdown.ClrExitReason.Instance);
_system = null;
}
}
}