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:
commit
52a6e6b23b
5 changed files with 39 additions and 6 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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::
|
||||
|
||||
|
|
|
|||
|
|
@ -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::
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue