JasperFx / lamar

Fast Inversion of Control Tool and Successor to StructureMap
https://jasperfx.github.io/lamar
MIT License
568 stars 119 forks source link

Two instances of a "Scoped" service that depends on a "Transient" service sometimes get the same instance of the transient service #156

Closed CodingGorilla closed 5 years ago

CodingGorilla commented 5 years ago

This is really hard to reproduce, but I can reproduce it very consistently with very specific circumstances. What I cannot determine is whether this is a Lamar issue, or an ASP.NET issue.

So I have Service1, which is explicitly registered as: For<IService1>().Use<Service1>().Scoped(). I also have an IService2 which is not explicitly register but is rather disconvered by convention and therefore has a default lifetime of transient. To reproduce this I have to get the application (it's an ASP.NET Core MVC API, no razor or anything) to process two requests literally at the same time. The way I can consistently reproduce this condition is to start the app up, and immediately fire two requests back to back, the requests are queued up while the application runs through the start up code, and then the are run back to back on separate threads.

What ends up happening is that the two instances of Service1 will both end up with the same reference to Service2. I injected the container into both Service1 and Service2 to dig a bit deeper and what I found is that the containers are different for the two instances of Service1, but both Service2 instances refer back to the same container, which is owned by one of the Service1 instances. This sort of leads me to think it's an ASP.Net problem, but this is all so convoluted I have no idea whether that's true or not.

Creating explicit registrations and making Service2 scoped as well solves the problem entirely. Maybe this is too much of an edge case to worry about, but we were getting this error pretty consistently from our API when running in our UI after a new build.

jeremydmiller commented 5 years ago

You can also control the lifetime scoping through attributes. Right now, I'm not seeing anything actionable here, and I don't have any possible explanation for how it's getting the same instance of a transient service.

CodingGorilla commented 5 years ago

Yea, I have tried vigorously to figure out how it's getting the same instance; that's what really concerns me because that should never happen. But for the life of me I cannot figure it out; I can however reproduce it like clockwork. I can't write a test for it though, because the only way I can reproduce it is to force two requests to be processed simultaneously, and I don't know how to do that in a unit test.