Skip to content

Code smell: ModuleContextProvider accumulates scopes without cleanup #1477

@thomhurst

Description

@thomhurst

Location

  • File: src/ModularPipelines/Engine/ModuleContextProvider.cs
  • Lines: 10, 17-23

Problem

The ModuleContextProvider class maintains a list of service scopes that are never disposed:

private readonly List<IServiceScope> _scopes = new();

public IPipelineContext GetModuleContext()
{
    var serviceScope = _serviceProvider.CreateAsyncScope();
    _scopes.Add(serviceScope);
    return serviceScope.ServiceProvider.GetRequiredService<IPipelineContext>();
}

Why it's a problem

  1. Potential Resource Leak: Service scopes are added to the list but there's no clear disposal mechanism
  2. Memory Growth: The list grows unbounded during pipeline execution
  3. IScopeDisposer Interface: While the class implements IScopeDisposer, the GetScopes() method only returns the scopes - it doesn't dispose them
  4. Thread Safety: The List is not thread-safe, but GetModuleContext() could be called from multiple threads

Suggested Fix

  1. Make the class implement IDisposable or IAsyncDisposable
  2. Dispose all scopes when the provider is disposed
  3. Use a thread-safe collection like ConcurrentBag<IServiceScope>
internal class ModuleContextProvider : IPipelineContextProvider, IScopeDisposer, IAsyncDisposable
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ConcurrentBag<IServiceScope> _scopes = new();

    // ...

    public async ValueTask DisposeAsync()
    {
        foreach (var scope in _scopes)
        {
            if (scope is IAsyncDisposable asyncDisposable)
                await asyncDisposable.DisposeAsync();
            else
                scope.Dispose();
        }
    }
}

Category

  • Magic numbers/strings
  • DRY violation
  • SOLID violation
  • Resource leaks
  • Thread safety issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions