He-Pin opened a new issue, #3362:
URL: https://github.com/apache/pekko/issues/3362
### Summary
`AdjustPoolSize` sent to a `ClusterRouterPool` can create a local routee
without applying the cluster pool's deployment constraints. In particular, it
can create a local child when `allowLocalRoutees` is `false`. The same
inherited path also does not consult `useRoles`, `totalInstances`, or
`maxInstancesPerNode`.
### Reproducer
On current `main` (`1fa250d450e18bbebd0374378b6e2a8069473e46`), this
directional test in `ClusterRouterSupervisorSpec` exposes the issue:
```scala
import pekko.routing.{ AdjustPoolSize, GetRoutees, Routees, RoundRobinPool }
"not create a local routee through AdjustPoolSize when local routees are
disabled" in {
val router = system.actorOf(
ClusterRouterPool(
RoundRobinPool(nrOfInstances = 0),
ClusterRouterPoolSettings(
totalInstances = 1,
maxInstancesPerNode = 1,
allowLocalRoutees = false))
.props(Props(classOf[KillableActor])))
router ! AdjustPoolSize(1)
router ! GetRoutees
expectMsg(Routees(Vector.empty))
}
```
Run with JDK 17:
```text
sbt "cluster / Test / testOnly
org.apache.pekko.cluster.routing.ClusterRouterSupervisorSpec"
```
The assertion fails because a local routee named `c1` is present:
```text
expected Routees(Vector()), found
Routees(Vector(ActorRefRoutee(Actor[pekko://.../c1])))
```
### Cause
`ClusterRouterPoolActor` inherits `RouterPoolActor` and delegates unmatched
messages, including `AdjustPoolSize`, to `super.receive`:
-
https://github.com/apache/pekko/blob/1fa250d450e18bbebd0374378b6e2a8069473e46/cluster/src/main/scala/org/apache/pekko/cluster/routing/ClusterRouterConfig.scala#L403-L409
The inherited handler calls `pool.newRoutee` directly for each requested
addition:
-
https://github.com/apache/pekko/blob/1fa250d450e18bbebd0374378b6e2a8069473e46/actor/src/main/scala/org/apache/pekko/routing/RoutedActorCell.scala#L203-L214
For a `ClusterRouterPool`, `newRoutee` attaches a local child without
checking cluster settings:
-
https://github.com/apache/pekko/blob/1fa250d450e18bbebd0374378b6e2a8069473e46/cluster/src/main/scala/org/apache/pekko/cluster/routing/ClusterRouterConfig.scala#L342-L360
In contrast, the normal cluster-pool allocation path calls
`selectDeploymentTarget`, which applies available-node, total-instance, and
per-node limits:
-
https://github.com/apache/pekko/blob/1fa250d450e18bbebd0374378b6e2a8069473e46/cluster/src/main/scala/org/apache/pekko/cluster/routing/ClusterRouterConfig.scala#L411-L450
The documentation also states that `max-nr-of-instances-per-node` will not
be exceeded:
-
https://github.com/apache/pekko/blob/1fa250d450e18bbebd0374378b6e2a8069473e46/docs/src/main/paradox/cluster-routing.md#L171-L177
### Expected behavior
`AdjustPoolSize` must not create a routee on a node excluded by
`allowLocalRoutees` or `useRoles`, and must not silently bypass cluster pool
limits.
The exact management semantics need a maintainer decision. Possible
approaches include rejecting/ignoring `AdjustPoolSize` for cluster pools, or
interpreting it through the cluster allocation path while preserving
`totalInstances` and `maxInstancesPerNode`.
### Additional context
This was found while investigating #3253. It is separate from the generic
pool/resizer-bounds question there: the generic `AdjustPoolSize` contract is a
direct management override, whereas cluster deployment settings describe node
eligibility and per-node limits.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]