[ISSUE #10582] Fix POP revive offset comparator overflow#10583
Conversation
POP revive checkpoints are ordered by reviveOffset before mergeAndRevive advances through the pending checkpoints. The previous comparator subtracted two long offsets and cast the result to int, so large offset gaps could reverse the intended ordering. Use Comparator.comparingLong to preserve the full long ordering and add a regression test covering offsets separated by more than Integer.MAX_VALUE. Constraint: reviveOffset is a long queue offset and can exceed int comparison range Rejected: Keep subtraction with a wider cast | Comparator APIs express the ordering directly and avoid overflow Confidence: high Scope-risk: narrow Directive: Do not compare long queue offsets by subtraction in POP revive ordering Tested: mvn -pl broker -Dtest=PopReviveServiceTest test -Dspotbugs.skip=true -Dcheckstyle.skip=true Tested: git diff --check
There was a problem hiding this comment.
Pull request overview
Fixes incorrect POP revive checkpoint ordering caused by an overflow-prone comparator in PopReviveService.ConsumeReviveObj#genSortList(), ensuring revive offsets are always sorted by their full long value.
Changes:
- Replaced
(int) (o1.getReviveOffset() - o2.getReviveOffset())comparator withComparator.comparingLong(PopCheckPoint::getReviveOffset)to prevent overflow and wrong ordering. - Added a regression test covering revive offsets that differ by more than
Integer.MAX_VALUE.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java | Uses a safe long comparator to sort revive checkpoints deterministically without overflow. |
| broker/src/test/java/org/apache/rocketmq/broker/processor/PopReviveServiceTest.java | Adds a regression test that would fail with the old overflow-prone comparator. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #10583 +/- ##
=============================================
- Coverage 48.26% 48.15% -0.11%
+ Complexity 13433 13409 -24
=============================================
Files 1378 1378
Lines 100817 100820 +3
Branches 13040 13041 +1
=============================================
- Hits 48660 48553 -107
- Misses 46211 46301 +90
- Partials 5946 5966 +20 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
PopReviveService keeps inflight checkpoints in a TreeMap<PopCheckPoint, ...> (inflightReviveRequestMap), which orders keys via PopCheckPoint.compareTo. That comparator subtracted two long startOffsets and cast the result to int, the same overflow pattern already fixed for the reviveOffset sort in the prior commit. With large offset gaps the TreeMap could misorder keys and corrupt the revive ordering. Use Long.compare to preserve the full long ordering and add a regression test covering startOffsets separated by more than Integer.MAX_VALUE, including TreeMap ordering which exercises the actual PopReviveService usage. Constraint: startOffset is a long queue offset and can exceed int comparison range Rejected: Keep subtraction with a wider cast | Long.compare expresses the ordering directly and avoids overflow Confidence: high Scope-risk: narrow Directive: Do not compare long queue offsets by subtraction in POP checkpoint ordering Tested: mvn -pl store -Dtest=PopCheckPointTest test Tested: git diff --check Co-Authored-By: Claude <noreply@anthropic.com>
Review by github-manager-botSummaryThis PR fixes integer overflow bugs in two comparators related to POP revive checkpoint ordering:
Both used Correctness ✅Both fixes are correct:
The Performance ✅
Tests ✅
Compatibility ✅No API changes. VerdictApproved. Clean, focused fix for a subtle overflow bug that could cause incorrect checkpoint ordering in production when revive offsets span a wide range. |
Which Issue(s) This PR Fixes
Brief Description
This PR fixes the POP revive checkpoint ordering comparator in
PopReviveService.ConsumeReviveObj#genSortList().The previous implementation subtracted two long
reviveOffsetvalues and cast the result toint:When the offset gap is larger than
Integer.MAX_VALUE, the cast can overflow and return the wrong ordering. Since the sorted checkpoint list is consumed bymergeAndRevive(), this can cause POP revive checkpoints to be processed out of order.The comparator now uses
Comparator.comparingLong(PopCheckPoint::getReviveOffset)so the full long value is compared safely. A regression test covers two checkpoints whose revive offsets differ by more thanInteger.MAX_VALUE.How Did You Test This Change?
mvn -pl broker -Dtest=PopReviveServiceTest test -Dspotbugs.skip=true -Dcheckstyle.skip=truegit diff --check