Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically add/remove routees to a router actor

Tags:

scala

akka

Would you know a nice way in Akka/Scala to add/remove routees to a Broadcaster router?

I have been looking at the Resizer - but does not meet my needs (I cannot see how to explicitly ask the resizer to resize (add routees) and to remove it seems that you need to send a Poison Pill to the actor which is then removed).

So far, I have a router with a list of ActorRef and I send AddRoutee and RemoveRoutee messages....

My business case: I have an actor getting data from the network (via a proxy), and it needs to dispatch this data to independent actors for processing in parallel. Due to the graph nature of the recipients (DAG), the graph can evolve at runtime, vertices/edges being modified, hence the need to add and remove routees

There must be a cleaner way to do this.

Thanks for the pointers.

Example of code I would like Akka to handle:

 class MDActor extends Actor {
  @volatile var routees = Set[ActorRef]()

  def receive = {
    case ar: AddRoutee => routees = routees + ar.actorRef
    case rr: RemoveRoutee => routees = routees - rr.actorRef
    case msg => routees.foreach(r => r forward msg)
  }
}
like image 418
jts Avatar asked May 20 '13 12:05

jts


2 Answers

Whenever you find yourself lacking a feature in a Router it is a very good time to start thinking in the other direction: what is wrong with the actor code you present? Unless you need to route more than a few million messages per second (which is unlikely given your description) such an actor is precisely the right solution. Routers are a very specialized construct which should not be used as a substitute; only use them when they exactly meet your requirements and you have benchmarked that a normal actor does not suffice.

like image 99
Roland Kuhn Avatar answered Nov 06 '22 15:11

Roland Kuhn


Not sure there is really a better way than to keep state about the routees and build a new router on every change OR don't use a router and use a plain actor. I looked at this recently too.

Favour immutability - The favoured solution, then, is likely going to be to throw away the old router and/or collection and build a new one (router or set/map of actors).

You can just keep track of your actors and not use the router at all - this is a fine solution and recommended in the akka documentation as a simpler alternative to a router. Routers are supposed to have a performance advantage over a full blown actor.

You can build routers with lists of actors as demonstrated here. Just do this every time there is a change. (source: akka documentation - http://doc.akka.io/docs/akka/snapshot/scala/routing.html)

val actor1 = system.actorOf(Props[ExampleActor1])
val actor2 = system.actorOf(Props[ExampleActor1])
val actor3 = system.actorOf(Props[ExampleActor1])
val routees = Vector[ActorRef](actor1, actor2, actor3)
val router2 = system.actorOf(Props().withRouter(
  RoundRobinRouter(routees = routees)))

Here shows the RoundRobin router but that's not any different than using the broadcast one.

It's a bit more functional to recreate this.

like image 33
JasonG Avatar answered Nov 06 '22 17:11

JasonG