-
Notifications
You must be signed in to change notification settings - Fork 14.8k
KAFKA-18323: Add StreamsGroup class #18729
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
Conversation
b9894e7 to
ad4f4f3
Compare
|
Rebased on latest target assignment builder |
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.
Copilot reviewed 8 out of 16 changed files in this pull request and generated 1 comment.
Files not reviewed (8)
- group-coordinator/src/main/java/org/apache/kafka/coordinator/group/metrics/GroupCoordinatorMetrics.java: Evaluated as low risk
- group-coordinator/src/main/java/org/apache/kafka/coordinator/group/metrics/GroupCoordinatorMetricsShard.java: Evaluated as low risk
- group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/TargetAssignmentBuilder.java: Evaluated as low risk
- group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/assignor/MockAssignor.java: Evaluated as low risk
- group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/topics/ConfiguredTopology.java: Evaluated as low risk
- group-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/assignor/MockAssignorTest.java: Evaluated as low risk
- group-coordinator/src/main/java/org/apache/kafka/coordinator/group/Group.java: Evaluated as low risk
- group-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/topics/ConfiguredTopologyTest.java: Evaluated as low risk
Comments suppressed due to low confidence (1)
group-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/TopologyMetadataTest.java:126
- The method name testNumTasksThrowsExceptionWhenTopologyNotConfigured is inconsistent with the actual method being tested (maxNumInputPartitions). It should be renamed to testMaxNumInputPartitionsThrowsExceptionWhenTopologyNotConfigured.
void testNumTasksThrowsExceptionWhenTopologyNotConfigured() {
...or/src/main/java/org/apache/kafka/coordinator/group/streams/topics/InternalTopicManager.java
Show resolved
Hide resolved
ad4f4f3 to
ab70816
Compare
ab70816 to
8866781
Compare
|
Rebased on latest trunk |
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.
Thanks for the PR, @lucasbru !
I did a first pass over the production code.
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> invertedTargetActiveTasksAssignment; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> invertedTargetStandbyTasksAssignment; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> invertedTargetWarmupTasksAssignment; |
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.
Could you please add some more info to the javadoc? This data structure is a bit hard to grasp.
A visualization like the following would help:
subtopology -> partition -> memberId
I am wondering if using a class like TaskId for the key would make the code simpler.
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.
What do you think of renaming this data structures to currrentXTaskToMemberId?
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.
Hmm, this is not used at all right now. In the consumer group, this is used to optimize the assignor, but we don't use it in our assignors. I think I will remove it for now, we can bring it back once we optimize the assignors.
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> currentActiveTaskProcessId; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, Set<String>>> currentStandbyTaskProcessIds; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, Set<String>>> currentWarmupTaskProcessIds; |
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.
The above comment also applies to this data structure.
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.
What do you think of renaming this data structures to currrentXTaskToProcessId?
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.
Done
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.
I agree with Bruno about a slight renaming for clarity.
| } | ||
|
|
||
| /** | ||
| * @return An immutable Map containing all the target assignment keyed by member id. |
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.
| * @return An immutable Map containing all the target assignment keyed by member id. | |
| * @return An immutable map containing all the target assignment keyed by member ID. |
Here and elsewhere
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.
Done
| /** | ||
| * Removes the target assignment of a member. | ||
| * | ||
| * @param memberId The member id. |
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.
| * @param memberId The member id. | |
| * @param memberId The member ID. |
Here and in other java docs.
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.
Done
| } | ||
|
|
||
| /** | ||
| * Returns the current processId of a task or null if the task does not have one. |
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.
| * Returns the current processId of a task or null if the task does not have one. | |
| * Returns the current process ID of a task or null if the task does not have one. |
Here and in other places.
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.
Done
| if (tasks == null) { | ||
| return null; | ||
| } else { | ||
| return tasks.getOrDefault(taskId, null); | ||
| } |
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.
Does it make sense to change this to Optional?
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.
I think this may have to checked in tight loops inside the assignor. I think it's a good place to avoid creating extra objects just for returning a value.
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.
I made a pass over the test code.
| } | ||
|
|
||
| @Test | ||
| public void testAsListedGroup() { |
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.
I do not understand this test. The test name is testAsListedGroup() but the method asListedGroup() is never called.
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.
Yes, you are right. This is what is being tested in the other groups as well, interestingly. I think what is being tested here is covered by other tests already. I replaced it by a test that makes sense to me.
| .setGroupType(type().toString()); | ||
| } | ||
|
|
||
| public ConfiguredTopology configuredTopology() { |
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.
Would it make sense to return the Optional here?
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.
Let's try it.
| return configuredTopology.get().orElse(null); | ||
| } | ||
|
|
||
| public StreamsTopology topology() { |
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.
Would it make sense to return the Optional here?
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.
Let's try it
| return topology.get().orElse(null); | ||
| } | ||
|
|
||
| public void setTopology(StreamsTopology topology) { |
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.
Could you please add a test that verifies that the configured topology is updated?
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.
Done
| * @param groupInstanceId The group instance id. | ||
| * @return The member id corresponding to the given instance id or null if it does not exist | ||
| */ | ||
| public String staticMemberId(String groupInstanceId) { |
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.
Maybe also here we might want to return an Optional. However, we can postpone this decision to when we will use this method in the handlers.
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.
Yes, let's postpone it.
| } | ||
|
|
||
| @Test | ||
| public void testUpdateInvertedAssignment() { |
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.
Could you please also add a case where the subtopology ID is modified?
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.
I removed the interverted assignment because we are not using it (yet)
| * | ||
| * @param partitionMetadata The new partition metadata. | ||
| */ | ||
| public void setPartitionMetadata( |
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.
Could you add unit test for this?
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.
Done
| * @param clusterImage The current metadata for the Kafka cluster. | ||
| * @return An immutable map of partition metadata for each topic that the streams topology is using (besides non-repartition sink topics) | ||
| */ | ||
| public Map<String, TopicMetadata> computePartitionMetadata( |
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.
I assume that this will be used in the future. Could you please add unit tests?
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.
Yes. I also realized that the rack information that we included here for future proofing (but not rack-aware assignment is currently done / planned) was removed from consumer groups due to the memory pressure it caused. I also updated this to not include the rack information. We can always bring it back in the future. This required some additional changes (but only removals).
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.
The part of the GroupMetadataManager that calls this method is a bit weird. The group computes and returns the partition metadata so that the computed partition metadata can be passed back into the group. We should consider simplifying that part when we get to the GroupMetadataManager.
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsGroup.java
Show resolved
Hide resolved
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsGroup.java
Show resolved
Hide resolved
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.
Thanks for the PR @lucasbru - I don't have any additional comments beyond what Bruno has, overall this looks good to me modulo addressing those comments.
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> currentActiveTaskProcessId; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, Set<String>>> currentStandbyTaskProcessIds; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, Set<String>>> currentWarmupTaskProcessIds; |
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.
I agree with Bruno about a slight renaming for clarity.
| /** | ||
| * @return The current state based on committed offset. | ||
| */ | ||
| public StreamsGroupState state(long committedOffset) { |
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.
When is this method called? How often is the offset updated? From the parameter name, I'm inferring that it occurs after every commit
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.
It's not really called. We always get the latest state, although we can get the state at every committed offset of the consumer offset topic. I removed it, we can always bring it back
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.
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> invertedTargetActiveTasksAssignment; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> invertedTargetStandbyTasksAssignment; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> invertedTargetWarmupTasksAssignment; |
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.
Hmm, this is not used at all right now. In the consumer group, this is used to optimize the assignor, but we don't use it in our assignors. I think I will remove it for now, we can bring it back once we optimize the assignors.
| private final TimelineHashMap<String, TimelineHashMap<Integer, String>> currentActiveTaskProcessId; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, Set<String>>> currentStandbyTaskProcessIds; | ||
| private final TimelineHashMap<String, TimelineHashMap<Integer, Set<String>>> currentWarmupTaskProcessIds; |
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.
Done
| .setGroupType(type().toString()); | ||
| } | ||
|
|
||
| public ConfiguredTopology configuredTopology() { |
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.
Let's try it.
| return configuredTopology.get().orElse(null); | ||
| } | ||
|
|
||
| public StreamsTopology topology() { |
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.
Let's try it
| /** | ||
| * Removes the target assignment of a member. | ||
| * | ||
| * @param memberId The member id. |
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.
Done
| * @param groupInstanceId The group instance id. | ||
| * @return The member id corresponding to the given instance id or null if it does not exist | ||
| */ | ||
| public String staticMemberId(String groupInstanceId) { |
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.
Yes, let's postpone it.
| * | ||
| * @param partitionMetadata The new partition metadata. | ||
| */ | ||
| public void setPartitionMetadata( |
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.
Done
| * @param clusterImage The current metadata for the Kafka cluster. | ||
| * @return An immutable map of partition metadata for each topic that the streams topology is using (besides non-repartition sink topics) | ||
| */ | ||
| public Map<String, TopicMetadata> computePartitionMetadata( |
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.
Yes. I also realized that the rack information that we included here for future proofing (but not rack-aware assignment is currently done / planned) was removed from consumer groups due to the memory pressure it caused. I also updated this to not include the rack information. We can always bring it back in the future. This required some additional changes (but only removals).
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsGroup.java
Show resolved
Hide resolved
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsGroup.java
Show resolved
Hide resolved
77921b0 to
98bcef4
Compare
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.
Thanks for the updates, @lucasbru !
Here my comments.
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsGroup.java
Outdated
Show resolved
Hide resolved
...p-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/StreamsGroupTest.java
Show resolved
Hide resolved
...p-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/StreamsGroupTest.java
Show resolved
Hide resolved
...p-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/StreamsGroupTest.java
Show resolved
Hide resolved
| * @param clusterImage The current metadata for the Kafka cluster. | ||
| * @return An immutable map of partition metadata for each topic that the streams topology is using (besides non-repartition sink topics) | ||
| */ | ||
| public Map<String, TopicMetadata> computePartitionMetadata( |
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.
The part of the GroupMetadataManager that calls this method is a bit weird. The group computes and returns the partition metadata so that the computed partition metadata can be passed back into the group. We should consider simplifying that part when we get to the GroupMetadataManager.
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.
Comments addressed, ready for re-review @cadonna
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsGroup.java
Outdated
Show resolved
Hide resolved
...p-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/StreamsGroupTest.java
Show resolved
Hide resolved
...p-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/StreamsGroupTest.java
Show resolved
Hide resolved
...p-coordinator/src/test/java/org/apache/kafka/coordinator/group/streams/StreamsGroupTest.java
Show resolved
Hide resolved
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.
Implements a memory model for representing streams groups in the group coordinator, as well as group count and rebalance metrics. Reviewers: Bill Bejeck <bill@confluent.io>, Bruno Cadonna <bruno@confluent.io>
Implements a memory model for representing streams groups in the group coordinator, as well as group count and rebalance metrics. Reviewers: Bill Bejeck <bill@confluent.io>, Bruno Cadonna <bruno@confluent.io>
Implements a memory model for representing streams groups in the group coordinator, as well as group count and rebalance metrics.
Committer Checklist (excluded from commit message)