通过间接引用找到以前持久化的Akka actor

时间:2017-07-25 11:21:49

标签: akka akka.net akka-persistence

我目前正在构建的系统中有很多地方可以通过多种方式联系同一个演员。例如,如果你有一个持久的汽车演员,你可以使用VIN或登记牌。

由于我们需要在重新创建actor时使用单个“真实名称”作为actor名称/持久性ID,因此这些“lookups / references”本身就是actor,以其键命名,仅保留它们引用的actor的ID

这看起来是正确的方法吗?似乎很多演员都不是演员,只是代理人。

1 个答案:

答案 0 :(得分:0)

编辑更新答案。

听起来我们有一个包含汽车集合的存储库,每辆汽车都可以有一个VIN或REG编号(或序列号,或底盘编号......唯一标识汽车的东西)。

ID    |  VIN  |  REG
car1  |  ABC  |  123
car2  |  DEF  |  456

我们还有一个持久的CarActor,它封装了汽车的状态和逻辑。

public class CarActor : PersistentReceiveActor
{
    string _id;
    public override string PersistenceId { get { return _id; } }

    public CarActor(string id)
    {
        _id = id;
    }

    public static Props Props(string id)
    {
        return Akka.Actor.Props.Create(() => new CarActor(id));
    }     
}
  

因为我们需要一个真正的名字"用作演员姓名/持久性   重新创建演员时的ID,这些"查找/引用"他们自己   演员,以他们的钥匙命名,只持有演员的身份证   他们参考。

     

这看起来是正确的方法吗?好像很多   演员不是真正的演员,只是代理人。

为简化起见,我们可以定义一条消息,该消息封装了可以识别汽车的各种ID号。然后可以将此消息传递给我们的Actor系统进行处理。

public class CarCommand
{
    public string Vin { get; private set; }
    public string Reg { get; private set; }
}

Best practice是拥有一个主管或路由器角色,负责实体领域,并选择将每个实体表示为自己的角色。该主管可以收到CarCommand消息,通过VIN或REG查找汽车的ID,并查找/创建一个子演员来处理该消息。

public class CarSupervisor : ReceiveActor
{
    //in reality this would be a repository e.g. a DB context... it would
    //be even better if this was handled in another Actor that this Actor
    //has access to
    readonly IEnumerable<Cars> _cars;

    public CarSupervisor(IEnumerable<Cars> cars)
    {
        _cars = cars;
        Receive<CarCommand>(command => 
        {
            //find a car by VIN or REG or other variable
            var car = _cars.First(c => c.VIN == command.VIN);
            //see if any child actors have been created for this car instance
            var child = Context.Child(car.Id);
            //if we don't have an incarnation yet, create one
            if (Equals(child, ActorRefs.Nobody))
                child = Context.ActorOf(CarActor.Props(car.Id), car.Id));
            //tell the child to process the message
            child.Forward(command);
        });
    }      
}