Resolve KafkaHealthCheck from container (#6035)
Description
This PR addresses a memory leak in the Aspire.Confluent.Kafka component caused by the creation of a new KafkaHealthCheck instance on each health check execution and the lack of proper disposal. The fix ensures that KafkaHealthCheck is registered as a singleton in the ServiceCollection, allowing reuse of the same instance for health checks. This change prevents unnecessary object creation and ensures proper resource management by allowing disposal of the KafkaHealthCheck instance when needed.
Fixes #6035
Checklist
- Is this feature complete?
- [x] Yes. Ready to ship.
- [ ] No. Follow-up changes expected.
- Are you including unit tests for the changes and scenario tests if relevant?
- [ ] Yes
- [x] No
- Did you add public API?
- [ ] Yes
- If yes, did you have an API Review for it?
- [ ] Yes
- [ ] No
- Did you add
<remarks />and<code />elements on your triple slash comments?- [ ] Yes
- [ ] No
- If yes, did you have an API Review for it?
- [x] No
- [ ] Yes
- Does the change make any security assumptions or guarantees?
- [ ] Yes
- If yes, have you done a threat model and had a security review?
- [ ] Yes
- [ ] No
- If yes, have you done a threat model and had a security review?
- [x] No
- [ ] Yes
- Does the change require an update in our Aspire docs?
- [ ] Yes
- Link to aspire-docs issue:
- [x] No
- [ ] Yes
Microsoft Reviewers: Open in CodeFlow
@dotnet-policy-service agree
Is there any way to test this?
Do we have a similar bad pattern being followed in other integrations?
Is there any way to test this?
I don't see any possibility to test it, but if you suggest something - I can implement it.
Do we have a similar bad pattern being followed in other integrations?
I found these:
- Aspire.RabbitMQ.Client: https://github.com/dotnet/aspire/blob/6c48677f422978e9b67f56803bba587e3cce3efc/src/Components/Aspire.RabbitMQ.Client/AspireRabbitMQExtensions.cs#L132
- Aspire.Seq: https://github.com/dotnet/aspire/blob/6c48677f422978e9b67f56803bba587e3cce3efc/src/Components/Aspire.Seq/AspireSeqExtensions.cs#L75
Any updates?
@radical @eerhardt can we proceed with the next step?
@mitchdenny - this same issue exists in the Hosting layer:
https://github.com/dotnet/aspire/blob/84b2dee614249729589f4d2d567850dd682e2474/src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs#L57-L64
I'm going to merge this PR, but we should get an issue written up for the Hosting side as well.
Do we have a similar bad pattern being followed in other integrations?
I found these:
- Aspire.RabbitMQ.Client: https://github.com/dotnet/aspire/blob/6c48677f422978e9b67f56803bba587e3cce3efc/src/Components/Aspire.RabbitMQ.Client/AspireRabbitMQExtensions.cs#L132
- Aspire.Seq: https://github.com/dotnet/aspire/blob/6c48677f422978e9b67f56803bba587e3cce3efc/src/Components/Aspire.Seq/AspireSeqExtensions.cs#L75
RabbitMQ is fine since it reuses the IConnection that is put into DI. So nothing expensive gets created per health check execution.
A SeqHealthCheck creates a new HttpClient every time. While not great to create new HttpClient instances, they will be GC'd, so there isn't really a leak there either.