skaundinya15 commented on a change in pull request #10743:
URL: https://github.com/apache/kafka/pull/10743#discussion_r655134390



##########
File path: 
clients/src/main/java/org/apache/kafka/clients/admin/internals/CoordinatorStrategy.java
##########
@@ -17,84 +17,153 @@
 package org.apache.kafka.clients.admin.internals;
 
 import org.apache.kafka.common.errors.GroupAuthorizationException;
+import org.apache.kafka.common.errors.InvalidGroupIdException;
 import org.apache.kafka.common.errors.TransactionalIdAuthorizationException;
 import org.apache.kafka.common.message.FindCoordinatorRequestData;
+import org.apache.kafka.common.message.FindCoordinatorResponseData.Coordinator;
 import org.apache.kafka.common.protocol.Errors;
 import org.apache.kafka.common.requests.AbstractResponse;
 import org.apache.kafka.common.requests.FindCoordinatorRequest;
+import org.apache.kafka.common.requests.FindCoordinatorRequest.CoordinatorType;
 import org.apache.kafka.common.requests.FindCoordinatorResponse;
 import org.apache.kafka.common.utils.LogContext;
 import org.slf4j.Logger;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 public class CoordinatorStrategy implements 
AdminApiLookupStrategy<CoordinatorKey> {
+
+    private static final ApiRequestScope GROUP_REQUEST_SCOPE = new 
ApiRequestScope() { };
+    private static final ApiRequestScope TXN_REQUEST_SCOPE = new 
ApiRequestScope() { };
+
     private final Logger log;
+    private final FindCoordinatorRequest.CoordinatorType type;
+    private boolean batch = true;
+    private Set<CoordinatorKey> unrepresentableKeys = Collections.emptySet();
 
     public CoordinatorStrategy(
+        FindCoordinatorRequest.CoordinatorType type,
         LogContext logContext
     ) {
+        this.type = type;
         this.log = logContext.logger(CoordinatorStrategy.class);
     }
 
     @Override
     public ApiRequestScope lookupScope(CoordinatorKey key) {
-        // The `FindCoordinator` API does not support batched lookups, so we 
use a
-        // separate lookup context for each coordinator key we need to lookup
-        return new LookupRequestScope(key);
+        if (batch) {
+            if (type == CoordinatorType.GROUP) {
+                return GROUP_REQUEST_SCOPE;
+            } else {
+                return TXN_REQUEST_SCOPE;
+            }
+        } else {
+            // If the `FindCoordinator` API does not support batched lookups, 
we use a
+            // separate lookup context for each coordinator key we need to 
lookup
+            return new LookupRequestScope(key);
+        }
     }
 
     @Override
     public FindCoordinatorRequest.Builder buildRequest(Set<CoordinatorKey> 
keys) {
-        CoordinatorKey key = requireSingleton(keys);
-        return new FindCoordinatorRequest.Builder(
-            new FindCoordinatorRequestData()
-                .setKey(key.idValue)
-                .setKeyType(key.type.id())
-        );
+        unrepresentableKeys = keys.stream().filter(k -> 
!isRepresentableKey(k.idValue)).collect(Collectors.toSet());
+        keys = keys.stream().filter(k -> 
isRepresentableKey(k.idValue)).collect(Collectors.toSet());
+        if (batch) {
+            keys = requireSameType(keys);
+            FindCoordinatorRequestData data = new FindCoordinatorRequestData()
+                    .setKeyType(type.id())
+                    .setCoordinatorKeys(keys.stream().map(k -> 
k.idValue).collect(Collectors.toList()));
+            return new FindCoordinatorRequest.Builder(data);
+        } else {
+            CoordinatorKey key = requireSingleton(keys);
+            return new FindCoordinatorRequest.Builder(
+                new FindCoordinatorRequestData()
+                    .setKey(key.idValue)
+                    .setKeyType(key.type.id())
+            );
+        }
     }
 
     @Override
     public LookupResult<CoordinatorKey> handleResponse(
         Set<CoordinatorKey> keys,
         AbstractResponse abstractResponse
     ) {
-        CoordinatorKey key = requireSingleton(keys);
+        Map<CoordinatorKey, Integer> mappedKeys = new HashMap<>();
+        Map<CoordinatorKey, Throwable> failedKeys = new HashMap<>();
+
+        for (CoordinatorKey key : unrepresentableKeys) {
+            failedKeys.put(key, new InvalidGroupIdException("The given group 
id '" +
+                            key.idValue + "' cannot be represented in a 
request."));
+        }
         FindCoordinatorResponse response = (FindCoordinatorResponse) 
abstractResponse;
-        Errors error = response.error();
+        if (batch) {
+            for (Coordinator coordinator : response.data().coordinators()) {
+                handleError(Errors.forCode(coordinator.errorCode()),
+                            new CoordinatorKey(type, coordinator.key()),
+                            coordinator.nodeId(),
+                            mappedKeys,
+                            failedKeys);
+            }
+        } else {
+            CoordinatorKey key = requireSingleton(keys);
+            Errors error = response.error();
+            handleError(error, key, response.node().id(), mappedKeys, 
failedKeys);
+        }
+        return new LookupResult<>(failedKeys, mappedKeys);
+    }
+
+    public void disableBatch() {
+        batch = false;
+    }
+
+    private static CoordinatorKey requireSingleton(Set<CoordinatorKey> keys) {
+        if (keys.size() != 1) {
+            throw new IllegalArgumentException("Unexpected lookup key set");
+        }
+        return keys.iterator().next();
+    }
 
+    private static Set<CoordinatorKey> requireSameType(Set<CoordinatorKey> 
keys) {
+        if (keys.stream().map(k -> k.type).collect(Collectors.toSet()).size() 
!= 1) {
+            throw new IllegalArgumentException("Unexpected lookup key set");
+        }
+        return keys;
+    }
+
+    private static boolean isRepresentableKey(String groupId) {
+        return groupId != null;
+    }
+
+    private void handleError(Errors error, CoordinatorKey key, int nodeId, 
Map<CoordinatorKey, Integer> mappedKeys, Map<CoordinatorKey, Throwable> 
failedKeys) {
         switch (error) {
             case NONE:
-                return LookupResult.mapped(key, response.data().nodeId());
-
+                mappedKeys.put(key, nodeId);
+                break;
             case COORDINATOR_NOT_AVAILABLE:

Review comment:
       @mimaison Gotcha, makes sense. Perhaps we can still log at `DEBUG` level 
so in case we need to debug, we have evidence of this in the logs.




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

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to