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

本文关键字:初始化 我的 Actor 状态 OnActivateAsync 数据 | 更新日期: 2023-09-27 18:35:54

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

问题:

有没有办法在参与者代理创建(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);

我对这种方法的担忧:

  • 此操作不是原子操作。这可能会让我的演员处于不一致的状态
  • 此初始化方法现在在执行组件的整个生命周期中都可用,这是不需要的。

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

这里有

一些想法给你。首先,在OnActivateAsync期间,需要进行初始化的数据真的对参与者本身不可用吗?通常,如果我依靠将一些初始数据输入到我的演员的状态中,这就是我会这样做的方式。

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

另一个想法是,如果您确实无法让参与者在自己的激活期间检索数据,那么您很容易创建一个布尔属性,该属性是参与者状态的一部分,指示您正在谈论的其他激活是否曾经发生过。

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

这样,虽然从技术上讲,该方法可以在参与者的生存期内调用,但您可以保证它只会在第一次调用时实际执行某些操作。

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

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

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