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

Lifetime of constructor injected services for an Actor #988

Closed
hittaKAFFE opened this issue Dec 1, 2022 · 3 comments
Closed

Lifetime of constructor injected services for an Actor #988

hittaKAFFE opened this issue Dec 1, 2022 · 3 comments

Comments

@hittaKAFFE
Copy link

I have a few question about the lifetime of contructor injected services for IRemindable Actors.

Background

We are going to be using an Actor for our .NET application with a long lifetime (several days), which is going to be reminded to activate once every day for a few days.

The Actor will be dependent on a service that in turn is dependent on an EF Core DbContext. We want the context to be as short lived as possible, and ensure that it doesn't share the same lifetime as the Actor (which will be several days).

It will look something like this:

public class MyActor : Actor, IMyActor, IRemindable
{
    public MyActor(ActorHost host, IMyRepository) // IMyRepository contains an EF Core DbContext
        : base(host)
    {
        ...
    }

    ...

 	public async Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period)
    {
        ...
    }
}

Questions

From the documentation:

Each actor instance has its own dependency injection scope and remains in memory for some time after performing an operation. During that time, the dependency injection scope associated with the actor is also considered live. The scope will be released when the actor is deactivated.

When is the Actor deactivated? And is the Actor only reactivated when it receives a reminder?
Is the Actor, and/or its services, disposed on deactivation?

Do you see any issues with using constructor injected services for long-running IRemindable Actors (several days)?

Should we perhaps use an IServiceProvider.CreateScope() instead and create a new scope everytime the Actor is reminded, to ensure that services are disposed of properly? Like so:

public async Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period)
    {
        using (var scope = _serviceScopeFactory.CreateScope()) // Constructor injected IServiceScopeFactory
        var myRepository = scope.ServiceProvider.GetRequiredService<IMyRepository>();
        ...
    }
@WhitWaldo
Copy link
Contributor

@hittaKAFFE I'm sorry this was missed and no one wrote back to you for so long.

Actors are virtual - it'll be activated whenever a turn starts for its identifier (e.g. when a method is invoked on it or a reminder is triggered) and will be deactivated at some unknown point beyond that (up to the runtime), but re-activated whenever another turn is triggered.

I don't anticipate issues with any constructor-injected services so long as the DI registrations aren't themselves subject to change (e.g. you're creating a scoped or transient EF context from a connection string in Key Vault that you delete out of the blue at some point).

Creating your own scope isn't necessary.

@WhitWaldo
Copy link
Contributor

@hittaKAFFE I was reading through other issues this morning and also noticed this response which might be of some use to you. Here, the user did find value in creating their own scope to gain access to a correlation identifier that would be consistent across the scoped request, so there may indeed be some limited value in doing that, but I struggle to think of any other similar situations off the top of my head.

@hittaKAFFE
Copy link
Author

Cool, thanks @WhitWaldo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants