Get Actor reference from unique path

Hello I am struggling to get an actor reference from a dynamic path

I created a bunch of actors at the root level with an unique name for each actor
My idea is to allow after any new actor of my application to send a message to an actor it can guess its unique path.
something like that
val actor = getActorByPath(“myuniquepath”)
actor ! SendAMessage()

I am not able to find the right way to do that or even if it is possible when we build actors in a dynamic way
thanks for your help

For the classic actor APIs you can use actor selection

For typed APIs that is not possible (as it would not convey the type of messages the actors can receive) and you should in general use the receptionist instead.

1 Like

It looks like ernleite posted a similar query on StackOverlow with a similar question, but it struggling to get the Receptionist working in a clustered environment.

I’m going to try and hack together a really quick sample.

But, ernleite, I think you are going to have to post your code, config, and logs, because this is pretty much the basic functionality of the receptionist and if it isn’t working for you it’s probably something basic wrong with your config (like a DistributedData config that isn’t working) or a misunderstanding you have of the API.

thanks @davidogren for your reply.
I got it to work finally
I created a separate Manager to do the job :-)

@davidogren
I have the receptionist working but now I have another problem.

Could you confirm that if I declare a variable on the object I would have its value not shared with the other instances of the same actor (I mean actors that are in the same machine or jvm) ?
I have a strange behaviour that apparently the variable is shared amoung all the same actors…
Maybe I missunderstood that also… Sorry still learning

example
ActorA/Instance1/variableA=1
ActorA/Instance2/variableA=2

Could you confirm that when I spawn a message to ActorA/InstanceA it will see variableA =1?
If I spawn a message to ActorA/InstanceB it will see variableA =2?

for the moment it is not the behaviour I have.
I am using a scala object but is it better to implement my actor as a class? I don’t know the difference as I can see both implementation in the documentation

here is my object :

trait ComputeActivationSerializable
object ComputeActivation {
  final case class Compute(Weighted: Array[Double], InternalSubLayer:Int, Layer:Int, Shards: Int) extends ComputeActivationSerializable
  private var shard:Int = 0
  private var shardReceived:Int = 0
  private var inProgress: Boolean = false
  private var bInitialized = false

  def apply(actorId: String): Behavior[Compute] =
    Behaviors.setup { context =>
      context.system.receptionist ! Receptionist.Register(
        ServiceKey[Compute](actorId), context.self
      )

      Behaviors.receiveMessage { message =>
        if (!bInitialized ) {
          //do some stuffs just once when the actor receives its first message
          bInitialized = false 
        }
        //continue

I have a feeling that the values are shared per jvm
if so how can I achieve that goal to have private variables per actor instance?

thanks

You are creating your variables in the Scala object (which is indeed a singleton across the JVM), not in the actor.

If you want to use the functional style, take a look at the style guide for best practices on how to pass around the state.

Thanks a lot
I will have a look at it

Here is my workaround
I defined a case class

object ComputeState {
  case class ZState(
      var bInitialized:Boolean = false,
      var shardReceived:Int = 0,
      var shard:Int = 0,
      var bias:Array[Double] = Array[Double](),
      var inProgress:Boolean = false,
      var activation:Array[Double] = Array[Double](),
      var weighted:Array[Double] = Array[Double]()
  )
}

I declared this on the actor itself.
And I put each object per actor on a hashmap The actorId which is the key and unique in the cluster

if (!stateInfo.keys.exists(_ == actorId)) {
context.log.info("Creating ZCompute object " + context.self.path.name)
stateInfo += (actorId -> ZState())
}

Then I can use that later in the code :

if (!stateInfo(actorId).bInitialized ) {

What do you think ?
Thanks

Storing the state externally in a hashmap defeats the purpose of actors.

If you don’t store the state in the actors you are losing most of the benefits. You also end up with all kinds of edge case problems (e.g. if the actor is stopped, you still have dangling state). Plus, if you don’t learn how to do this now it’s going to cause all kinds of problems later because everyone and everything is going to expect that you are storing the state in the actors. For example, the approach you are taking wouldn’t work with something like sharding or persistence.

Just store the state in the actor. The functional style can be non-intuitive if you aren’t used to functional programming, but once you get used to the approach it’s easy. Or you can still use the object oriented style with typed actors if you prefer.

2 Likes

thanks a lot for your excellent support
I did the changes and I can confirm that it is working as expected.
Very Nice !
thanks again