-
Notifications
You must be signed in to change notification settings - Fork 449
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
Subtle differences in DI between WebJobs.Script.WebHost and Microsoft.Azure.WebJobs/Microsoft.Extensions.DependencyInjection #3399
Comments
+1 on this issue. I've spent a while investigating DbContext exceptions because of this. My case is similar in that each MediatR handler instance receives the same DbContext even though the Handler instance is unique and is called from a unique service scope. Thanks @ielcoro for identifying the root cause. |
Using the same pattern and libraries. Is this still an active issue? |
@jtemperv Yes, that line hasn't changed, it's still and issue, and I think it will not be resolved until this is done at the webjobs-sdk level first: Azure/azure-webjobs-sdk#2078 and then they start adapting those changes to azure-functions |
@ielcoro -- can you try the scoped scenario again? Scoped services weren't supported until this PR went in a few weeks ago: Azure/azure-webjobs-sdk#2133 |
@brettsam Thanks for looking into this. Tried, now scoped services work BUT the issue with scoped delegate dependencies is still happening. I created a sample repo here: https://github.com/ielcoro/ScopedDIDemo When the scoped service is a dependency of a registered factory, it is injected as a Singleton. That is happening because in this line azure-functions-host/src/WebJobs.Script.WebHost/DependencyInjection/DryIoc/DryIocAdapter.cs Line 156 in 5294afc
The good news is that, the first behavior difference ("A constructor parameter dependency is not registerd with DI" has been fixed, and now it throws like the builtin one. However, what worries me most, is that the longer the functions runtime keeps building on top of a different IOC library, instead of building on top of using .NET Core one (Microsoft.Extensions.DependencyInjection), more of this subtle issues could appear, specially in complex .net ecosystem libraries. Those differences can make both hard to migrate existing apps to functions and the functions framework itself costly to mantain, as customers report weird issues when using libraries like EF, Mediator, Health and many others. |
Just want to +1 this comment from @ielcoro
|
I'm also using MediatR and run into DbContext errors -- exactly as @ielcoro described above. 🙏Hopefully this will be addressed in the next release as mentioned in Dependency Injection support for Functions #3736 ?
[Edit] Seeing activity in #3736 maybe @fabiocav can drop a comment here? |
+1 blocked on the same issue |
I have the same issue with no usage of a Delegate Factory. I think this issue is just with scoped services in general. I'm not exactly sure what causes them to get treated as a singleton but this is blocking us. |
@fabiocav @jeffhollan any update? |
@espray apologies for the delay on providing an update. We'll triage this again today (as this wasn't addressed on the sprint it was assigned to) so we can provide an update ASAP. |
@fabiocav Yes please and thank you very much! :) We have so much code in our project currently that just does the DI and we have been looking forward to removing it. |
ugh, we have just hit this issue as well. We are really trying to use the power of azure functions in our current sprint. |
@jwisener because of this issue, I would recommend using attribute/binding DI and NOT the AzFunc/WebJob DI. Been using attribute/binding DI for better part of a year for a multi-tenant SaaS product with out any problems. https://github.com/espray/azure-webjobs-sdk-extensions |
@espray thanks for the links , I will try to do that. Currently we are attempting to use MediatR for events & handlers via domain events for transnational saving/publishing. The problem I'm encountering is when mediatR calls the eventhanlders the EF Context that is injected is not the right one, it seems like it's a new one (or maybe the singleton, I am still not sure yet). Anyway, we lose any data changes that were made in the event handler run. (in our case adds that occured to the dbcontext). |
@fabiocav @jeffhollan any update? |
@espray this is something that is high priority on our list. As soon as there's an update, I'll keep providing updates here, so you won't miss if you're following the issue. I'm hoping to have more details by the end of the week. |
🙏 🙏 🙏 🙏 🙏 Please be that Side Thoughts: So awesome seeing people using MediatR + AzFunctions |
Just to provide an udpate, as promised (since I'll also be out for a couple of days). We have a fix for this in validation right now. Because of the nature of the issue, full validation may not be completed before we cut the next release (which happens early next week), so it's possible that it wouldn't be on the next drop, but on the following one. If that happens, we'll investigate the possibility of making this available for validation on Azure with an opt-in runtime version. |
@fabiocav thanks for the update. I'll check this out asap. Enjoy your holidays! |
Having followed your advice, starting such a project yields the following startup:
But I'm guessing I want this for the pre-release version, because as you say this branch https://github.com/Azure/azure-functions-host/tree/asynscopeccontext is not yet merged:
Confused. What host process should be running this? I've Do I need to @meixger , @jtemperv are you able to clarify at all? Thanks update: In my ignorance, I thought maybe specifying Eventually I settled on copying the base Dockerfile at https://github.com/Azure/azure-functions-docker/blob/master/host/2.0/stretch/amd64/base.Dockerfile and customised it to build commit 7fd035c - then published my function library into it and went from there. Attempting to run a prerelease |
@t-l-k You are right - as of now it doesn't work anymore on my machine - evidently because the Function Runtime auto updated. I'm was able to configure it manually and now i get this version information on startup:
|
@meixger thanks, this works for me now also. I hadn't realised there was a prerelease build for |
@meixger We just did the test and it works, but is has to be version Azure.Functions.Cli.win-x64.2.7.1513. Later versions don't work (tested with Azure.Functions.Cli.win-x64.2.7.1575). |
@fabiocav tested and confirmed, the fix works. Looking forward to see this becoming available in consumption plans. :) thanks for the effort! |
Has anyone managed to get this working hosted? It works fine in localhost containers and the patched
Then updating the SDK to
Is there some sort of integrity check on the images when hosted in Azure? I'm puzzled why it appeared to momentarily work in (2), but alas I may just have been fooled by a possible cached result. I thought Docker might be the easier approach here, and allows me to keep consistent across every environment and dev/test workstations. I'll try an AppService tomorrow. Anybody else have luck? I've a lot of code needing QA cycles in a deployed environment. UPDATE: So it definitely does work in an AppService. When running as a container, the detailed diagnostic logging in Kudu's Log Stream (had to enable debug level logging as per .NET Core logging configuration) just reported that "0 functions were found". They were definitely there though, and the image worked locally. Probably some kind of integrity check? Couldn't see anything in The advantage of that containerised Linux plan is the sweet 66% discount ... but alas, expensive AppServices it is. |
Is the deployment still planned for early September ? Looking forward to using this in production. |
Just a heads up, have been working with this patched As it's the end of the week, I haven't yet debugged the issue fully, but my early observation appears to indicate that a number of What's odd is that normally the first time the behaviour runs the wrong dependencies are resolved. Yet, on subsequent executions the right dependencies are resolved. If I have the scope, I'll see if I can repro in a repo next week, but because of the problems we're experiencing I may have to work on something else. It's making testing very difficult. This might be another issue TBH and of course I have to rule out our own code as the issue ;) |
Okay, after spending some time on some other stuff, I've come back around to this. I've spent all day narrowing down what my problem is. I've affectionately called it "scope creep", because the DI framework doesn't appear to be honouring the scope (affection is really not what I'm feeling in regards to these DI issues). It all comes down to this specific registration using
I've repro'd it at: https://github.com/t-l-k/azure-functions-di-bug.git I've added the prerelease CLI tools You have to run it in this version, because without the When running, the bug manifests in the class
The trace level output of the application displays this as part of an extension initialisation:
Commenting out the
Note the absence of Here are all the registrations in the example:
I did try experimenting with service provider sub-scopes, but doing so appeared to offend the Function's host runtime. I wish to point out, that whilst I have materialised this in an extension, the exact same behaviour was being exhibited when resolving a My temporary workaround is to just resolve all of my Please fix! 😢 |
@t-l-k I've moved your comment to a new issue to make it easier for us to iterate and discuss. It's also a bit different than what we're tracking as part of this issue, so I wanted to make sure we had a dedicated thread. For the updates for this issue, we'll be releasing those changes with the current sprint deployment. |
@fabiocav sorry to bother but can you clarify "current sprint deployment"?
Can we expect to target it App Services once it appears in "Releases" using the Thanks! |
@t-l-k ; the release I'm referring to would be the release for Sprint 58. That sprint comes to an end on 09/18, and at that point, we begin the validation/release activities, which usually takes about a week or so (for global deployment).
Once that release is fully deployed, existing function apps will be automatically updated, there's no need to take any of the steps for a private deployment or to make any modifications to the |
Is it possible to give the current status of this? Just to know when and how we can go to production with our project. Thanks |
The changes are going out with this release: Azure/app-service-announcements#201 This started rolling to production environments yesterday and we expect the deployment to be completed by the end of the week. |
Closing this as the changes to address the issues originally tracked here have been deployed. For other problems/requests in this area, please open new issues. |
Tryin to create a extension that worked both on Microsoft.Azure.WebJobs and Azure Functions (Script.WebHost), I found that there were differences between how the DI container behaves on Azure Functions on how it does in WebJobs (the standard behavior from Microsoft.Extensions.DependencyInjection), that makes a pain to create a extensions that works on both, or to migrate an application that worked in ASP.NET to functions:
A constructor parameter dependency is not registerd with DISilently injects nullThrows an exception explaining that the dependency could not be resolvedI could work around 1, but I couldn't do anything than use another separate DI container instance for my extension services for 2.
To illustrate the second scenario example, let's think that we want to use the well-known MediatR library, this library uses a delegate for resolving handlers, and we want those handlers to be scoped for whatever reason (compatibility, isolating the object graph between function instances…) :
By default Mediator register it dependencies as scoped. The factory, in the default WebJobs/Microsoft DI implementation, ends using the scope from wich it was resolver and passing it as the provider parameter to the factory lambda. However from my tests, in Azure Functions, it always uses the root service provider instance, thus making any scoped dependency from "type" effectively a singleton.
Looks like this line in DryIOC could be causing this severe difference in behavior.
I´m sure the team has a reason for deviating from the standard DI solutions that the parent WebJobs project happens to be using, however wouldn't be better and much simpler, to have a consistent behavior between Azure Functions - WebJobs and ASP.NET default implementations? That would ease the creation of extensions and reduce the changes needed to migrate existings ASP.NET projects.
The text was updated successfully, but these errors were encountered: