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]

Reply via email to