1
votes

I am new to Akka and Actor and is playing with it. For this purpose I use a parent Actor with several child actors, created from router with balancing pool. Each actor will hold some data which I want to update (all of them) from the parent actors. So I do something like router ! Broadcast(MessengeToAll(Somedata))

To my surprise, in a balancing pool settings, not all the state of the child actors are updated. I tried to send a print message and find that I am so stupid that of course not necessary all will be updated, as it seems the routers just send messages to the mailbox, and as I am using the balancing pool, only the most idle actors will "steal" the updating message.

This can be solved by using RoundRobin router, however, I do still want to use Balancing pool. Nor do I want a broadcasting pool. I found in the Scala docs something about event bus, but it is very complex and I do not understand how to do it really. Can someone help me with a (possibly) easy solution? Thanks very much. :)

1

1 Answers

1
votes

If you want to send a broadcast to all child actors of a given actor, a BalancingPool router is definitely not what you want, nor is a RoundRobin router.

Read the section "Pools vs Groups" in this link. Disregard the fact that it is a .NET doc; its content is platform-agnostic

If you use a routing pool, you don't hold references to the actors that get created by the routing pool. Therefore, unless you want to do some magic to figure out the actor path names, you can only send them messages using the routing logic of that routing pool.

What you want is to create the actors yourself and then supply them as routees when you create the routing group. Then you get to address them both directly and via the router.

If you want to send them all a message, you can just myActors foreach (_ ! "message"), and if you want to go via router, you can router ! "message"

I'm afraid there is no "BalancingPool" router group equivalent; I'll give you a full example using the RoundRobin routing logic:

import akka.actor.{Actor, ActorSystem, Props}
import akka.routing.{ActorRefRoutee, RoundRobinRoutingLogic, Router}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

class ParentActor extends Actor {
  val actors = (1 to 5).map(i => context.system.actorOf(Props[ChildActor], "child" + i))
  val routees = actors map ActorRefRoutee

  val router = Router(RoundRobinRoutingLogic(), routees)

  router.route("hello", sender())
  router.route("hello", sender())
  router.route("hello", sender())
  router.route("hello", sender())
  router.route("hello", sender())

  actors foreach (_ ! "broadcast")

  def receive = { case _ => }
}

class ChildActor extends Actor {
  def receive = {
    case "hello" => println(s"${self.path.name} answers hey")
    case "broadcast" => println(s"${self.path.name} received broadcast")
  }
}

object Main extends App {
  val system = ActorSystem("HelloSystem")

  val parent = system.actorOf(Props(classOf[ParentActor]))

  Future {
    Thread.sleep(5000)
    system.terminate()
  }
}

Outputs when sbt run

[info] Running Main
child2 answers hey
child5 answers hey
child1 answers hey
child4 answers hey
child1 received broadcast
child3 answers hey
child4 received broadcast
child3 received broadcast
child5 received broadcast
child2 received broadcast
[success] Total time: 8 s, completed 7/05/2016 6:28:18 PM
>

Good luck learning Akka!