feat(config): migration AddClusterNodeTransportPorts
Additive only — two AddColumn ops, no AlterColumn, so no accumulated model drift is riding along with this change: ALTER TABLE [ClusterNode] ADD [AkkaPort] int NOT NULL DEFAULT 4053; ALTER TABLE [ClusterNode] ADD [GrpcPort] int NULL; Adds a third test covering the DB-side default specifically. The entity round-trip cannot see it: ClusterNode.AkkaPort's CLR initializer is also 4053, so that assertion passes with the mapping default deleted. The new test inserts through raw SQL with the column omitted, so only the schema can supply the value — verified by setting defaultValue: 0, which turns exactly that one test red and leaves the other two green. Configuration.Tests 95/95. Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
@@ -49,6 +49,41 @@ public sealed class ClusterNodeTransportPortsTests(SchemaComplianceFixture fixtu
|
||||
defaulted.GrpcPort.ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the <b>DB-side</b> default on <c>AkkaPort</c> — the migration's
|
||||
/// <c>defaultValue: 4053</c>, which is what rows created before the column existed inherit.
|
||||
/// The entity round-trip above cannot see this: <see cref="ClusterNode.AkkaPort"/>'s CLR
|
||||
/// initializer is also 4053, so that assertion passes with the mapping default deleted. This
|
||||
/// one inserts through raw SQL with the column omitted, so only the schema can supply the value.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task AkkaPort_has_a_DB_side_default_of_4053()
|
||||
{
|
||||
await using var ctx = NewContext();
|
||||
var clusterId = await SeedClusterAsync(ctx);
|
||||
|
||||
await using (var conn = fixture.OpenConnection())
|
||||
{
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = """
|
||||
INSERT INTO dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort,
|
||||
ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
|
||||
VALUES (@nodeId, @clusterId, @host, 4840, 8081, @uri, 200, 1, 'raw-sql');
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("@nodeId", $"{clusterId}-raw:4053");
|
||||
cmd.Parameters.AddWithValue("@clusterId", clusterId);
|
||||
cmd.Parameters.AddWithValue("@host", $"{clusterId}-raw");
|
||||
cmd.Parameters.AddWithValue("@uri", $"urn:OtOpcUa:{clusterId}-raw");
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
await using var read = NewContext();
|
||||
var row = await read.ClusterNodes.AsNoTracking()
|
||||
.SingleAsync(n => n.NodeId == $"{clusterId}-raw:4053");
|
||||
row.AkkaPort.ShouldBe(4053);
|
||||
row.GrpcPort.ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the columns are queryable server-side — Phase 2's contact-point refresh selects
|
||||
/// them in SQL rather than materialising every node, so a client-side-evaluation regression
|
||||
@@ -98,7 +133,9 @@ public sealed class ClusterNodeTransportPortsTests(SchemaComplianceFixture fixtu
|
||||
Name = clusterId,
|
||||
Enterprise = "zb",
|
||||
Site = "ports-test",
|
||||
// CK_ServerCluster_RedundancyMode_NodeCount: Warm/Hot require exactly 2 nodes.
|
||||
RedundancyMode = RedundancyMode.Warm,
|
||||
NodeCount = 2,
|
||||
CreatedBy = nameof(ClusterNodeTransportPortsTests),
|
||||
});
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
Reference in New Issue
Block a user