Skip to content

Fix #8302 redis subscriptions with union payload fields#9274

Open
michaelstaib wants to merge 1 commit intomainfrom
mst/issue-8302
Open

Fix #8302 redis subscriptions with union payload fields#9274
michaelstaib wants to merge 1 commit intomainfrom
mst/issue-8302

Conversation

@michaelstaib
Copy link
Member

Fixes #8302

Summary

  • Adds a Redis integration regression test that reproduces a subscription payload containing a union-typed field on a parent object.
  • Adds a runtime-polymorphic JSON converter used by DefaultJsonMessageSerializer so interface/abstract members are serialized with runtime type metadata and deserialized back to concrete types.
  • Keeps deserialization guarded by assignability checks before materialization.

Repro Test Code

[Fact]
public async Task Subscribe_Union_Field_In_Payload()
{
    using var cts = new CancellationTokenSource(Timeout);
    await using var services = CreateServer(
        builder => builder
            .AddSubscriptionType<UnionPayloadSubscription>()
            .AddType<UnionTextMessage>()
            .AddType<UnionCodeMessage>()
            .ModifyOptions(o => o.StrictValidation = false));
    var sender = services.GetRequiredService<ITopicEventSender>();

    var result = await services.ExecuteRequestAsync(
        """
        subscription {
          onUnionPayload {
            message {
              __typename
              ... on UnionTextMessage {
                text
              }
            }
          }
        }
        """,
        cancellationToken: cts.Token);

    await using var responseStream = result.ExpectResponseStream();
    var responses = responseStream.ReadResultsAsync().ConfigureAwait(false);

    await sender.SendAsync(
        "OnUnionPayload",
        new UnionPayloadEnvelope
        {
            Message = new UnionTextMessage { Text = "from-redis" }
        },
        cts.Token);
    await sender.CompleteAsync("OnUnionPayload");

    var snapshot = new Snapshot();

    await foreach (var response in responses.WithCancellation(cts.Token).ConfigureAwait(false))
    {
        snapshot.Add(response);
    }

    snapshot.MatchInline(
        """
        {
          "data": {
            "onUnionPayload": {
              "message": {
                "__typename": "UnionTextMessage",
                "text": "from-redis"
              }
            }
          }
        }
        """);
}

Tests

  • dotnet test src/HotChocolate/Core/test/Subscriptions.Tests/HotChocolate.Subscriptions.Tests.csproj -f net8.0 --filter "FullyQualifiedName~DefaultJsonMessageSerializerTests.Serialize_And_Deserialize_DefaultMessage_With_Interface_Property" (Passed)
  • dotnet test src/HotChocolate/Core/test/Subscriptions.Redis.Tests/HotChocolate.Subscriptions.Redis.Tests.csproj -f net8.0 --filter "FullyQualifiedName~RedisIntegrationTests.Subscribe_Union_Field_In_Payload" (Passed)
  • dotnet test src/HotChocolate/Core/test/Subscriptions.Tests/HotChocolate.Subscriptions.Tests.csproj -f net9.0 --filter "FullyQualifiedName~DefaultJsonMessageSerializerTests.Serialize_And_Deserialize_DefaultMessage_With_Interface_Property" (Passed)
  • dotnet test src/HotChocolate/Core/test/Subscriptions.Redis.Tests/HotChocolate.Subscriptions.Redis.Tests.csproj -f net9.0 --filter "FullyQualifiedName~RedisIntegrationTests.Subscribe_Union_Field_In_Payload" (Passed)
  • dotnet test src/HotChocolate/Core/test/Subscriptions.Tests/HotChocolate.Subscriptions.Tests.csproj -f net10.0 --filter "FullyQualifiedName~DefaultJsonMessageSerializerTests.Serialize_And_Deserialize_DefaultMessage_With_Interface_Property" (Passed)
  • dotnet test src/HotChocolate/Core/test/Subscriptions.Redis.Tests/HotChocolate.Subscriptions.Redis.Tests.csproj -f net10.0 --filter "FullyQualifiedName~RedisIntegrationTests.Subscribe_Union_Field_In_Payload" (Passed)

@github-actions
Copy link
Contributor

Fusion Gateway Performance Results

Progress: 0/6 benchmarks completed — this report updates as each job finishes.

Simple Composite Query

Req/s Err%
Constant 2 (50 VUs) pending pending
Ramping 2 (0-500-0 VUs) pending pending
Response Times
Min Med Avg P90 P95 Max
Constant 2 pending pending pending pending pending pending
Ramping 2 pending pending pending pending pending pending

Deep Recursion Query

Req/s Err%
Constant 2 (50 VUs) pending pending
Ramping 2 (0-500-0 VUs) pending pending
Response Times
Min Med Avg P90 P95 Max
Constant 2 pending pending pending pending pending pending
Ramping 2 pending pending pending pending pending pending

Variable Batching Throughput

Req/s Err%
Constant 2 (50 VUs) pending pending
Ramping 2 (0-500-0 VUs) pending pending
Response Times
Min Med Avg P90 P95 Max
Constant 2 pending pending pending pending pending pending
Ramping 2 pending pending pending pending pending pending

Runner 2 = benchmarking-2

Run 22506364038 • Commit 287df5d • Fri, 27 Feb 2026 22:31:03 GMT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Union types using redis subscription do not send.

1 participant