feat: add HTTP Management API, migrate CLI from Akka ClusterClient to HTTP

Replace the CLI's Akka.NET ClusterClient transport with a simple HTTP client
targeting a new POST /management endpoint on the Central Host. The endpoint
handles Basic Auth, LDAP authentication, role resolution, and ManagementActor
dispatch in a single round-trip — eliminating the CLI's Akka, LDAP, and
Security dependencies.

Also fixes DCL ReSubscribeAll losing subscriptions on repeated reconnect by
deriving the tag list from _subscriptionsByInstance instead of _subscriptionIds.
This commit is contained in:
Joseph Doherty
2026-03-20 23:55:31 -04:00
parent 7740a3bcf9
commit 1a540f4f0a
38 changed files with 863 additions and 758 deletions

View File

@@ -483,11 +483,18 @@ public class DataConnectionActor : UntypedActor, IWithStash, IWithTimers
private void ReSubscribeAll()
{
_log.Info("[{0}] Re-subscribing {1} tags after reconnect", _connectionName, _subscriptionIds.Count);
// Derive tag list from _subscriptionsByInstance (durable source of truth),
// not _subscriptionIds which gets cleared and is only repopulated on success.
var allTags = _subscriptionsByInstance.Values
.SelectMany(tags => tags)
.Distinct()
.ToList();
_log.Info("[{0}] Re-subscribing {1} tags after reconnect", _connectionName, allTags.Count);
var self = Self;
var allTags = _subscriptionIds.Keys.ToList();
_subscriptionIds.Clear();
_unresolvedTags.Clear();
_resolvedTags = 0;
foreach (var tagPath in allTags)
@@ -535,6 +542,16 @@ public class DataConnectionActor : UntypedActor, IWithStash, IWithTimers
{
_log.Debug("[{0}] Tag resolution still failing for {1}: {2}",
_connectionName, msg.TagPath, msg.Error);
// Track as unresolved so periodic retry picks it up
if (_unresolvedTags.Add(msg.TagPath))
{
Timers.StartPeriodicTimer(
"tag-resolution-retry",
new RetryTagResolution(),
_options.TagResolutionRetryInterval,
_options.TagResolutionRetryInterval);
}
}
private void HandleTagValueReceived(TagValueReceived msg)