Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instance Hash Collisions for Large Service Registry #398

Open
jwoodmanbuildium opened this issue Apr 23, 2024 · 1 comment
Open

Instance Hash Collisions for Large Service Registry #398

jwoodmanbuildium opened this issue Apr 23, 2024 · 1 comment

Comments

@jwoodmanbuildium
Copy link

When an application has a large service graph (thousands of services), instance hash collisions occur, causing the wrong implementations to be resolved at runtime.

Exception info:

ClassName: System.InvalidCastException
Message: Unable to cast object of type '{ImplentationType}' to type '{ServiceType}'.

Stack Trace:
   at (Closure`6 , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
   at (Closure`9 , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
   at (ArrayClosure , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
   at (ArrayClosure , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
   at (ArrayClosure , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
   at (ArrayClosure , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
   at (Closure`1 , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Instances.GeneratedInstance.Resolve(Scope scope)
   at (ArrayClosure , Scope )
   at Lamar.IoC.Instances.GeneratedInstance.<>c__DisplayClass5_1.<BuildFuncResolver>b__0(Scope s)
   at Lamar.IoC.Scope.GetInstance(Type serviceType)
   at Lamar.IoC.Scope.GetInstance[T]()

I've added a workaround to recalculate the hash duplicates at startup by updating the instance names, but it would be nice if these collisions could be avoided by Lamar.

e.g. workaround

void MitigateHashCollisions(ServiceRegistry serviceRegistry)
{
    var hashCollisions = serviceRegistry
        .Select(x => x.ImplementationInstance)
        .OfType<Instance>()
        .GroupBy(x => x.Hash)
        .Where(x => x.Select(y => y.ServiceType).Distinct().Count() > 1);

    foreach (var collisionGroup in hashCollisions)
    {
        foreach (var lamarInstance in collisionGroup.Where(x => !x.IsExplicitlyNamed))
        {
            // Updating the name will result in a new hash
            lamarInstance.Name = $"Default_{lamarInstance.ServiceType.Name}";
        }
    }
}
@jeremydmiller
Copy link
Member

I'd be happy for a pull request on this one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants