-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-9130: KIP-518 Allow listing consumer groups per state #8238
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
Changes from 9 commits
88e7a0c
143514c
badbc1a
b243a61
145b689
a0247b0
4bed4d3
d6102e8
5854e56
1f032e7
499b15b
56f839a
5e18e5c
acb64f3
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 |
|---|---|---|
|
|
@@ -17,22 +17,30 @@ | |
|
|
||
| package org.apache.kafka.clients.admin; | ||
|
|
||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
|
|
||
| import org.apache.kafka.common.ConsumerGroupState; | ||
|
|
||
| /** | ||
| * A listing of a consumer group in the cluster. | ||
| */ | ||
| public class ConsumerGroupListing { | ||
| private final String groupId; | ||
| private final boolean isSimpleConsumerGroup; | ||
| private final Optional<ConsumerGroupState> state; | ||
|
|
||
| /** | ||
| * Create an instance with the specified parameters. | ||
| * | ||
| * @param groupId Group Id | ||
| * @param isSimpleConsumerGroup If consumer group is simple or not. | ||
| * @param state The state of the consumer group | ||
| */ | ||
| public ConsumerGroupListing(String groupId, boolean isSimpleConsumerGroup) { | ||
| public ConsumerGroupListing(String groupId, boolean isSimpleConsumerGroup, Optional<ConsumerGroupState> state) { | ||
| this.groupId = groupId; | ||
| this.isSimpleConsumerGroup = isSimpleConsumerGroup; | ||
| this.state = state; | ||
|
mimaison marked this conversation as resolved.
Outdated
Contributor
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. nit: usually we would write this is |
||
| } | ||
|
|
||
| /** | ||
|
|
@@ -49,11 +57,49 @@ public boolean isSimpleConsumerGroup() { | |
| return isSimpleConsumerGroup; | ||
| } | ||
|
|
||
| /** | ||
| * Consumer Group state | ||
| */ | ||
| public Optional<ConsumerGroupState> state() { | ||
| return state; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "(" + | ||
| "groupId='" + groupId + '\'' + | ||
| ", isSimpleConsumerGroup=" + isSimpleConsumerGroup + | ||
| ", state=" + state + | ||
| ')'; | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(groupId, isSimpleConsumerGroup, state); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object obj) { | ||
| if (this == obj) | ||
| return true; | ||
| if (obj == null) | ||
| return false; | ||
| if (getClass() != obj.getClass()) | ||
| return false; | ||
| ConsumerGroupListing other = (ConsumerGroupListing) obj; | ||
| if (groupId == null) { | ||
| if (other.groupId != null) | ||
| return false; | ||
| } else if (!groupId.equals(other.groupId)) | ||
| return false; | ||
| if (isSimpleConsumerGroup != other.isSimpleConsumerGroup) | ||
| return false; | ||
| if (state == null) { | ||
| if (other.state != null) | ||
| return false; | ||
| } else if (!state.equals(other.state)) | ||
| return false; | ||
| return true; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,11 @@ | |
|
|
||
| package org.apache.kafka.clients.admin; | ||
|
|
||
| import java.util.EnumSet; | ||
| import java.util.Optional; | ||
| import java.util.Set; | ||
|
|
||
| import org.apache.kafka.common.ConsumerGroupState; | ||
| import org.apache.kafka.common.annotation.InterfaceStability; | ||
|
|
||
| /** | ||
|
|
@@ -26,4 +31,34 @@ | |
| */ | ||
| @InterfaceStability.Evolving | ||
| public class ListConsumerGroupsOptions extends AbstractOptions<ListConsumerGroupsOptions> { | ||
|
|
||
| private Optional<Set<ConsumerGroupState>> states = Optional.empty(); | ||
|
|
||
| /** | ||
| * Only groups in these states will be returned by listConsumerGroups() | ||
|
Contributor
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. Probably worth adding a comment about broker compatibility with this API.
Contributor
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. Can you address this comment? |
||
| * If not set, all groups are returned without their states | ||
| * throw IllegalArgumentException if states is empty | ||
| */ | ||
| public ListConsumerGroupsOptions inStates(Set<ConsumerGroupState> states) { | ||
| if (states == null || states.isEmpty()) { | ||
| throw new IllegalArgumentException("states should not be null or empty"); | ||
| } | ||
| this.states = Optional.of(states); | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * All groups with their states will be returned by listConsumerGroups() | ||
| */ | ||
| public ListConsumerGroupsOptions inAnyState() { | ||
|
mimaison marked this conversation as resolved.
Outdated
|
||
| this.states = Optional.of(EnumSet.allOf(ConsumerGroupState.class)); | ||
|
Contributor
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. Hmm.. We have an
Member
Author
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. That's a good point so I agree, it makes sense to return all states when
Member
Author
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. This can also be argued for the state value in the response. Currently |
||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the list of States that are requested | ||
| */ | ||
| public Optional<Set<ConsumerGroupState>> states() { | ||
| return states; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,8 +20,14 @@ | |
| // Version 1 and 2 are the same as version 0. | ||
| // | ||
| // Version 3 is the first flexible version. | ||
| "validVersions": "0-3", | ||
| // | ||
| // Version 4 adds the States flexible field (KIP-518). | ||
| "validVersions": "0-4", | ||
| "flexibleVersions": "3+", | ||
| "fields": [ | ||
| { "name": "States", "type": "[]string", "versions": "4+", "tag": 0, "taggedVersions": "4+", | ||
|
Contributor
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. Sorry I missed this from the discussion, but why are we bumping the version if we are only adding tagged fields? Is it so that we can detect whether the capability is supported? If so, then I wonder why we don't make this a regular field.
Member
Author
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. Yes the version bump is necessary to detect if this field was supported. As we're bumping the version and as you said in #8238 (comment) the overhead of the extra field on this API is not a concern, it's probably simpler to use a regular field. |
||
| "about": "The states of the groups we want to list. If empty, all groups are returned, without state.", "fields": [ | ||
| { "name": "Name", "type": "string", "versions": "4+", "about": "The group state" } | ||
| ]} | ||
| ] | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.