如何将数据传递给 OnActivateAsync() 以初始化我的有状态 actor?

How to pass data to `OnActivateAsync()` to initialize my stateful actor?

我正在创建一个可靠的、有状态的服务参与者。

问题:

有没有办法在 actor 代理创建期间传递初始化数据 (ActorProxy.Create())?基本上相当于我的演员的构造函数。

目前的想法:

我可以通过调用负责初始化状态的 actor 方法调用代理创建调用来实现这一点。

例如

//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);

我对这种方法的担忧:

代理创建不等同于构造函数。在 Service Fabric 中,客户端不应该知道参与者是否已经创建,并且生命周期由运行时管理。

因此 actor 本身应该初始化为某个默认状态。 actor 实现的工作是在初始化调用之前防止其他调用,并在需要时防止多次初始化。由于 actor 始终是单线程的,因此可以使用布尔标志之类的东西轻松实现。

似乎进行原子初始化的最佳方法是将初始化数据保存在某个外部存储中,并在 OnActivateAsync() 期间使用该存储中的数据。

在这里给你一些想法。其一,在 OnActivateAsync 期间,您需要进行初始化的数据是否真的对 actor 本身不可用?通常,如果我依赖于将一些初始数据输入到我的演员状态中,我会这样做。

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();
   }
}

另一个想法是,如果你真的不能让 actor 在它自己的激活期间检索数据,那么你很容易创建一个布尔值 属性,它是 actor 状态的一部分,指示是否或你说的另一个激活曾经发生过。

 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;
 }

这样虽然从技术上讲该方法可以在 actor 的生命周期内调用,但您有一个单线程保证它只会在第一次调用时实际执行某些操作。