Don't stop dynamic router when all routees terminated, see #2734

This commit is contained in:
Patrik Nordwall 2013-04-08 13:19:44 +02:00
parent 3ee42dbe11
commit accdd63e7d
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 { "be able to send their routees" in {
case class TestRun(id: String, names: immutable.Iterable[String], actors: Int) case class TestRun(id: String, names: immutable.Iterable[String], actors: Int)
val actor = system.actorOf(Props(new Actor { val actor = system.actorOf(Props(new Actor {

View file

@ -215,6 +215,12 @@ trait RouterConfig {
*/ */
def verifyConfig(): Unit = () 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
} }
/** /**
@ -373,7 +379,8 @@ trait Router extends Actor {
case Terminated(child) case Terminated(child)
ref.removeRoutees(child :: Nil) ref.removeRoutees(child :: Nil)
if (ref.routees.isEmpty) context.stop(self) if (ref.routees.isEmpty && ref.routerConfig.stopRouterWhenAllRouteesRemoved)
context.stop(self)
}: Receive) orElse routerReceive }: 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 resizer: Option[Resizer] = local.resizer
override def stopRouterWhenAllRouteesRemoved: Boolean = false
override def withFallback(other: RouterConfig): RouterConfig = other match { override def withFallback(other: RouterConfig): RouterConfig = other match {
case ClusterRouterConfig(_: RemoteRouterConfig, _) throw new IllegalStateException( case ClusterRouterConfig(_: RemoteRouterConfig, _) throw new IllegalStateException(
"ClusterRouterConfig is not allowed to wrap a RemoteRouterConfig") "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 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 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 Router usage
^^^^^^^^^^^^ ^^^^^^^^^^^^
@ -378,7 +379,7 @@ documentation for details.
.. includecode:: code/docs/jrouting/RouterViaProgramDocTestBase.java#poisonPill .. 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 ``PoisonPill`` messages are processed by the router only. ``PoisonPill`` messages sent to a router
will *not* be sent on to routees. 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 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 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 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:: .. 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 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 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 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 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 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 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:: .. note::