He-Pin opened a new pull request, #3098:
URL: https://github.com/apache/pekko/pull/3098
### Motivation
The "must be able to send messages with actorSelection concurrently
preserving order" test flakes on CI: 4 sender actors each drive 1000
round-trips via `ActorSelection` (4004 messages total). With multi-lane artery
config (`outbound-lanes > 1`), all `ActorSelection` messages are routed to the
same outbound queue because `selectQueue` uses the anchor's UID as the
distribution key:
```scala
OrdinaryQueueIndex + (math.abs(r.path.uid % outboundLanes))
```
The anchor for `ActorSelection` is the root guardian (`RootActorPath`),
whose UID is always `0` (`ActorCell.undefinedUid`). So `math.abs(0 % N) = 0`
for any N — all `ActorSelection` traffic concentrates on lane 0 while other
lanes sit idle.
Similarly, inbound lane partitioning uses the wire recipient's UID (root
guardian = 0), concentrating all inbound `ActorSelection` processing on a
single inbound lane.
This is **not a recent regression** — the `selectQueue` logic has been
unchanged since the Pekko fork from Akka.
### Modification
**Outbound** (`Association.send`): Add a dedicated `case sel:
ActorSelectionMessage` that computes the queue index from the selection's
target path elements hash instead of the anchor's UID:
```scala
case sel: ActorSelectionMessage =>
sel.msg match {
case _: PriorityMessage =>
// cluster heartbeats stay on control queue
controlQueue.offer(outboundEnvelope)
case _ =>
val queueIndex =
if (outboundLanes == 1) OrdinaryQueueIndex
else OrdinaryQueueIndex + ((sel.elements.hashCode() & Int.MaxValue)
% outboundLanes)
queues(queueIndex).offer(outboundEnvelope)
}
```
**Inbound** (`ArteryTransport.inboundLanePartitioner`): Parse the
`ActorSelectionMessage`'s target path from the envelope byte buffer and use it
as the destination hash key, distributing inbound ActorSelection processing
across all inbound lanes.
`PriorityMessage` ActorSelection (used by cluster heartbeats) continues to
go through the control queue unchanged.
### Result
ActorSelection messages are distributed across all outbound and inbound
lanes based on target path, eliminating the single-lane throughput bottleneck
while preserving per-path message ordering (same target path → same hash → same
lane).
### Tests
```
sbt -Dpekko.test.timefactor=2 "remote / Test / testOnly *SendConsistency*"
→ 24/24 passed (all 6 spec variants: Upd/Tcp/TlsTcp × 1-lane/3-lanes)
sbt "remote / mimaReportBinaryIssues" → clean
```
### References
Fixes #3089
--
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]