unbridled-41 opened a new pull request, #11042:
URL: https://github.com/apache/rocketmq/pull/11042
### Problem / Evidence
The split-metadata pagination loops terminate one entry too early. The
client loops in `MQClientAPIImpl#getAllTopicConfig` /
`#getAllSubscriptionGroup` break on `topicSeq >= totalTopicNum - 1` / `groupSeq
>= totalGroupNum - 1`, while the broker pages `[seq, seq + maxNum)` with no
overlap (`TopicConfigManager#subTopicConfig`,
`SubscriptionGroupManager#subGroupTable`, `totalTopicNum = size()`).
After page k the client holds `k·pageSize` entries, so the loop stops as
soon as `k·pageSize >= N − 1` — which is already true when exactly one entry
remains unfetched, i.e. for every **N ≡ 1 (mod pageSize)**. Example: 2001
topics with the default page size 2000 → page 1 returns 2000 entries, `2000 >=
2001 − 1` holds, the loop breaks, topic #2001 is never requested. No error, no
retry — silently truncated metadata.
The identical off-by-one exists in `BrokerOuterAPI#getAllTopicConfig` (used
by `SlaveSynchronize#syncTopicConfig`) and
`BrokerOuterAPI#getAllSubscriptionGroup`: a slave whose master has N ≡ 1 (mod
2000) topics permanently misses the last topic — and the dataVersion comparison
then matches, so no later resync repairs it.
Regression tests
`MQClientAPIImplTest#testGetAllTopicConfigFetchesLastEntryWhenTotalIsOneOverPageSize`
and `#testGetAllSubscriptionGroupFetchesLastEntryWhenTotalIsOneOverPageSize`
fail before the fix (`expected:<101> but was:<100>`) and pass after.
### Root cause / Fix
Terminate when `seq >= totalNum`. When the page completes the set the
condition still breaks immediately; when exactly one entry remains it now
continues and fetches the final page (a subsequent empty page still terminates
because `seq >= totalNum` remains true). Applied to all four occurrences of the
same defect: `MQClientAPIImpl` (topic + subscription group) and
`BrokerOuterAPI` (topic + subscription group).
### Priority
PRIORITY = 74:影响 28(静默元数据截断——mqadmin 导出/同步工具丢最后一个 topic/消费组,SlaveSynchronize
全量同步永久缺最新 topic 且不会自愈)+ 波及范围 14(4 处同类循环、client+broker 两端)+ 可复现性 20(确定性单元测试,N =
pageSize + 1 边界)+ 维护价值 12(一行终止条件 ×4)。FIX_CONFIDENCE = 90。
### Tests
- `mvn -pl client test
-Dtest=MQClientAPIImplTest#testGetAllTopicConfigFetchesLastEntryWhenTotalIsOneOverPageSize`
- before fix (ff8f6f74c + test only): `Tests run: 1, Failures: 1` —
`expected:<101> but was:<100>`
- after fix: `Tests run: 1, Failures: 0`
- same for
`testGetAllSubscriptionGroupFetchesLastEntryWhenTotalIsOneOverPageSize`
- `mvn -pl client test -Dtest=MQClientAPIImplTest`: `Tests run: 135,
Failures: 0, Errors: 0`
- `mvn -pl broker compile`: OK (BrokerOuterAPI change)
### Risk
Low. The only behavior change is that exactly one extra page request is
issued in the boundary case (and none in any other case — for all other N the
old and new conditions break at the same page). Old-version brokers that do not
return `totalTopicNum`/`totalGroupNum` are unaffected (the null-compatibility
break precedes this condition).
--
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]