Runtime platform environment
All platforms; reproduced by a deterministic unit test on the current develop branch.
RocketMQ version
develop at e3458616d207ee636b1762f0f8dcf788a590d59d.
Describe the Bug
Both the Java producer and Proxy availability detectors select a cached topic by first checking whether a concurrent map is empty and then creating a new iterator and immediately calling next().
If the final cache entry is evicted between the two operations, next() throws NoSuchElementException. The client path is DefaultMQProducerImpl.pickTopic; the Proxy has the same pattern in TopicRouteService.pickTopic.
Steps to Reproduce
- Populate the producer topic cache with one entry.
- Simulate eviction immediately after
isEmpty() returns false.
- Invoke
pickTopic through the availability detector helper.
- Observe
NoSuchElementException.
Expected Behavior
A cache that becomes empty during candidate selection returns an empty Optional, causing the detector to report no candidate rather than throwing.
Actual Behavior
Candidate selection throws before the detector can return a normal unavailable result.
Proposed Fix
Use one iterator and check hasNext() before calling next() in both Client and Proxy implementations. Add a regression test for the Client implementation.
Runtime platform environment
All platforms; reproduced by a deterministic unit test on the current
developbranch.RocketMQ version
developate3458616d207ee636b1762f0f8dcf788a590d59d.Describe the Bug
Both the Java producer and Proxy availability detectors select a cached topic by first checking whether a concurrent map is empty and then creating a new iterator and immediately calling
next().If the final cache entry is evicted between the two operations,
next()throwsNoSuchElementException. The client path isDefaultMQProducerImpl.pickTopic; the Proxy has the same pattern inTopicRouteService.pickTopic.Steps to Reproduce
isEmpty()returns false.pickTopicthrough the availability detector helper.NoSuchElementException.Expected Behavior
A cache that becomes empty during candidate selection returns an empty
Optional, causing the detector to report no candidate rather than throwing.Actual Behavior
Candidate selection throws before the detector can return a normal unavailable result.
Proposed Fix
Use one iterator and check
hasNext()before callingnext()in both Client and Proxy implementations. Add a regression test for the Client implementation.