feat(dcl): extend CreateConnectionCommand with backup config and failover retry count
Update CreateConnectionCommand to carry PrimaryConnectionDetails, BackupConnectionDetails, and FailoverRetryCount. Update all callers: DataConnectionManagerActor, DataConnectionActor, DeploymentManagerActor, FlatteningService, and ConnectionConfig. The actor stores both configs but continues using primary only — failover logic comes in Task 3.
This commit is contained in:
@@ -7,4 +7,6 @@ namespace ScadaLink.Commons.Messages.DataConnection;
|
||||
public record CreateConnectionCommand(
|
||||
string ConnectionName,
|
||||
string ProtocolType,
|
||||
IDictionary<string, string> ConnectionDetails);
|
||||
IDictionary<string, string> PrimaryConnectionDetails,
|
||||
IDictionary<string, string>? BackupConnectionDetails = null,
|
||||
int FailoverRetryCount = 3);
|
||||
|
||||
@@ -33,6 +33,8 @@ public sealed record ConnectionConfig
|
||||
{
|
||||
public string Protocol { get; init; } = string.Empty;
|
||||
public string? ConfigurationJson { get; init; }
|
||||
public string? BackupConfigurationJson { get; init; }
|
||||
public int FailoverRetryCount { get; init; } = 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -61,6 +61,9 @@ public class DataConnectionActor : UntypedActor, IWithStash, IWithTimers
|
||||
private int _resolvedTags;
|
||||
|
||||
private readonly IDictionary<string, string> _connectionDetails;
|
||||
private readonly IDictionary<string, string> _primaryConfig;
|
||||
private readonly IDictionary<string, string>? _backupConfig;
|
||||
private readonly int _failoverRetryCount;
|
||||
|
||||
/// <summary>
|
||||
/// Captured Self reference for use from non-actor threads (event handlers, callbacks).
|
||||
@@ -73,13 +76,18 @@ public class DataConnectionActor : UntypedActor, IWithStash, IWithTimers
|
||||
IDataConnection adapter,
|
||||
DataConnectionOptions options,
|
||||
ISiteHealthCollector healthCollector,
|
||||
IDictionary<string, string>? connectionDetails = null)
|
||||
IDictionary<string, string>? primaryConfig = null,
|
||||
IDictionary<string, string>? backupConfig = null,
|
||||
int failoverRetryCount = 3)
|
||||
{
|
||||
_connectionName = connectionName;
|
||||
_adapter = adapter;
|
||||
_options = options;
|
||||
_healthCollector = healthCollector;
|
||||
_connectionDetails = connectionDetails ?? new Dictionary<string, string>();
|
||||
_primaryConfig = primaryConfig ?? new Dictionary<string, string>();
|
||||
_backupConfig = backupConfig;
|
||||
_failoverRetryCount = failoverRetryCount;
|
||||
_connectionDetails = _primaryConfig;
|
||||
}
|
||||
|
||||
protected override void PreStart()
|
||||
|
||||
@@ -45,10 +45,13 @@ public class DataConnectionManagerActor : ReceiveActor
|
||||
}
|
||||
|
||||
// WP-34: Factory creates the correct adapter based on protocol type
|
||||
var adapter = _factory.Create(command.ProtocolType, command.ConnectionDetails);
|
||||
var adapter = _factory.Create(command.ProtocolType, command.PrimaryConnectionDetails);
|
||||
|
||||
var props = Props.Create(() => new DataConnectionActor(
|
||||
command.ConnectionName, adapter, _options, _healthCollector, command.ConnectionDetails));
|
||||
command.ConnectionName, adapter, _options, _healthCollector,
|
||||
command.PrimaryConnectionDetails,
|
||||
command.BackupConnectionDetails,
|
||||
command.FailoverRetryCount));
|
||||
|
||||
// Sanitize name for Akka actor path (replace spaces and invalid chars)
|
||||
var actorName = new string(command.ConnectionName
|
||||
|
||||
@@ -422,7 +422,7 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
|
||||
if (_createdConnections.Contains(name))
|
||||
continue;
|
||||
|
||||
var connectionDetails = new Dictionary<string, string>();
|
||||
var primaryDetails = new Dictionary<string, string>();
|
||||
if (!string.IsNullOrEmpty(connConfig.ConfigurationJson))
|
||||
{
|
||||
try
|
||||
@@ -431,14 +431,29 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
|
||||
using var doc = System.Text.Json.JsonDocument.Parse(connConfig.ConfigurationJson);
|
||||
foreach (var prop in doc.RootElement.EnumerateObject())
|
||||
{
|
||||
connectionDetails[prop.Name] = prop.Value.ToString();
|
||||
primaryDetails[prop.Name] = prop.Value.ToString();
|
||||
}
|
||||
}
|
||||
catch { /* Ignore parse errors */ }
|
||||
}
|
||||
|
||||
Dictionary<string, string>? backupDetails = null;
|
||||
if (!string.IsNullOrEmpty(connConfig.BackupConfigurationJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
backupDetails = new Dictionary<string, string>();
|
||||
using var doc = System.Text.Json.JsonDocument.Parse(connConfig.BackupConfigurationJson);
|
||||
foreach (var prop in doc.RootElement.EnumerateObject())
|
||||
{
|
||||
backupDetails[prop.Name] = prop.Value.ToString();
|
||||
}
|
||||
}
|
||||
catch { backupDetails = null; /* Ignore parse errors */ }
|
||||
}
|
||||
|
||||
_dclManager.Tell(new Commons.Messages.DataConnection.CreateConnectionCommand(
|
||||
name, connConfig.Protocol, connectionDetails));
|
||||
name, connConfig.Protocol, primaryDetails, backupDetails, connConfig.FailoverRetryCount));
|
||||
|
||||
_createdConnections.Add(name);
|
||||
_logger.LogInformation(
|
||||
|
||||
@@ -90,7 +90,9 @@ public class FlatteningService
|
||||
connections[attr.BoundDataConnectionName] = new ConnectionConfig
|
||||
{
|
||||
Protocol = conn.Protocol,
|
||||
ConfigurationJson = conn.PrimaryConfiguration
|
||||
ConfigurationJson = conn.PrimaryConfiguration,
|
||||
BackupConfigurationJson = conn.BackupConfiguration,
|
||||
FailoverRetryCount = conn.FailoverRetryCount
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class DataConnectionManagerActorTests : TestKit
|
||||
new DataConnectionManagerActor(_mockFactory, _options, _mockHealthCollector)));
|
||||
|
||||
manager.Tell(new CreateConnectionCommand(
|
||||
"conn1", "OpcUa", new Dictionary<string, string>()));
|
||||
"conn1", "OpcUa", new Dictionary<string, string>(), null, 3));
|
||||
|
||||
// Factory should have been called
|
||||
AwaitCondition(() =>
|
||||
|
||||
Reference in New Issue
Block a user