8
votes

I am trying to use a broadcast router in Scala, if I'm not mistaken it should look like this:

val system = ActorSystem("My beautiful system")
val workerRouter = system.actorOf(Props[Agent].withRouter(BroadcastRouter(individualDefinitions.size)), name = "agentRouter")

That is what I understand from the tutorial I am following.

The workerRouter acts as another actor and I can send messages to this router that will send them to all the Agents (as many as individualDefinitions I have).

The problem is that I'd like to use the individual definitions to build the agents, they actually take some parameters in the constructor and those parameters are in the individualDefinitions.

Q: How could I tell the router to pass those parameters to each one of them as part of the constructor?

Please note each actor should get one individualDefinition and they are all different. I cannot use the solution in a related question where the constructor receives constants: In Akka Java actor model, can a router create actors with non-default constructor?

Please note that here each actor should have different parameters, if one of them is restarted it should get the same parameters it got in the first place. I don't know if that solution could be modified to do that.

A possible solution could be using an actor as the router, to separate creation (constructor) and routing, as in question Akka (java), non blocking broadcast to all children.

I'm not sure that is the "right" approach in this case. Using an actor as the router has several problems (besides of elegance). I am concerned about the actor that works as a router being restarted and losing all its subscribers. If the actor is restarted in half of a loop some actors could also miss some messages if I'm not mistaken.

Thank you.

2

2 Answers

7
votes

You can create routers by specifying as routees some already created actors, constructed by whatever logic.

The following example will create 2 actors created differently and then create a round robin router which will route the messages to them.

class MyActor(param1: String) extends Actor with ActorLogging {
  def receive: Actor.Receive = {
    case msg => log.info("Message from {}: {}", param1, msg)
  }
}

object MyActor {
  def apply(param: String): Props = Props(new MyActor(param))
}

object Main extends App {
  val system = ActorSystem()

  val a1 = system.actorOf(MyActor("actor1"))
  val a2 = system.actorOf(MyActor("actor2"))

  val routerProps = Props.empty.withRouter(RoundRobinRouter(routees = Vector(a1, a2)))

  val router = system.actorOf(routerProps)

  for (i <- 1 to 10) {
    router ! i
  }

  readLine()
  system.shutdown()
}

More details here: http://doc.akka.io/docs/akka/2.2.0/scala/routing.html

0
votes
public class Master extends UntypedActor {
     -----
     -----
    public Master() {
        workerRouter = this.getContext().actorOf(Worker.createWorker().withRouter(new RoundRobinRouter(8)), "workerRouter");
    }

With Akka 2.4.2, we can simply use:

workerRouter = this.getContext().actorOf(new RoundRobinPool(noOfWorkers).props(Props.create(Worker.class)), "workerRouter");

This is best Effort code executed in min. time in akka .