jeffkbkim commented on code in PR #13663:
URL: https://github.com/apache/kafka/pull/13663#discussion_r1191303709


##########
group-coordinator/src/main/java/org/apache/kafka/coordinator/group/generic/GenericGroup.java:
##########
@@ -0,0 +1,998 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.kafka.coordinator.group.generic;
+
+import org.apache.kafka.clients.consumer.internals.ConsumerProtocol;
+import org.apache.kafka.common.message.JoinGroupResponseData;
+import org.apache.kafka.common.message.ListGroupsResponseData;
+import org.apache.kafka.common.message.SyncGroupResponseData;
+import 
org.apache.kafka.common.message.JoinGroupResponseData.JoinGroupResponseMember;
+import org.apache.kafka.common.protocol.Errors;
+import org.apache.kafka.common.protocol.types.SchemaException;
+import org.apache.kafka.common.utils.LogContext;
+import org.apache.kafka.common.utils.Time;
+import org.apache.kafka.coordinator.group.Group;
+import org.slf4j.Logger;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+import static 
org.apache.kafka.coordinator.group.generic.GenericGroupState.COMPLETING_REBALANCE;
+import static 
org.apache.kafka.coordinator.group.generic.GenericGroupState.DEAD;
+import static 
org.apache.kafka.coordinator.group.generic.GenericGroupState.EMPTY;
+import static 
org.apache.kafka.coordinator.group.generic.GenericGroupState.PREPARING_REBALANCE;
+
+/**
+ *
+ * This class holds metadata for a generic group where the
+ * member assignment is driven solely from the client side.
+ *
+ * The APIs members use to make changes to the group membership
+ * consist of JoinGroup, SyncGroup, and LeaveGroup.
+ */
+public class GenericGroup implements Group {
+
+    /**
+     * Empty generation.
+     */
+    public static final int NO_GENERATION = -1;
+
+    /**
+     * Protocol with empty name.
+     */
+    public static final String NO_PROTOCOL_NAME = "";
+
+    /**
+     * No leader.
+     */
+    public static final String NO_LEADER = "";
+
+    /**
+     * Delimiter used to join a randomly generated UUID
+     * with a client id or a group instance id.
+     */
+    private static final String MEMBER_ID_DELIMITER = "-";
+
+    /**
+     * The slf4j log context, used to create new loggers.
+     */
+    private final LogContext logContext;
+
+    /**
+     * The slf4j logger.
+     */
+    private final Logger log;
+
+    /**
+     * The group id.
+     */
+    private final String groupId;
+
+    /**
+     * The time.
+     */
+    private final Time time;
+
+    /**
+     * The current group state.
+     */
+    private GenericGroupState state;
+
+    /**
+     * The timestamp of when the group transitioned
+     * to its current state.
+     */
+    private Optional<Long> currentStateTimestamp;
+
+    /**
+     * The protocol type used for rebalance.
+     */
+    private Optional<String> protocolType = Optional.empty();
+
+    /**
+     * The protocol name used for rebalance.
+     */
+    private Optional<String> protocolName = Optional.empty();
+
+    /**
+     * The generation id.
+     */
+    private int generationId = 0;
+
+    /**
+     * The id of the group's leader.
+     */
+    private Optional<String> leaderId = Optional.empty();
+
+    /**
+     * The members of the group.
+     */
+    private final Map<String, GenericGroupMember> members = new HashMap<>();
+
+    /**
+     * The static members of the group.
+     */
+    private final Map<String, String> staticMembers = new HashMap<>();
+
+    /**
+     * Members who have yet to (re)join the group
+     * during the join group phase.
+     */
+    private final Set<String> pendingJoinMembers = new HashSet<>();
+
+    /**
+     * The number of members awaiting a join response.
+     */
+    private int numMembersAwaitingJoinResponse = 0;
+
+    /**
+     * Map of protocol names to the number of members that support them.
+     */
+    private final Map<String, Integer> supportedProtocols = new HashMap<>();
+
+    /**
+     * Members who have yet to sync with the group
+     * during the sync group phase.
+     */
+    private final Set<String> pendingSyncMembers = new HashSet<>();
+
+    /**
+     * The list of topics to which the group members are subscribed.
+     */
+    private Optional<Set<String>> subscribedTopics = Optional.empty();
+
+    /**
+     * A flag to indiciate whether a new member was added. Used
+     * to further delay initial joins (new group).
+     */
+    private boolean newMemberAdded = false;
+
+    public GenericGroup(
+        LogContext logContext,
+        String groupId,
+        GenericGroupState initialState,
+        Time time
+    ) {
+        this.logContext = Objects.requireNonNull(logContext);
+        this.log = logContext.logger(GenericGroup.class);
+        this.groupId = Objects.requireNonNull(groupId);
+        this.state = Objects.requireNonNull(initialState);
+        this.time = Objects.requireNonNull(time);
+        this.currentStateTimestamp = Optional.of(time.milliseconds());
+    }
+
+    /**
+     * The type of this group.
+     *
+     * @return The group type (Generic).
+     */
+    @Override
+    public GroupType type() {
+        return GroupType.GENERIC;
+    }
+
+    /**
+     * The state of this group.
+     *
+     * @return The current state as a String.
+     */
+    @Override
+    public String stateAsString() {
+        return this.state.toString();
+    }
+
+    /**
+     * @return the group id.
+     */
+    public String groupId() {
+        return this.groupId;
+    }
+
+    /**
+     * @return the generation id.
+     */
+    public int generationId() {
+        return this.generationId;
+    }
+
+    /**
+     * @return the protocol name.
+     */
+    public Optional<String> protocolName() {
+        return this.protocolName;
+    }
+
+    /**
+     * @return the protocol type.
+     */
+    public Optional<String> protocolType() {
+        return this.protocolType;
+    }
+
+    /**
+     * @return the current group state.
+     */
+    public GenericGroupState currentState() {
+        return state;
+    }
+
+    /**
+     * Compares the group's current state with the given state.
+     *
+     * @param groupState the state to match against.
+     * @return true if the state matches, false otherwise.
+     */
+    public boolean isState(GenericGroupState groupState) {
+        return this.state == groupState;
+    }
+
+    /**
+     * To identify whether the given member id is part of this group.
+     *
+     * @param memberId the given member id.
+     * @return true if the member is part of this group, false otherwise.
+     */
+    public boolean hasMemberId(String memberId) {
+        return members.containsKey(memberId);
+    }
+
+    /**
+     * Get the member metadata associated with the provided member id.
+     *
+     * @param memberId the member id.
+     * @return the member metadata if it exists, null otherwise.
+     */
+    public GenericGroupMember member(String memberId) {
+        return members.get(memberId);
+    }
+
+    /**
+     * @return the total number of members in this group.
+     */
+    public int size() {
+        return members.size();
+    }
+
+    /**
+     * Used to identify whether the given member is the leader of this group.
+     *
+     * @param memberId the member id.
+     * @return true if the member is the leader, false otherwise.
+     */
+    public boolean isLeader(String memberId) {
+        return leaderId.map(id -> id.equals(memberId)).orElse(false);
+    }
+
+    /**
+     * @return the leader id or null if a leader does not exist.
+     */
+    public String leaderOrNull() {
+        return leaderId.orElse(null);
+    }
+
+    /**
+     * @return the current state timestamp.
+     */
+    public long currentStateTimestampOrDefault() {
+        return currentStateTimestamp.orElse(-1L);
+    }
+
+    /**
+     * @return whether the group is using the consumer protocol.
+     */
+    public boolean isGenericGroup() {
+        return protocolType.map(type ->
+            type.equals(ConsumerProtocol.PROTOCOL_TYPE)
+        ).orElse(false);
+    }

Review Comment:
   got it. this is from
   `def isConsumerGroup: Boolean = 
protocolType.contains(ConsumerProtocol.PROTOCOL_TYPE)`
   
   the naming is confusing because we both consumer and generic groups but a 
generic group can expect a group using the consumer protocol



-- 
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: jira-unsubscr...@kafka.apache.org

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

Reply via email to