0

There are quite a few places in a system I am currently building in which there are multiple ways to reach the same actor. For instance, if you have a persistent car actor, you could use the VIN or registration plate.

As we need a single "true name" to use as the actor name/persistence ID when recreating an actor, these "lookups/references" are themselves actors, named after their key, persisting only the ID of the actor they reference.

Does this seem like the right way to do it? It seems like a lot of actors which aren't really actors, just proxies.

jameswilddev
  • 582
  • 7
  • 16

1 Answers1

0

Edited to update answer.

It sounds like we have a repository that contains a collection of cars, and each car can have a VIN or REG number (or serial number, or chassis number... things that uniquely identify a car).

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

We also have a persistent CarActor that encapsulates state and logic for a car.

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

As we need a single "true name" to use as the actor name/persistence ID when recreating an actor, these "lookups/references" are themselves actors, named after their key, persisting only the ID of the actor they reference.

Does this seem like the right way to do it? It seems like a lot of actors which aren't really actors, just proxies.

To simplify things, we could define a message that encapsulates the various ID numbers a car can be identified with. This message can then be passed to our Actor system for processing.

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

Best practice is to have a supervisor or router actor that is responsible for a domain of entities and elects to represent each entity as its own actor. This supervisor can receive a CarCommand message, look up the ID of the car by VIN or REG, and find/create a child actor to process the message.

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);
        });
    }      
}
Chima Osuji
  • 391
  • 2
  • 10
  • Thanks for your answer but I'm not sure you've understood the question. There is no natural key for this actor; I could be trying to find it by VIN, registration plate,etc. Is there a way of finding the car by any of these other than having a separate actor for every reference (VIN, registration plate)? Also, in memory lists would not be feasible. – jameswilddev Jul 25 '17 at 15:31
  • Isn't a VIN or Reg a unique key? E.g. one VIN can only relate to one car, which has an ID in our repository. An `IdSupplierActor` could take a message containing a VIN or Reg etc, and return the ID of the car in question. Or a `CarFinderActor` takes the message and returns a path to the `Actor`. – Chima Osuji Jul 25 '17 at 15:55
  • This is what I mean; how would that be implemented using Akka Persistence? It's not feasible to have an actor with every single VIN or registration plate number on it. Thanks. – jameswilddev Jul 25 '17 at 16:01
  • @james - edited answer after our discussion... hope this helps :) – Chima Osuji Jul 26 '17 at 07:17
  • @ChimaOsuji do I understand you correctly that you would use a conventional DB to fetch (or store) identification references to a single ID to use as a name of an actor? Combining a DB with an actor system? – Bjorn Bailleul Aug 20 '18 at 20:37
  • @Bjorn Bailleul, yes that is exactly what I mean. How else would an actor name be persisted? It has to be saved somewhere. – Chima Osuji Aug 22 '18 at 04:38