user_mda
user_mda

Reputation: 19418

context().parent() in a router pool

I create a pool of actors like this:

 public ParentActor() {

    childRouter = getContext().actorOf(
        new SmallestMailboxPool(actorPoolSize)
            .props(Props.create(Child.class)),
        "ChildRouter");
  }

Then somewhere in the child actor I have the following:

if (message instanceof someMessage) {

    context().parent().tell(someOtherMessage, getSelf());
}

I was expecting that the sometherMessage will be received in the ParentActor; instead, this goes into an infinite loop. To debug this further I added some logs in the child actor as follows:

log.debug("who is my parent {} ",  context().parent().getPath())

This gives me the following path:

/ActorSystem/user/ParentActor/ChildRouter

Which makes me think that the parent of one of the actors in the pool is the router actor--is this the correct behavior? How should I send a message back to the actor that spawned the router actor? I am confused.

Upvotes: 1

Views: 169

Answers (1)

Jeffrey Chung
Jeffrey Chung

Reputation: 19527

Yes, the router is the parent (or supervisor) of the routees. From the documentation:

Routees that are created by a pool router will be created as the router’s children. The router is therefore also the children’s supervisor.

When you make the following call in a routee...

context().parent().tell(someOtherMessage, getSelf());

...the someOtherMessage message is sent to the router.

The actor that you've named ParentActor is not the parent of the Child actors that are created as part of the childRouter pool. If you want a routee to send a message to ParentActor, one approach is to change the Child actor class to take an ActorRef as a constructor argument:

public class Child extends AbstractActor {
  private final ActorRef target;

  public Child(ActorRef target) {
    this.target = target;
  }

  // ...
}

Then in ParentActor, when creating the router, you can pass the reference to ParentActor (with getSelf()) to the Props for creating the routees:

childRouter = getContext().actorOf(
    new SmallestMailboxPool(actorPoolSize)
        .props(Props.create(Child.class, getSelf())),
    "ChildRouter");

Now the Child actors can send messages to ParentActor:

if (message instanceof someMessage) {
  target.tell(someOtherMessage, getSelf());
}

Upvotes: 3

Related Questions