I was learnning Akka Typed Actor library and tried to send a message to all child actors of a particular actor, using this.getContext().getChildren()
. But it returns a Void
type and not the type I initially created the child actors with -> hence I could not send any type of message to the children.
The workaround I did is to simply store the children in a hashmap at the time of creation. But this is not a scalable one.
How can I achieve this? especially under distributed scenario?
.onMessage(GetPosition.class, message -> {
// whenever I send a GetPosition() message to myself,
// I get that reminder and send an AskPosition to all workers
while (results.keySet().size() < 10) {
// while not finished, ask for positions from child actors
// This is not working
this.getContext().getChildren().forEach(child -> {
child.tell("this is a void class, so I cannot send any message to children");
});
// WORKAROUND:
// get child actors from hashmap (hashmap lambda has 2 things in it -> bi-consumer)
racers.forEach((id, actor) -> actor.tell(new RacerBehavior.AskPosition(this.getContext().getSelf())));
}
return this;
})
Because it's not possible to statically know the types of messages accepted by the children which an arbitrary actor will spawn, getChildren()
can only return ActorRef<Void>
s (or ActorRef[Nothing]
s in Scala, which better captures the idea that you cannot send them messages).
If all your children happen to be the same type (which would be a prerequisite for being able to iterate through them in to send messages), something like this should work:
child.unsafeUpcast<Object>.narrow<RacerBehavior.AskPosition>
If you can't be absolutely sure that all your children are the same type, tracking them explicitly with their types in the parent actor's state (e.g. having a collection per-type) is the way to go.