64 lines
2.0 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|