Merge pull request #1312 from akka/wip-2734-router-termination-patriknw

Don't stop dynamic router when all routees terminated, see #2734
This commit is contained in:
Patrik Nordwall 2013-04-08 12:37:16 -07:00
commit 52a6e6b23b
5 changed files with 39 additions and 6 deletions

View file

@ -100,6 +100,26 @@ class RoutingSpec extends AkkaSpec(RoutingSpec.config) with DefaultTimeout with
}
}
"not terminate when resizer is used" in {
val latch = TestLatch(1)
val resizer = new Resizer {
def isTimeForResize(messageCounter: Long): Boolean = messageCounter == 0
def resize(routeeProvider: RouteeProvider): Unit = {
routeeProvider.createRoutees(nrOfInstances = 2)
latch.countDown()
}
}
val router = system.actorOf(Props[TestActor].withRouter(RoundRobinRouter(resizer = Some(resizer))))
watch(router)
Await.ready(latch, remaining)
router ! CurrentRoutees
val routees = expectMsgType[RouterRoutees].routees
routees.size must be(2)
routees foreach system.stop
// expect no Terminated
expectNoMsg(2.seconds)
}
"be able to send their routees" in {
case class TestRun(id: String, names: immutable.Iterable[String], actors: Int)
val actor = system.actorOf(Props(new Actor {

View file

@ -215,6 +215,12 @@ trait RouterConfig {
*/
def verifyConfig(): Unit = ()
/*
* Specify that this router should stop itself when all routees have terminated (been removed).
* By Default it is `true`, unless a `resizer` is used.
*/
def stopRouterWhenAllRouteesRemoved: Boolean = resizer.isEmpty
}
/**
@ -376,7 +382,8 @@ trait Router extends Actor {
case Terminated(child)
ref.removeRoutees(child :: Nil)
if (ref.routees.isEmpty) context.stop(self)
if (ref.routees.isEmpty && ref.routerConfig.stopRouterWhenAllRouteesRemoved)
context.stop(self)
}: Receive) orElse routerReceive

View file

@ -60,6 +60,8 @@ final case class ClusterRouterConfig(local: RouterConfig, settings: ClusterRoute
override def resizer: Option[Resizer] = local.resizer
override def stopRouterWhenAllRouteesRemoved: Boolean = false
override def withFallback(other: RouterConfig): RouterConfig = other match {
case ClusterRouterConfig(_: RemoteRouterConfig, _) throw new IllegalStateException(
"ClusterRouterConfig is not allowed to wrap a RemoteRouterConfig")

View file

@ -149,7 +149,8 @@ direct children of their grand-parent instead.
If the child of a router terminates, the router will not automatically spawn
a new child. In the event that all children of a router have terminated the
router will terminate itself.
router will terminate itself, unless it is a dynamic router, e.g. using
a resizer.
Router usage
^^^^^^^^^^^^
@ -378,7 +379,7 @@ documentation for details.
.. includecode:: code/docs/jrouting/RouterViaProgramDocTestBase.java#poisonPill
For a router, which normally passes on messages to routees, it is important to realised that
For a router, which normally passes on messages to routees, it is important to realise that
``PoisonPill`` messages are processed by the router only. ``PoisonPill`` messages sent to a router
will *not* be sent on to routees.
@ -399,7 +400,8 @@ routees aren't children of the router, i.e. even routees programmatically provid
With the code shown above, each routee will receive a ``PoisonPill`` message. Each routee will
continue to process its messages as normal, eventually processing the ``PoisonPill``. This will
cause the routee to stop. After all routees have stopped the router will itself be :ref:`stopped
automatically <note-router-terminated-children-java>`.
automatically <note-router-terminated-children-java>` unless it is a dynamic router, e.g. using
a resizer.
.. note::

View file

@ -151,7 +151,8 @@ direct children of their grand-parent instead.
If the child of a router terminates, the router will not automatically spawn
a new child. In the event that all children of a router have terminated the
router will terminate itself.
router will terminate itself unless it is a dynamic router, e.g. using
a resizer.
Router usage
^^^^^^^^^^^^
@ -396,7 +397,8 @@ routees aren't children of the router, i.e. even routees programmatically provid
With the code shown above, each routee will receive a ``PoisonPill`` message. Each routee will
continue to process its messages as normal, eventually processing the ``PoisonPill``. This will
cause the routee to stop. After all routees have stopped the router will itself be :ref:`stopped
automatically <note-router-terminated-children-scala>`.
automatically <note-router-terminated-children-scala>` unless it is a dynamic router, e.g. using
a resizer.
.. note::