Comments (2)
Disabling the check for the AuthProviderService would remove the error, but I am also aware that may cause other issues (leak?).
It would not work the way you expect it to, because before the introduction of strict mode if you resolved a singleton through a scope, if that singleton depended on scoped services, it would maintain references to those scoped services which is considered a leak. For example, say on the first HTTP request your singleton receives a scoped auth context, on subsequent requests it will be using that same auth context that it got in the first request.
You are correct that this use case is common, and your original solution is how you'd solve it, but you mention that you're taking a performance hit. Could you elaborate on this? I've been running the same setup as you in production at my current company for the past 7 years and haven't had a performance issue that could be traced back to scoped services.
Some questions:
- Approximately how many scoped services get resolved in a typical request?
- What injection mode are you using? Classic mode will give you the best performance as it scans class/function dependencies at declaration time and does not have the overhead of a
Proxy
call.
If you're certain that this is indeed a significant cause of GC churn, then I would recommend that you pass in your auth context via arguments, and use the factory pattern for constructing short-lived services (e.g. ones that use per-scope caching). This is how I've been doing it for new things I've been building, both in JS/TS and in other languages like C#.
from awilix.
Thank you for your quick response and proposed solution!
I realise the solution I suggested would cause a leak, it makes sense to drop that idea. What I ended up doing was to use AsyncLocalStorage
to create a ReqContextStore
. Then I added an Express
middleware to add the authContext
to that store on each request. That allows me to create a singleton
reqContextStore
(and keep all the services as singletons
) while still having access to the authContext
per request.
For more context on my issue, let me also answer your questions:
Approximately how many scoped services get resolved in a typical request?
The way the DI is currently structured, there's about 100 registered scoped objects (Services, UseCases, DomainEventHandlers). A typical requests likely resolves around 1-2 Services and 3-4 UseCases. The issues comes with the DomainEventHandlers. I have a DomainEventDispatcher
on which I register handlers for various DomainEvents
. Because of the way it's currently implemented, I must manually resolve all the registered handlers on each request, and that causes 10-20 of them to be instantiated. And with each new handlers, there's a little bit more overhead added. I could refactor the DomainEventDispatcher
but I was curious to see if there was a way they could all be turned into singletons
instead, which I think the above solution achieves.
What injection mode are you using? Classic mode will give you the best performance as it scans class/function dependencies at declaration time and does not have the overhead of a Proxy call.
All the services use the proxied
injection mode, while the rest typically use the classic
mode. It's good to know the classic mode yields better performance! I'll keep that in mind for the future.
I guess this issue can be closed, if I end up needing the scoped
lifetime for anything else, I'll refer back to this!
from awilix.
Related Issues (20)
- Whiteboard pattern HOT 7
- [Question] Support for assisted inject HOT 2
- awilix object is undefined when using default import, but named import of functions work HOT 1
- Support for ESM modules HOT 3
- Is it possible to reinforce constructor param name/types? HOT 1
- Can't resolve HOT 4
- How to unregister a dependency from the container? HOT 6
- Default value not working in class constructor in Proxy mode HOT 2
- asFunction -> asClass Cyclic dependency HOT 2
- Awilix TypeError: Cannot read properties of undefined (reading 'cache') HOT 2
- Calling `loadModules` does not register all the file paths HOT 2
- Is it possible to detect / error on singletons dependent on transient or scoped registrations? HOT 1
- Awilix 10 type exposure HOT 1
- [QUESTION] Userland async initializers HOT 7
- replace camel-case dependency HOT 3
- Critical dependency: the request of a dependency is an expression HOT 3
- Add TypeScript support HOT 1
- [QUESTION] - Awilix Fails to Autoload Modules in Vitest Tests with TypeScript Setup HOT 1
- How can I get scope inside instance? HOT 14
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from awilix.