Skip to content

Conversation

@bart-vmware
Copy link
Member

Description

Fixed crash during RabbitMQ connect:

System.InvalidCastException: 'Unable to cast object of type 'AsyncStateMachineBox`1[System.IDisposable,Steeltoe.Connectors.RabbitMQ.RabbitMQServiceCollectionExtensions+d__5]' to type 'RabbitMQ.Client.IConnection'.'

This happened because the connect callback returned a Task<IConnection>, whereas the connector is registered in the service container with IConnection. There are two solutions:

  1. Change the service registration from ConnectorFactory<RabbitMQOptions, IConnection> to ConnectorFactory<RabbitMQOptions, Task<IConnection>>, such that the call to connectorFactory.Get().GetConnection() needs to be awaited.
  2. Stick with the current API and synchronously wait for the task to complete before returning it.

This PR implements solution 2, because that doesn't require breaking the public API. I'm also unsure whether it's safe when the task is awaited concurrently.

Quality checklist

  • Your code complies with our Coding Style.
  • You've updated unit and/or integration tests for your change, where applicable.
  • You've updated documentation for your change, where applicable.
    If your change affects other repositories, such as Documentation, Samples and/or MainSite, add linked PRs here.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.
  • You've added required license files and/or file headers (explaining where the code came from with proper attribution), where code is copied from StackOverflow, a blog, or OSS.

@bart-vmware
Copy link
Member Author

This bug was introduced in #1459.

> System.InvalidCastException: 'Unable to cast object of type 'AsyncStateMachineBox`1[System.IDisposable,Steeltoe.Connectors.RabbitMQ.RabbitMQServiceCollectionExtensions+<CreateConnectionAsync>d__5]' to type 'RabbitMQ.Client.IConnection'.'

This happened because the connect callback returned a `Task<IConnection>`, whereas the connector is registered in the service container with `IConnection`. There are two solutions:

1. Change the service registration from `ConnectorFactory<RabbitMQOptions, IConnection>` to `ConnectorFactory<RabbitMQOptions, Task<IConnection>>`, such that the call to `connectorFactory.Get().GetConnection()` needs to be awaited.
2. Stick with the current API and synchronously wait for the task to complete before returning it.

This PR implements solution 2, because that doesn't require breaking the public API.
I'm also unsure whether it's safe when the task is awaited concurrently.
@bart-vmware bart-vmware marked this pull request as ready for review August 15, 2025 14:00
@bart-vmware bart-vmware requested a review from TimHess August 15, 2025 14:00
@github-actions
Copy link
Contributor

Summary - All Code Coverage (ubuntu-latest)

Line coverage Branch coverage

Assembly Line coverage Branch coverage
Steeltoe.Bootstrap.AutoConfiguration 97.4% 100%
Steeltoe.Common 85.6% 79.8%
Steeltoe.Common.Certificates 96.2% 85.2%
Steeltoe.Common.Hosting 84% 70%
Steeltoe.Common.Http 100% 85.2%
Steeltoe.Common.Logging 81.1% 41.6%
Steeltoe.Common.Net 64.5% 66.6%
Steeltoe.Configuration.Abstractions 97.8% 92.6%
Steeltoe.Configuration.CloudFoundry 99.1% 91.6%
Steeltoe.Configuration.ConfigServer 97.2% 91.5%
Steeltoe.Configuration.Encryption 97.6% 92.4%
Steeltoe.Configuration.Kubernetes.ServiceBindings 95.1% 89.3%
Steeltoe.Configuration.Placeholder 93.8% 84.7%
Steeltoe.Configuration.RandomValue 93.2% 90%
Steeltoe.Configuration.SpringBoot 98.4% 95.4%
Steeltoe.Connectors 93.9% 89.4%
Steeltoe.Connectors.EntityFrameworkCore 81.5% 75%
Steeltoe.Discovery.Configuration 90.4% 100%
Steeltoe.Discovery.Consul 98% 94.8%
Steeltoe.Discovery.Eureka 92.7% 85.6%
Steeltoe.Discovery.HttpClients 94% 95.4%
Steeltoe.Logging.Abstractions 99.4% 96.9%
Steeltoe.Logging.DynamicConsole 100% 95.4%
Steeltoe.Logging.DynamicSerilog 99.1% 95%
Steeltoe.Management.Abstractions 100% 100%
Steeltoe.Management.Endpoint 95.5% 89.1%
Steeltoe.Management.Prometheus 95.9% 91.6%
Steeltoe.Management.Tasks 100% ****
Steeltoe.Management.Tracing 100% 75%
Steeltoe.Security.Authentication.JwtBearer 100% 100%
Steeltoe.Security.Authentication.OpenIdConnect 73.8% 59%
Steeltoe.Security.Authorization.Certificate 96.3% 75%
Steeltoe.Security.DataProtection.Redis 100% ****

@sonarqubecloud
Copy link

@TimHess
Copy link
Member

TimHess commented Aug 15, 2025

  1. Change the service registration from ConnectorFactory<RabbitMQOptions, IConnection> to ConnectorFactory<RabbitMQOptions, Task<IConnection>>, such that the call to connectorFactory.Get().GetConnection() needs to be awaited.
  2. Stick with the current API and synchronously wait for the task to complete before returning it.

This PR implements solution 2, because that doesn't require breaking the public API. I'm also unsure whether it's safe when the task is awaited concurrently.

Sticking with the current API seems like the right thing to do, this approach seems right given where we're at with 4.0 and nothing jumps out at me as blockers for merge, but I have a couple questions before approving:

  • Is it awkward/unexpected to return the RMQ ConnectionFactory and have the caller open the connection on their own?
  • Would it be unreasonable to add a GetConnectionAsync variant for connectors that have an async way to open the connection?

@bart-vmware
Copy link
Member Author

  • Is it awkward/unexpected to return the RMQ ConnectionFactory and have the caller open the connection on their own?

Yes, that's an anti-pattern. See https://www.rabbitmq.com/dotnet-api-guide.html#connection-and-channel-lifespan.

  • Would it be unreasonable to add a GetConnectionAsync variant for connectors that have an async way to open the connection?

That's basically solution 1, but with a different method name. I'm not sure that awaiting concurrently is thread-safe.

Copy link
Member

@TimHess TimHess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bart-vmware bart-vmware merged commit 4e259f8 into main Aug 15, 2025
17 of 18 checks passed
@bart-vmware bart-vmware deleted the fix-rabbitmq-async branch August 15, 2025 15:32
@bart-vmware bart-vmware added Component/Connectors Issues related to Steeltoe connectors ReleaseLine/4.x Identified as a feature/fix for the 4.x release line labels Aug 15, 2025
@bart-vmware bart-vmware added this to the 4.0.0 milestone Aug 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component/Connectors Issues related to Steeltoe connectors ReleaseLine/4.x Identified as a feature/fix for the 4.x release line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants