已编辑以更新答案。
听起来我们有一个包含汽车集合的存储库,每辆汽车都可以有一个 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
他们参考。
这似乎是正确的方法吗?好像很多
演员不是真正的演员,只是代理。
为了简单起见,我们可以定义一个消息来封装可以识别汽车的各种 ID 号。然后可以将此消息传递给我们的 Actor 系统进行处理。
public class CarCommand
{
public string Vin { get; private set; }
public string Reg { get; private set; }
}
Best practice 是有一个主管或路由器参与者,负责实体域并选择将每个实体表示为其自己的参与者。这个主管可以接收CarCommand 消息,通过 VIN 或 REG 查找汽车的 ID,并找到/创建一个子 Actor 来处理该消息。
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);
});
}
}