Find actor by persistence id

516 Views Asked by At

I have a system, that has an actor per user. Users send messages rarely, but when they do, they send usually not only one, but few.

Currently, I have a map, where I store persistenceId -> ActorRef. When I'm receiving a new message for an actor, I look into the map, if there is an ActorRef, I use it. If it is missing, I create it and put it into the map. For sure I don't want to have 2 instances of same persistence actor at the same time. Also, I don't want to create and destroy the actor for each message, as recovery could take some time.

I feel there should be some cleaner way of "locating or creating" an actor. Something like actorSystem.getOrCreate(persistenceId, props). I thought that sharding might help me with that, but I couldn't find an exact example of this. Also, I know there is actorSelection, which has downsides:

  • using it in too many places, with hardcoded paths that are tricky to maintain
  • using it to send too many messages as it has a performance cost

So basically the question is what is the best way of locating persistence actor within one service if I actor persistenceId is userId. If I decide to use sharding, then it will be 1 shard per actor. Is this ok?

1

There are 1 best solutions below

2
On BEST ANSWER

Actor sharding is pretty much what you need - you can think about it as a distributed map of actors and there is no need of having additional solutions. The sharding takes care of summoning the actor behind the scenes and there is no need for you to manage actors yourself.

val sharding = ClusterSharding(system).start(
    typeName = CustomerActor.shardName,
    entityProps = CustomerActor.props,
    settings = ClusterShardingSettings(system),
    extractEntityId = CustomerActor.extractEntityId,
    extractShardId = CustomerActor.extractShardId)
}

where extractEntityId is a function which routes messages to appropriate actors

val extractEntityId: ShardRegion.ExtractEntityId = {
  case gc: GetCustomer => (gc.customerId, gc)
}

And final example:

case class GetCustomer(customerId: String)

sharding ! GetCustomer("customer-id")

More details here https://doc.akka.io/docs/akka/2.5/cluster-sharding.html