-
Notifications
You must be signed in to change notification settings - Fork 0
KAFKA-19164: Keep track of groups when deleting transactional offsets #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -198,12 +198,19 @@ public OffsetMetadataManager build() { | |||||||||||||||||||||
| private final TimelineHashMap<String, TimelineHashSet<Long>> openTransactionsByGroup; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private class Offsets { | ||||||||||||||||||||||
| /** | ||||||||||||||||||||||
| * Whether to preserve empty entries for groups when removing offsets. | ||||||||||||||||||||||
| * We use this to keep track of the groups associated with pending transactions. | ||||||||||||||||||||||
| */ | ||||||||||||||||||||||
| private final boolean preserveGroups; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /** | ||||||||||||||||||||||
| * The offsets keyed by group id, topic name and partition id. | ||||||||||||||||||||||
| */ | ||||||||||||||||||||||
| private final TimelineHashMap<String, TimelineHashMap<String, TimelineHashMap<Integer, OffsetAndMetadata>>> offsetsByGroup; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private Offsets() { | ||||||||||||||||||||||
| private Offsets(boolean preserveGroups) { | ||||||||||||||||||||||
| this.preserveGroups = preserveGroups; | ||||||||||||||||||||||
| this.offsetsByGroup = new TimelineHashMap<>(snapshotRegistry, 0); | ||||||||||||||||||||||
|
Comment on lines
+212
to
214
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uninitialized Flag ParameterThe Offsets constructor was modified to accept a preserveGroups parameter but the original constructor call at line 288 passes false without explanation. This could lead to inconsistent group preservation behavior. Standards
Comment on lines
+201
to
214
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Insufficient Constructor DocumentationThe constructor parameter is documented but lacks explanation of when to use true/false values and their implications. This makes future modifications risky as developers may not understand the full impact of this parameter. Standards
Comment on lines
+212
to
214
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Boolean Parameter ClarityBoolean parameter lacks semantic clarity, making intention hard to understand from call sites. Consider using a more descriptive enum or builder pattern to make the parameter's purpose self-documenting. Standards
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -256,7 +263,7 @@ private OffsetAndMetadata remove( | |||||||||||||||||||||
| if (partitionOffsets.isEmpty()) | ||||||||||||||||||||||
| topicOffsets.remove(topic); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if (topicOffsets.isEmpty()) | ||||||||||||||||||||||
| if (!preserveGroups && topicOffsets.isEmpty()) | ||||||||||||||||||||||
| offsetsByGroup.remove(groupId); | ||||||||||||||||||||||
|
Comment on lines
+266
to
267
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Group Preservation OverheadThe
Suggested change
Standards
Comment on lines
+266
to
267
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Group Preservation LogicThe original code incorrectly removed groups with empty topic offsets even when they had pending transactions. This could cause premature group deletion and data inconsistency when transactions complete later.
Suggested change
Standards
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return removedValue; | ||||||||||||||||||||||
|
|
@@ -278,7 +285,7 @@ private OffsetAndMetadata remove( | |||||||||||||||||||||
| this.groupMetadataManager = groupMetadataManager; | ||||||||||||||||||||||
| this.config = config; | ||||||||||||||||||||||
| this.metrics = metrics; | ||||||||||||||||||||||
| this.offsets = new Offsets(); | ||||||||||||||||||||||
| this.offsets = new Offsets(false); | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing Constructor ParameterThe Offsets constructor is modified to take a boolean parameter, but the main offsets instance is initialized with the parameterless constructor which no longer exists. This would cause compilation failure since the constructor signature has changed. Standards
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing Group PreservationMain offsets store initialized with preserveGroups=false while pending transactional offsets use true. Inconsistent behavior could lead to premature group deletion.
Suggested change
Standards
|
||||||||||||||||||||||
| this.pendingTransactionalOffsets = new TimelineHashMap<>(snapshotRegistry, 0); | ||||||||||||||||||||||
| this.openTransactionsByGroup = new TimelineHashMap<>(snapshotRegistry, 0); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
@@ -995,7 +1002,7 @@ public void replay( | |||||||||||||||||||||
| // offsets store. Pending offsets there are moved to the main store when | ||||||||||||||||||||||
| // the transaction is committed; or removed when the transaction is aborted. | ||||||||||||||||||||||
| pendingTransactionalOffsets | ||||||||||||||||||||||
| .computeIfAbsent(producerId, __ -> new Offsets()) | ||||||||||||||||||||||
| .computeIfAbsent(producerId, __ -> new Offsets(true)) | ||||||||||||||||||||||
| .put( | ||||||||||||||||||||||
| groupId, | ||||||||||||||||||||||
| topic, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential Resource Exhaustion
Preserving empty group entries indefinitely could lead to memory exhaustion. Attackers could create numerous groups with pending transactions, depleting coordinator resources.
Standards