mjsax commented on code in PR #20574:
URL: https://github.com/apache/kafka/pull/20574#discussion_r2373691400


##########
core/src/test/scala/integration/kafka/api/PlaintextAdminIntegrationTest.scala:
##########
@@ -4463,6 +4463,47 @@ class PlaintextAdminIntegrationTest extends 
BaseAdminIntegrationTest {
     }
   }
 
+  @Test
+  def testDescribeStreamsGroupsNotReady(): Unit = {
+    val streamsGroupId = "stream_group_id"
+    val testTopicName = "test_topic"
+
+    val config = createConfig
+    client = Admin.create(config)
+
+    val streams = createStreamsGroup(
+      inputTopic = testTopicName,
+      streamsGroupId = streamsGroupId
+    )
+    streams.poll(JDuration.ofMillis(500L))
+
+    try {
+      TestUtils.waitUntilTrue(() => {
+        val firstGroup = client.listGroups().all().get().stream()
+          .filter(g => g.groupId() == streamsGroupId).findFirst().orElse(null)
+        firstGroup.groupState().orElse(null) == GroupState.NOT_READY && 
firstGroup.groupId() == streamsGroupId
+      }, "Stream group not NOT_READY yet")

Review Comment:
   How does this test ensure, that the group stays in NOT_READY state (ie, does 
not go into ASSIGNING, RECONCILING, or STABLE) ?



##########
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsGroup.java:
##########
@@ -1039,7 +1039,16 @@ public StreamsGroupDescribeResponseData.DescribedGroup 
asDescribedGroup(
             .setGroupEpoch(groupEpoch.get(committedOffset))
             .setGroupState(state.get(committedOffset).toString())
             .setAssignmentEpoch(targetAssignmentEpoch.get(committedOffset))
-            
.setTopology(configuredTopology.get(committedOffset).map(ConfiguredTopology::asStreamsGroupDescribeTopology).orElse(null));
+            .setTopology(
+                configuredTopology.get(committedOffset)
+                    .filter(ConfiguredTopology::isReady)
+                    .map(ConfiguredTopology::asStreamsGroupDescribeTopology)
+                    .orElse(
+                        topology.get(committedOffset)
+                            
.map(StreamsTopology::asStreamsGroupDescribeTopology)
+                            .orElse(null)

Review Comment:
   Is `orElse(null)` a valid case? Should we not always have a topology, even 
if it's not configured yet?



##########
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/streams/StreamsTopology.java:
##########
@@ -95,4 +97,43 @@ public static StreamsTopology 
fromHeartbeatRequest(StreamsGroupHeartbeatRequestD
             
.collect(Collectors.toMap(StreamsGroupTopologyValue.Subtopology::subtopologyId, 
x -> x));
         return new StreamsTopology(topology.epoch(), subtopologyMap);
     }
+
+    public StreamsGroupDescribeResponseData.Topology 
asStreamsGroupDescribeTopology() {
+        return new StreamsGroupDescribeResponseData.Topology()
+            .setEpoch(topologyEpoch)
+            .setSubtopologies(
+                subtopologies.entrySet().stream()
+                    .sorted(Map.Entry.comparingByKey())
+                    .map(entry -> 
asStreamsGroupDescribeSubtopology(entry.getKey(), entry.getValue()))
+                    .toList()
+            );
+    }
+
+    private StreamsGroupDescribeResponseData.Subtopology 
asStreamsGroupDescribeSubtopology(String subtopologyId, 
StreamsGroupTopologyValue.Subtopology subtopology) {
+        return new StreamsGroupDescribeResponseData.Subtopology()
+            .setSubtopologyId(subtopologyId)
+            
.setSourceTopics(subtopology.sourceTopics().stream().sorted().toList())
+            
.setRepartitionSinkTopics(subtopology.repartitionSinkTopics().stream().sorted().toList())
+            
.setRepartitionSourceTopics(subtopology.repartitionSourceTopics().stream()
+                .map(this::asStreamsGroupDescribeTopicInfo)
+                
.sorted(Comparator.comparing(StreamsGroupDescribeResponseData.TopicInfo::name)).toList())
+            
.setStateChangelogTopics(subtopology.stateChangelogTopics().stream()
+                .map(this::asStreamsGroupDescribeTopicInfo)
+                
.sorted(Comparator.comparing(StreamsGroupDescribeResponseData.TopicInfo::name)).toList());
+    }
+
+    private StreamsGroupDescribeResponseData.TopicInfo 
asStreamsGroupDescribeTopicInfo(StreamsGroupTopologyValue.TopicInfo topicInfo) {
+        return new StreamsGroupDescribeResponseData.TopicInfo()
+            .setName(topicInfo.name())
+            .setPartitions(topicInfo.partitions())
+            .setReplicationFactor(topicInfo.replicationFactor())
+            .setTopicConfigs(
+                topicInfo.topicConfigs().stream().map(
+                    y -> new StreamsGroupDescribeResponseData.KeyValue()

Review Comment:
   Why `y` ? Can't we find a better name?



-- 
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]

Reply via email to