dapr / dotnet-sdk

Dapr SDK for .NET
Apache License 2.0
1.12k stars 340 forks source link

Actor dependency injection & scoping #683

Open tomkerkhove opened 3 years ago

tomkerkhove commented 3 years ago

Ask your question here

I'm trying to understand the scoping of an actor's lifetime and how it maps to my dependencies.

We have an API controller that uses correlation that we want to pass to the actor. We are using as scoped dependency but based on the DI docs I understood that the scope of an actor is the actor lifetime and thus it would receive a different instance than our API controller.

Is there a way to have the same dependency instance or not?

rynowak commented 3 years ago

Hi @tomkerkhove - thanks for the question.

Your understanding of the facts is accurate.

To answer your question I think I need more info about this part ... what's the relationship between the controller and the actor?

We have an API controller that uses correlation that we want to pass to the actor.

These are both primitives that do request processing so how are they related? Maybe I can help if you zoom out a bit and tell me what you want to build.

tomkerkhove commented 3 years ago

Certainly, here is an example of a fictitious scenario:

We only use Dapr actors and state stores, not the service invocation/observability pieces.

We have a dependency that tracks the correlation information but because the scopes are different, we receive different scopes.

tomkerkhove commented 3 years ago

Any thoughts on this @rynowak?

tomkerkhove commented 3 years ago

Feel free to let me know @rynowak, happy to see how we can adapt or help.

tomkerkhove commented 3 years ago

Any tips on this @rynowak? Our alternative is to pass the dependency through every call which is not ideal so would appreciate your help.

codeputer commented 3 years ago

I'm confused by your definition of an Actor. An Actor by my definition, is the encapsulation of behavior and data. It encapsulates to ensure access to the behaviour and data is single threaded and hence avoids concurrency issues.

Imo, the most important aspect is the Actor ID and it's related instantiation and data rehydration. So if you modelled a customer as an actor, and used customer ID as the actor I'd, you would first need to lookup the ID before asking for the actor to be instanciated (eg. Login using creds to authenticate a user and use creds to pick up the customer ID)

A correlation ID IMO is something passed through an async workflow, allowing traceability of a request across a distributed application.

Imo, the difference between a micro service and an actor is a concurrency control.

With that as a backdrop...what is your question/concern? Richard

tomkerkhove commented 3 years ago

Yes, I agree - My ask is more how we can improve the dependency injection in case you need a dependency that has the scope that has started outside of an actor (without passing it through the method parameters)

My example for this was to propagate things such as correlation ID, etc. so that the actor could use it for telemetry purposes.

marchagele commented 8 months ago

I have the same problem currently. What I have done so far:

At Actor level: private readonly IServiceScopeFactory _serviceScopeFactory;

At function level of the Actor: using (IServiceScope scope = this._serviceScopeFactory.CreateScope()) { IPaymentService paymentService = scope.ServiceProvider.GetRequiredService<IPaymentService>();

At this point I know when I call a function of the Actor from a Controller I will get a scoped Service at least for this instance. It will not be the same as the instance of the Controller, but for this I have wrapped the logic into a Service.

Kinds regards