In my task parent actor create some child actors and send message to them
def apply(): Behavior[CreateBranch] = {
Behaviors.receive { (context, message) =>
val child1 = context.spawn(Child(), "child1")
val child2 = context.spawn(Child(), "child2")
val child3 = context.spawn(Child(), "child3")
context.children.foreach {
child ! Child.SomeMessage
{
}
}
Child actor defined as:
object Child {
sealed trait SomeMessage
def apply():Behavior[SomeMessage] = {
// some behaviour
{
}
But expression "context.children" does not work: children defined as Iterable[ActorRef[Nothing]] instead of Iterable[ActorRef[Child.SomeMessage]]
In documentation about "context.children" ActorContext.children
"this is not a useful way to lookup children when the purpose is to send messages to them."
And this document suggest alternative way of realisation - but it about of 30 lines of code!
Is there any other alternative way to realise broadcast message send ?
CodePudding user response:
There is no way in general to guarantee the static type of the child actors (and the same is true of the parent actor and the guardian actor (context.system
)).
However, if you're absolutely sure that all children will accept the message you can
context.children.foreach { child =>
child.unsafeUpcast[Child.SomeMessage] ! Child.SomeMessage
}
As the name implies, this is unsafe and allows you to send messages without any guarantee that the child will handle them. Since the implementation of an Akka Typed Behavior
involves a classic actor which performs message casts, a mismatch between Behavior
and ActorRef
can cause the actor to immediately fail. unsafeUpcast
is (at least from the sender's perspective...) safer than an asInstanceOf
cast, as this at least guarantees that you're actually calling !
on an ActorRef
.