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

Actor dependency injection & scoping #683

Open
tomkerkhove opened this issue May 26, 2021 · 8 comments
Open

Actor dependency injection & scoping #683

tomkerkhove opened this issue May 26, 2021 · 8 comments
Labels
question Further information is requested

Comments

@tomkerkhove
Copy link
Contributor

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 rynowak added the question Further information is requested label May 27, 2021
@rynowak
Copy link
Contributor

rynowak commented May 27, 2021

Hi @tomkerkhove - thanks for the question.

Your understanding of the facts is accurate.

  • Controllers see a new scope for each request
  • Actors see a single scope until they crash or are deactivated

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
Copy link
Contributor Author

Certainly, here is an example of a fictitious scenario:

  • User does POST /api/v1/orders
  • Controller locates actor instance for that user
  • Call user.CreateOrder()
  • Return Created

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
Copy link
Contributor Author

Any thoughts on this @rynowak?

@tomkerkhove
Copy link
Contributor Author

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

@tomkerkhove
Copy link
Contributor Author

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
Copy link

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
Copy link
Contributor Author

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
Copy link

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

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

No branches or pull requests

4 participants