I am creating a reliable, stateful, service actor.
Question:
Is there a way to pass initialization data during the actor proxy creation (ActorProxy.Create()
)? Basically an equivalent to a constructor for my actor.
Current thoughts:
I can achieve this by following up the proxy creation call with an actor method call in charge of initializing the state.
E.g.
//Danger, the following calls are not atomic
ITokenManager tokenActor = ActorProxy.Create<IMyActor>(actorId, "AppName");
//Something could happen here and leave my actor in an unknown state
await tokenActor.InitializeAsync(desiredInitialState);
My concern with such approach:
A couple thoughts for you here. For one, is the data that you need to do initialization really not available to the actor itself during OnActivateAsync
? Normally if I rely on getting some initial data into my actor's state this is how I would do it.
protected override Task OnActivateAsync()
{
if (State == null)
{
var initialState = await externalSource.GetSomeState();
// simplified here but map the values properly onto the actual actor state
this.State = initialState;
return base.OnActivateAsync();
}
}
The other thought is that if you truly can't have the actor retrieve the data during it's own activation it's very easy for you to create a boolean property that is part of the actor state indicating whether or the other activation you're talking about has ever occurred.
public Task InitializeAsync(State someState)
{
if (State.IsActivated)
{
// log out here that someone is attempting to reactivate when they shouldn't
return Task.CompletedTask;
}
State = someState;
State.IsActivated = true;
return Task.CompletedTask;
}
This way while technically the method will be available to be called for the lifetime of the actor, you have a single threaded guarantee that it will only actually do something the very first time it is called.