[BUG] Clearing one topic's forbidden bits wipes the whole group's forbidden table and skips persist - #11093
Open
zjncs wants to merge 1 commit into
Open
[BUG] Clearing one topic's forbidden bits wipes the whole group's forbidden table and skips persist#11093zjncs wants to merge 1 commit into
zjncs wants to merge 1 commit into
Conversation
…dden bits are cleared updateForbiddenValue removed the WHOLE group entry from forbiddenTable when a single topic's forbidden value dropped to 0, so clearing the read permission of one topic silently restored permissions for every other forbidden topic of the same group. The removal was also neither data-version-bumped nor persisted, so a restart or a config-syncing peer resurrected the stale bits. Remove only the topic's entry (and the empty group map once the last topic is gone), then bump the data version and persist, mirroring the set path. Signed-off-by: zjncs <18910855655@163.com>
RockteMQ-AI
approved these changes
Sep 9, 2026
RockteMQ-AI
left a comment
Contributor
There was a problem hiding this comment.
Summary
Correct fix for a data-loss bug in updateForbiddenValue. The original code removed the entire group entry when clearing any single topic's forbidden bit, silently dropping forbidden state for all other topics in the same group. The fix is precise and minimal.
Findings
- [Info]
SubscriptionGroupManager.java:229— Good use of the two-argConcurrentMap.remove(group, topicForbiddens)for atomic conditional removal. This avoids a TOCTOU race where another thread could have already replaced the map. - [Info] The no-op guard (
topicForbiddens.remove(topic) != null) correctly prevents spurious data-version bumps and persists when the topic was never forbidden. Clean. - [Info] The regression test is thorough — it verifies cross-topic isolation, data-version bump, and full cleanup when the last topic is cleared.
Verdict
LGTM. The fix correctly scopes the removal to a single topic, ensures durability via updateDataVersion() + persist(), and the test covers the exact failure mode described in the issue.
Automated review by github-manager-bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
SubscriptionGroupManager.updateForbiddenValuehandles a forbidden value of 0 (i.e.clearForbiddenreleased the last forbidden bit of a topic) by removing the whole group fromforbiddenTable:Two problems:
AdminBrokerProcessor.updateForbidden/ the dashboard's per-topic perm toggle hit exactly this path.)updateDataVersion()norpersist(), so after a broker restart the stale forbidden state comes back from disk, and peers syncing viaGET_ALL_SUBSCRIPTIONGROUP_CONFIGsee an unchanged data version and keep the old bits.Changes
In the
forbidden <= 0branch: remove only the given topic's entry from the group's map (dropping the now-empty group map when the last topic is gone), thenupdateDataVersion()+persist(), mirroring the set path. A clear of a topic that was never forbidden stays a no-op (no spurious version bump).Verification
New regression test
ForbiddenTest#testClearOneTopicForbiddenKeepsOtherTopicsOfTheSameGroup: forbidst1/t2of one group, clearst1, and assertst2keeps its forbidden bit, the table shrinks to the single remaining entry, the data version counter is bumped, and clearing the last topic removes the group entry.