pekko/akka-remote/src/main/scala/akka/routing/RemoteRouterConfig.scala
Roland 0f48b9f3eb make supervisorStrategy of Router configurable, see #1835
- also do not scrap router’s children upon restart
- and add docs and tests
2012-02-18 22:15:39 +01:00

81 lines
3.2 KiB
Scala

/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.routing
import com.typesafe.config.ConfigFactory
import akka.actor.ActorContext
import akka.actor.ActorRef
import akka.actor.ActorSystemImpl
import akka.actor.Deploy
import akka.actor.InternalActorRef
import akka.actor.Props
import akka.config.ConfigurationException
import akka.remote.RemoteScope
import akka.actor.AddressExtractor
import akka.actor.SupervisorStrategy
/**
* [[akka.routing.RouterConfig]] implementation for remote deployment on defined
* target nodes. Delegates other duties to the local [[akka.routing.RouterConfig]],
* which makes it possible to mix this with the built-in routers such as
* [[akka.routing.RoundRobinRouter]] or custom routers.
*/
case class RemoteRouterConfig(local: RouterConfig, nodes: Iterable[String]) extends RouterConfig {
override def createRouteeProvider(context: ActorContext) = new RemoteRouteeProvider(nodes, context, resizer)
override def createRoute(routeeProps: Props, routeeProvider: RouteeProvider): Route = {
local.createRoute(routeeProps, routeeProvider)
}
override def createActor(): Router = local.createActor()
override def supervisorStrategy: SupervisorStrategy = local.supervisorStrategy
override def routerDispatcher: String = local.routerDispatcher
override def resizer: Option[Resizer] = local.resizer
override def withFallback(other: RouterConfig): RouterConfig = other match {
case RemoteRouterConfig(local, nodes) copy(local = this.local.withFallback(local))
case _ this
}
}
/**
* Factory and registry for routees of the router.
* Deploys new routees on the specified `nodes`, round-robin.
*
* Routee paths may not be combined with remote target nodes.
*/
class RemoteRouteeProvider(nodes: Iterable[String], _context: ActorContext, _resizer: Option[Resizer])
extends RouteeProvider(_context, _resizer) {
// need this iterator as instance variable since Resizer may call createRoutees several times
private val nodeAddressIter = {
val nodeAddresses = nodes map {
case AddressExtractor(a) a
case x throw new ConfigurationException("unparseable remote node " + x)
}
Stream.continually(nodeAddresses).flatten.iterator
}
override def createRoutees(props: Props, nrOfInstances: Int, routees: Iterable[String]): IndexedSeq[ActorRef] =
(nrOfInstances, routees, nodes) match {
case (_, _, Nil) throw new ConfigurationException("Must specify list of remote target.nodes for [%s]"
format context.self.path.toString)
case (n, Nil, ys)
val impl = context.system.asInstanceOf[ActorSystemImpl] //TODO ticket #1559
IndexedSeq.empty[ActorRef] ++ (for (i 1 to nrOfInstances) yield {
val name = "c" + i
val deploy = Deploy("", ConfigFactory.empty(), props.routerConfig, RemoteScope(nodeAddressIter.next))
impl.provider.actorOf(impl, props, context.self.asInstanceOf[InternalActorRef], context.self.path / name, false, Some(deploy), false)
})
case (_, xs, _) throw new ConfigurationException("Remote target.nodes can not be combined with routees for [%s]"
format context.self.path.toString)
}
}