feat(dcl): rename Configuration to PrimaryConfiguration, add BackupConfiguration and FailoverRetryCount

This commit is contained in:
Joseph Doherty
2026-03-22 08:18:31 -04:00
parent 5ca1be328c
commit 04af03980e
14 changed files with 31 additions and 20 deletions

View File

@@ -38,7 +38,7 @@ public static class DataConnectionCommands
var idOption = new Option<int>("--id") { Description = "Data connection ID", Required = true };
var nameOption = new Option<string>("--name") { Description = "Connection name", Required = true };
var protocolOption = new Option<string>("--protocol") { Description = "Protocol", Required = true };
var configOption = new Option<string?>("--configuration") { Description = "Configuration JSON" };
var configOption = new Option<string?>("--configuration") { Description = "Primary configuration JSON" };
var cmd = new Command("update") { Description = "Update a data connection" };
cmd.Add(idOption);
@@ -77,7 +77,7 @@ public static class DataConnectionCommands
var siteIdOption = new Option<int>("--site-id") { Description = "Site ID", Required = true };
var nameOption = new Option<string>("--name") { Description = "Connection name", Required = true };
var protocolOption = new Option<string>("--protocol") { Description = "Protocol (e.g. OpcUa)", Required = true };
var configOption = new Option<string?>("--configuration") { Description = "Connection configuration JSON" };
var configOption = new Option<string?>("--configuration") { Description = "Primary configuration JSON" };
var cmd = new Command("create") { Description = "Create a new data connection" };
cmd.Add(siteIdOption);

View File

@@ -100,7 +100,7 @@
_siteName = _sites.FirstOrDefault(s => s.Id == _formSiteId)?.Name ?? $"Site {_formSiteId}";
_formName = _editingConnection.Name;
_formProtocol = _editingConnection.Protocol;
_formConfiguration = _editingConnection.Configuration;
_formConfiguration = _editingConnection.PrimaryConfiguration;
}
}
catch (Exception ex)
@@ -124,14 +124,14 @@
{
_editingConnection.Name = _formName.Trim();
_editingConnection.Protocol = _formProtocol;
_editingConnection.Configuration = _formConfiguration?.Trim();
_editingConnection.PrimaryConfiguration = _formConfiguration?.Trim();
await SiteRepository.UpdateDataConnectionAsync(_editingConnection);
}
else
{
var conn = new DataConnection(_formName.Trim(), _formProtocol, _formSiteId)
{
Configuration = _formConfiguration?.Trim()
PrimaryConfiguration = _formConfiguration?.Trim()
};
await SiteRepository.AddDataConnectionAsync(conn);
}

View File

@@ -50,7 +50,7 @@
<td>@conn.Name</td>
<td><span class="badge bg-secondary">@conn.Protocol</span></td>
<td>@(_siteLookup.GetValueOrDefault(conn.SiteId)?.Name ?? $"Site {conn.SiteId}")</td>
<td class="text-muted small text-truncate" style="max-width: 300px;">@(conn.Configuration ?? "—")</td>
<td class="text-muted small text-truncate" style="max-width: 300px;">@(conn.PrimaryConfiguration ?? "—")</td>
<td>
<button class="btn btn-outline-primary btn-sm py-0 px-1 me-1"
@onclick='() => NavigationManager.NavigateTo($"/admin/data-connections/{conn.Id}/edit")'>Edit</button>

View File

@@ -6,7 +6,9 @@ public class DataConnection
public int SiteId { get; set; }
public string Name { get; set; }
public string Protocol { get; set; }
public string? Configuration { get; set; }
public string? PrimaryConfiguration { get; set; }
public string? BackupConfiguration { get; set; }
public int FailoverRetryCount { get; set; } = 3;
public DataConnection(string name, string protocol, int siteId)
{

View File

@@ -3,4 +3,6 @@ namespace ScadaLink.Commons.Messages.Artifacts;
public record DataConnectionArtifact(
string Name,
string Protocol,
string? ConfigurationJson);
string? PrimaryConfigurationJson,
string? BackupConfigurationJson,
int FailoverRetryCount = 3);

View File

@@ -2,6 +2,6 @@ namespace ScadaLink.Commons.Messages.Management;
public record ListDataConnectionsCommand(int? SiteId = null);
public record GetDataConnectionCommand(int DataConnectionId);
public record CreateDataConnectionCommand(int SiteId, string Name, string Protocol, string? Configuration);
public record UpdateDataConnectionCommand(int DataConnectionId, string Name, string Protocol, string? Configuration);
public record CreateDataConnectionCommand(int SiteId, string Name, string Protocol, string? PrimaryConfiguration);
public record UpdateDataConnectionCommand(int DataConnectionId, string Name, string Protocol, string? PrimaryConfiguration);
public record DeleteDataConnectionCommand(int DataConnectionId);

View File

@@ -43,9 +43,16 @@ public class DataConnectionConfiguration : IEntityTypeConfiguration<DataConnecti
.IsRequired()
.HasMaxLength(50);
builder.Property(d => d.Configuration)
builder.Property(d => d.PrimaryConfiguration)
.HasMaxLength(4000);
builder.Property(d => d.BackupConfiguration)
.HasMaxLength(4000);
builder.Property(d => d.FailoverRetryCount)
.IsRequired()
.HasDefaultValue(3);
builder.HasOne<Site>()
.WithMany()
.HasForeignKey(d => d.SiteId)

View File

@@ -102,7 +102,7 @@ public class ArtifactDeploymentService
// Map data connections
var dataConnectionArtifacts = dataConnections.Select(dc =>
new DataConnectionArtifact(dc.Name, dc.Protocol, dc.Configuration)).ToList();
new DataConnectionArtifact(dc.Name, dc.Protocol, dc.PrimaryConfiguration, dc.BackupConfiguration, dc.FailoverRetryCount)).ToList();
// Map SMTP configurations — use Host as the artifact name (matches SQLite PK on site)
var smtpArtifacts = smtpConfigurations.Select(smtp =>

View File

@@ -689,7 +689,7 @@ public class ManagementActor : ReceiveActor
private static async Task<object?> HandleCreateDataConnection(IServiceProvider sp, CreateDataConnectionCommand cmd, string user)
{
var repo = sp.GetRequiredService<ISiteRepository>();
var conn = new DataConnection(cmd.Name, cmd.Protocol, cmd.SiteId) { Configuration = cmd.Configuration };
var conn = new DataConnection(cmd.Name, cmd.Protocol, cmd.SiteId) { PrimaryConfiguration = cmd.PrimaryConfiguration };
await repo.AddDataConnectionAsync(conn);
await repo.SaveChangesAsync();
await AuditAsync(sp, user, "Create", "DataConnection", conn.Id.ToString(), conn.Name, conn);
@@ -703,7 +703,7 @@ public class ManagementActor : ReceiveActor
?? throw new InvalidOperationException($"DataConnection with ID {cmd.DataConnectionId} not found.");
conn.Name = cmd.Name;
conn.Protocol = cmd.Protocol;
conn.Configuration = cmd.Configuration;
conn.PrimaryConfiguration = cmd.PrimaryConfiguration;
await repo.UpdateDataConnectionAsync(conn);
await repo.SaveChangesAsync();
await AuditAsync(sp, user, "Update", "DataConnection", conn.Id.ToString(), conn.Name, conn);

View File

@@ -615,7 +615,7 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
foreach (var dc in command.DataConnections)
{
await _storage.StoreDataConnectionDefinitionAsync(
dc.Name, dc.Protocol, dc.ConfigurationJson);
dc.Name, dc.Protocol, dc.PrimaryConfigurationJson);
}
}

View File

@@ -185,7 +185,7 @@ public class SiteReplicationActor : ReceiveActor
if (command.DataConnections != null)
foreach (var dc in command.DataConnections)
await _storage.StoreDataConnectionDefinitionAsync(dc.Name, dc.Protocol, dc.ConfigurationJson);
await _storage.StoreDataConnectionDefinitionAsync(dc.Name, dc.Protocol, dc.PrimaryConfigurationJson);
if (command.SmtpConfigurations != null)
foreach (var smtp in command.SmtpConfigurations)

View File

@@ -90,7 +90,7 @@ public class FlatteningService
connections[attr.BoundDataConnectionName] = new ConnectionConfig
{
Protocol = conn.Protocol,
ConfigurationJson = conn.Configuration
ConfigurationJson = conn.PrimaryConfiguration
};
}
}

View File

@@ -104,7 +104,7 @@ public class SiteService
if (string.IsNullOrWhiteSpace(protocol))
return Result<DataConnection>.Failure("Protocol is required.");
var connection = new DataConnection(name, protocol, siteId) { Configuration = configuration };
var connection = new DataConnection(name, protocol, siteId) { PrimaryConfiguration = configuration };
await _repository.AddDataConnectionAsync(connection, cancellationToken);
await _repository.SaveChangesAsync(cancellationToken);
@@ -124,7 +124,7 @@ public class SiteService
connection.Name = name;
connection.Protocol = protocol;
connection.Configuration = configuration;
connection.PrimaryConfiguration = configuration;
await _repository.UpdateDataConnectionAsync(connection, cancellationToken);
await _repository.SaveChangesAsync(cancellationToken);

View File

@@ -200,7 +200,7 @@ public class FlatteningServiceTests
var connections = new Dictionary<int, DataConnection>
{
[100] = new("OPC-Server1", "OpcUa", 1) { Id = 100, Configuration = "opc.tcp://localhost:4840" }
[100] = new("OPC-Server1", "OpcUa", 1) { Id = 100, PrimaryConfiguration = "opc.tcp://localhost:4840" }
};
var result = _sut.Flatten(