Skip to content

Commit 0ccf3d4

Browse files
KSemenenkoclaude
andcommitted
Read MongoDB member endpoints and expect server-ordered link payloads
The benchmark host read published endpoints only for HTTP targets, so the MongoDB member address map received an empty list and both MongoDB cells failed while creating the session. The host now reads the TCP endpoints Aspire publishes for each MongoDB member. The integration link golden sorted keys ordinally, while the server writes a derived queue-graph link as from, to, label and attributes and keeps a caller's own payload text. The golden now builds the server's field order without serializing the production link type. Verification: solution build with -warnaserror, dotnet format verify and the governance check pass. FunctionalDatabaseGateTests, which commits documents, vectors, text, events, a queue message, a topic, a graph edge and time-series samples in one command and reads them back through SDK, MCP and SQL, passes locally for one node (6m 51s) and a three-node cluster (9m 50s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 336e6b5 commit 0ccf3d4

11 files changed

Lines changed: 44 additions & 15 deletions

File tree

‎benchmarks/KeyLoad.ComparisonHost/Configuration/IsolatedHostConstants.cs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ internal static class IsolatedHostConstants
2626
internal const string HelixDb = "HelixDB";
2727
internal const string Http = "http";
2828
internal const string Https = "https";
29+
internal const string Tcp = "tcp";
2930
internal const string RootPath = "/";
3031
internal const string Basic = "Basic";
3132
internal const string CredentialSeparator = ":";

‎benchmarks/KeyLoad.ComparisonHost/Configuration/RuntimeIsolatedHostSettings.cs‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ or IsolatedHostConstants.Mongo or IsolatedHostConstants.Kurrent
2323
var endpoints = target is IsolatedHostConstants.KeyLoad or IsolatedHostConstants.Qdrant or IsolatedHostConstants.Rabbit
2424
or IsolatedHostConstants.Neo4j or IsolatedHostConstants.OpenSearch or IsolatedHostConstants.Kurrent
2525
or IsolatedHostConstants.SurrealDb or IsolatedHostConstants.HelixDb
26-
? ReadEndpoints(configuration, selection.NodeCount) : ImmutableArray<Uri>.Empty;
26+
? ReadEndpoints(configuration, selection.NodeCount, tcp: false)
27+
: target == IsolatedHostConstants.Mongo ? ReadEndpoints(configuration, selection.NodeCount, tcp: true) : ImmutableArray<Uri>.Empty;
2728
var replicas = target == IsolatedHostConstants.Redis
2829
? ReadArray(configuration, IsolatedHostConstants.ReplicaConnections, selection.NodeCount - PrimaryReplicaCount) : ImmutableArray<string>.Empty;
2930
var authenticated = target is IsolatedHostConstants.Rabbit or IsolatedHostConstants.Neo4j or IsolatedHostConstants.SurrealDb;
@@ -39,7 +40,8 @@ or IsolatedHostConstants.SurrealDb or IsolatedHostConstants.HelixDb
3940
return new(image, connection, endpoints, replicas, user, password, apiKey, admin);
4041
}
4142

42-
private static ImmutableArray<Uri> ReadEndpoints(IConfiguration configuration, int count)
43+
// MongoDB members publish raw TCP endpoints; every other endpoint-bound target is an HTTP(S) origin.
44+
private static ImmutableArray<Uri> ReadEndpoints(IConfiguration configuration, int count, bool tcp)
4345
{
4446
const int EmptyUserInfoLength = 0;
4547
const int EmptyQueryLength = 0;
@@ -50,7 +52,8 @@ private static ImmutableArray<Uri> ReadEndpoints(IConfiguration configuration, i
5052
foreach (var value in values)
5153
{
5254
if (!Uri.TryCreate(value, UriKind.Absolute, out var endpoint)
53-
|| endpoint.Scheme is not (IsolatedHostConstants.Http or IsolatedHostConstants.Https)
55+
|| (tcp ? endpoint.Scheme != IsolatedHostConstants.Tcp
56+
: endpoint.Scheme is not (IsolatedHostConstants.Http or IsolatedHostConstants.Https))
5457
|| string.IsNullOrWhiteSpace(endpoint.Host) || endpoint.UserInfo.Length != EmptyUserInfoLength
5558
|| endpoint.Query.Length != EmptyQueryLength || endpoint.Fragment.Length != EmptyFragmentLength || endpoint.AbsolutePath != IsolatedHostConstants.RootPath)
5659
{
Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
1+
using System.Text.Json;
2+
13
namespace KeyLoad.IntegrationTests.DatabaseComposition;
24

3-
/// <summary>Independent ordinal-key golden for every public field of the Orleans link fixture.</summary>
5+
/// <summary>Independent golden for every public field of a queue graph link, in the field order the server writes.</summary>
6+
/// <remarks>The server serializes a derived link as from, to, label and attributes, and preserves a caller's own
7+
/// payload text exactly; this literal shape is built without serializing the production link type.</remarks>
48
internal static class DatabaseCompositionClusterPayload
59
{
6-
internal static string OrdinalGolden(QueueGraphLink link)
7-
=> FunctionalGateBoundJson.Serialize(link);
10+
internal static string Golden(QueueGraphLink link)
11+
=> JsonSerializer.Serialize(new
12+
{
13+
from = Reference(link.From),
14+
to = Reference(link.To),
15+
label = link.Label,
16+
attributesJson = link.AttributesJson
17+
}, JsonDefaults.Options);
18+
19+
private static object Reference(EntityRef reference)
20+
{
21+
var partition = new
22+
{
23+
tenantId = reference.Partition.TenantId,
24+
databaseId = reference.Partition.DatabaseId,
25+
transactionDomainId = reference.Partition.TransactionDomainId,
26+
partitionKey = reference.Partition.PartitionKey,
27+
atomicPartitionId = reference.Partition.AtomicPartitionId
28+
};
29+
return reference.Lifetime is { } lifetime
30+
? (object)new { partition, collection = reference.Collection, id = reference.Id, lifetime = new { incarnation = lifetime.Incarnation } }
31+
: new { partition, collection = reference.Collection, id = reference.Id };
32+
}
833
}

‎tests/KeyLoad.IntegrationTests/DatabaseComposition/Assertions/Links/DeclarativeReverseQuotaAssertions.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ private static async Task MessageAsync(RequestCqrsClusterCallers callers, Declar
7676
}
7777
var link = new QueueGraphLink(state.Scenario.First, state.Scenario.Second, RelationalSqlClusterTokens.EdgeLabel);
7878
var expected = new MessageInspection(new MessageMetadata(id, MessageState.Ready, NoAttempts,
79-
InitialVersion, sequence, null, null), DatabaseCompositionClusterPayload.OrdinalGolden(link), Headers);
79+
InitialVersion, sequence, null, null), DatabaseCompositionClusterPayload.Golden(link), Headers);
8080
await SqlClusterProtocol.EqualAsync(expected, actual);
8181
await SqlClusterProtocol.EqualAsync(expected, official);
8282
}

‎tests/KeyLoad.IntegrationTests/DatabaseComposition/Assertions/Links/TypedEndpointJoinReverseAssertions.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private static async Task MessageAsync(RequestCqrsClusterCallers admin, TypedEnd
9191
TypedEndpointJoinProtocol.To(state.Seed.Partition), TypedEndpointJoinProtocol.Label, TypedEndpointJoinProtocol.Attributes);
9292
var expected = new MessageInspection(new MessageMetadata(id, MessageState.Ready, NoAttempts,
9393
InitialVersion, sequence, null, null),
94-
DatabaseCompositionClusterPayload.OrdinalGolden(link), TypedEndpointJoinProtocol.Attributes);
94+
DatabaseCompositionClusterPayload.Golden(link), TypedEndpointJoinProtocol.Attributes);
9595
await SqlClusterProtocol.EqualAsync(expected, actual);
9696
await SqlClusterProtocol.EqualAsync(expected, official);
9797
}

‎tests/KeyLoad.IntegrationTests/DatabaseComposition/Assertions/Sql/CompositionSqlColdAssertions.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal static async Task OriginalAsync(RequestCqrsClusterCallers callers, Comp
2222
await Assert.That(actual.Derived.Metadata.State).IsEqualTo(MessageState.Ready);
2323
await Assert.That(actual.Derived.Metadata.Attempts).IsEqualTo(RelationalSqlClusterTokens.NoResults);
2424
await Assert.That(actual.Derived.Metadata.LeaseOwner).IsNull();
25-
await Assert.That(actual.Source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.OrdinalGolden(state.Link));
25+
await Assert.That(actual.Source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.Golden(state.Link));
2626
var traversal = new TraverseRequest(state.Scenario.Partition, RelationalSqlClusterTokens.Graph, state.Scenario.First);
2727
await SqlClusterProtocol.EqualAsync(state.Graph, (await McpCallerAssertions.SuccessAsync<global::KeyLoad.GraphTraversal>(
2828
await callers.Mcp.CallAsync(McpCallerTools.GraphTraverse, traversal, token))).Value);

‎tests/KeyLoad.IntegrationTests/DatabaseComposition/Assertions/TypedEndpoints/TypedEndpointJoinAssertions.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ internal static async Task LiteralAsync(TypedEndpointJoinModels models, Partitio
7575
};
7676
var link = new QueueGraphLink(new(partition, TypedEndpointJoinProtocol.FromCollection, fromId),
7777
TypedEndpointJoinProtocol.To(partition), TypedEndpointJoinProtocol.Label, TypedEndpointJoinProtocol.Attributes);
78-
await Assert.That(source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.OrdinalGolden(link));
78+
await Assert.That(source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.Golden(link));
7979
}
8080
var from = TypedEndpointJoinProtocol.From(partition);
8181
var to = TypedEndpointJoinProtocol.To(partition);
@@ -152,7 +152,7 @@ private static async Task MalformedSourceAsync(TypedEndpointJoinModels models, P
152152
await Assert.That(actual.Metadata.SafeFailureCode).IsNull();
153153
await Assert.That(actual.HeadersJson).IsEqualTo(TypedEndpointJoinProtocol.Attributes);
154154
var to = TypedEndpointJoinProtocol.To(partition);
155-
await Assert.That(actual.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.OrdinalGolden(
155+
await Assert.That(actual.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.Golden(
156156
new QueueGraphLink(to, to, TypedEndpointJoinProtocol.Label, TypedEndpointJoinProtocol.Attributes)));
157157
}
158158
}

‎tests/KeyLoad.IntegrationTests/DatabaseComposition/Cases/Database/DatabaseCompositionClusterTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ await SqlClusterProtocol.EqualAsync(graph, await SqlClusterProtocol.McpAsync<glo
9595
var source = await PublicReadAssertions.MessageAsync(await sdk.InspectAsync(scenario.Inspect(Message), cancellationToken));
9696
await Assert.That(source!.Metadata.State).IsEqualTo(MessageState.Ready);
9797
await Assert.That(source.Metadata.Attempts).IsEqualTo(RelationalSqlClusterTokens.NoResults);
98-
await Assert.That(source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.OrdinalGolden(link));
98+
await Assert.That(source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.Golden(link));
9999
await Assert.That(JsonSerializer.Deserialize<QueueGraphLink>(source.PayloadJson!, JsonDefaults.Options)).IsEqualTo(link);
100100
}
101101

‎tests/KeyLoad.IntegrationTests/DatabaseComposition/Cases/DeclarativeComposition/DeclarativeCompositionClusterTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ await SqlClusterProtocol.EqualAsync(graph, await SqlClusterProtocol.McpAsync<glo
126126
var source = await PublicReadAssertions.MessageAsync(await sdk.InspectAsync(scenario.Inspect(Message), cancellationToken));
127127
await Assert.That(source!.Metadata.State).IsEqualTo(MessageState.Ready);
128128
await Assert.That(source.Metadata.Attempts).IsEqualTo(RelationalSqlClusterTokens.NoResults);
129-
await Assert.That(source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.OrdinalGolden(link));
129+
await Assert.That(source.PayloadJson).IsEqualTo(DatabaseCompositionClusterPayload.Golden(link));
130130
await Assert.That(JsonSerializer.Deserialize<QueueGraphLink>(source.PayloadJson!, JsonDefaults.Options)).IsEqualTo(link);
131131
}
132132

‎tests/KeyLoad.IntegrationTests/DatabaseComposition/Scenarios/FunctionalGates/Queues/FunctionalGateQueueGraph.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal static async Task RunAsync(FunctionalGateContext ctx, CancellationToken
1717
var returnedId = returnPrefix + edgeId;
1818
var source = new QueueLaneRef(ctx.Partition, FunctionalGateQueues.Queue(P.SourceQueue));
1919
var target = new QueueLaneRef(ctx.Partition, FunctionalGateQueues.Queue(P.TargetQueue));
20-
var payload = DatabaseCompositionClusterPayload.OrdinalGolden(link);
20+
var payload = DatabaseCompositionClusterPayload.Golden(link);
2121
await SeedAsync(ctx, link, source, sourceId, payload, token);
2222
var original = await FunctionalGateQueueGraphQueue.ReadyAsync(ctx, source, sourceId, payload, token);
2323
await ForwardAsync(ctx, source, edgePrefix, edgeId, token);

0 commit comments

Comments
 (0)