Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import org.apache.kafka.common.message.DescribeGroupsRequestData;
import org.apache.kafka.common.message.DescribeGroupsResponseData.DescribedGroup;
import org.apache.kafka.common.message.DescribeGroupsResponseData.DescribedGroupMember;
import org.apache.kafka.common.message.FindCoordinatorRequestData;
import org.apache.kafka.common.message.MetadataRequestData;
import org.apache.kafka.common.message.IncrementalAlterConfigsRequestData;
import org.apache.kafka.common.message.IncrementalAlterConfigsRequestData.AlterableConfigSet;
Expand Down Expand Up @@ -103,6 +104,7 @@
import org.apache.kafka.common.requests.DeleteAclsResponse;
import org.apache.kafka.common.requests.DeleteAclsResponse.AclDeletionResult;
import org.apache.kafka.common.requests.DeleteAclsResponse.AclFilterResponse;
import org.apache.kafka.common.requests.FindCoordinatorRequest.CoordinatorType;
import org.apache.kafka.common.requests.DeleteGroupsRequest;
import org.apache.kafka.common.requests.DeleteGroupsResponse;
import org.apache.kafka.common.requests.DeleteRecordsRequest;
Expand Down Expand Up @@ -2538,8 +2540,11 @@ public DescribeConsumerGroupsResult describeConsumerGroups(final Collection<Stri

runnable.call(new Call("findCoordinator", deadline, new LeastLoadedNodeProvider()) {
@Override
AbstractRequest.Builder createRequest(int timeoutMs) {
return new FindCoordinatorRequest.Builder(FindCoordinatorRequest.CoordinatorType.GROUP, groupId);
FindCoordinatorRequest.Builder createRequest(int timeoutMs) {
return new FindCoordinatorRequest.Builder(
new FindCoordinatorRequestData()
.setKeyType(CoordinatorType.GROUP.id())
.setKey(groupId));
}

@Override
Expand Down Expand Up @@ -2781,8 +2786,11 @@ public ListConsumerGroupOffsetsResult listConsumerGroupOffsets(final String grou

runnable.call(new Call("findCoordinator", deadline, new LeastLoadedNodeProvider()) {
@Override
AbstractRequest.Builder createRequest(int timeoutMs) {
return new FindCoordinatorRequest.Builder(FindCoordinatorRequest.CoordinatorType.GROUP, groupId);
FindCoordinatorRequest.Builder createRequest(int timeoutMs) {
return new FindCoordinatorRequest.Builder(
new FindCoordinatorRequestData()
.setKeyType(CoordinatorType.GROUP.id())
.setKey(groupId));
}

@Override
Expand Down Expand Up @@ -2872,8 +2880,11 @@ public DeleteConsumerGroupsResult deleteConsumerGroups(Collection<String> groupI

runnable.call(new Call("findCoordinator", deadline, new LeastLoadedNodeProvider()) {
@Override
AbstractRequest.Builder createRequest(int timeoutMs) {
return new FindCoordinatorRequest.Builder(FindCoordinatorRequest.CoordinatorType.GROUP, groupId);
FindCoordinatorRequest.Builder createRequest(int timeoutMs) {
return new FindCoordinatorRequest.Builder(
new FindCoordinatorRequestData()
.setKeyType(CoordinatorType.GROUP.id())
.setKey(groupId));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.kafka.common.errors.RebalanceInProgressException;
import org.apache.kafka.common.errors.RetriableException;
import org.apache.kafka.common.errors.UnknownMemberIdException;
import org.apache.kafka.common.message.FindCoordinatorRequestData;
import org.apache.kafka.common.message.JoinGroupRequestData;
import org.apache.kafka.common.message.JoinGroupResponseData;
import org.apache.kafka.common.message.LeaveGroupRequestData;
Expand All @@ -42,6 +43,7 @@
import org.apache.kafka.common.metrics.stats.Meter;
import org.apache.kafka.common.protocol.Errors;
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.requests.HeartbeatRequest;
import org.apache.kafka.common.requests.HeartbeatResponse;
Expand Down Expand Up @@ -661,7 +663,10 @@ private RequestFuture<Void> sendFindCoordinatorRequest(Node node) {
// initiate the group metadata request
log.debug("Sending FindCoordinator request to broker {}", node);
FindCoordinatorRequest.Builder requestBuilder =
new FindCoordinatorRequest.Builder(FindCoordinatorRequest.CoordinatorType.GROUP, this.groupId);
new FindCoordinatorRequest.Builder(
new FindCoordinatorRequestData()
.setKeyType(CoordinatorType.GROUP.id())
.setKey(this.groupId));
return client.send(node, requestBuilder)
.compose(new FindCoordinatorResponseHandler());
}
Expand All @@ -679,12 +684,12 @@ public void onSuccess(ClientResponse resp, RequestFuture<Void> future) {
synchronized (AbstractCoordinator.this) {
// use MAX_VALUE - node.id as the coordinator id to allow separate connections
// for the coordinator in the underlying network client layer
int coordinatorConnectionId = Integer.MAX_VALUE - findCoordinatorResponse.node().id();
int coordinatorConnectionId = Integer.MAX_VALUE - findCoordinatorResponse.data().nodeId();

AbstractCoordinator.this.coordinator = new Node(
coordinatorConnectionId,
findCoordinatorResponse.node().host(),
findCoordinatorResponse.node().port());
findCoordinatorResponse.data().host(),
findCoordinatorResponse.data().port());
log.info("Discovered group coordinator {}", coordinator);
client.tryConnect(coordinator);
heartbeat.resetSessionTimeout();
Expand All @@ -693,7 +698,7 @@ public void onSuccess(ClientResponse resp, RequestFuture<Void> future) {
} else if (error == Errors.GROUP_AUTHORIZATION_FAILED) {
future.raise(new GroupAuthorizationException(groupId));
} else {
log.debug("Group coordinator lookup failed: {}", error.message());
log.debug("Group coordinator lookup failed: {}", findCoordinatorResponse.data().errorMessage());
future.raise(error);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.kafka.common.errors.AuthenticationException;
import org.apache.kafka.common.errors.GroupAuthorizationException;
import org.apache.kafka.common.errors.TopicAuthorizationException;
import org.apache.kafka.common.message.FindCoordinatorRequestData;
import org.apache.kafka.common.message.InitProducerIdRequestData;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.record.DefaultRecordBatch;
Expand All @@ -38,6 +39,7 @@
import org.apache.kafka.common.requests.EndTxnRequest;
import org.apache.kafka.common.requests.EndTxnResponse;
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.requests.InitProducerIdRequest;
import org.apache.kafka.common.requests.InitProducerIdResponse;
Expand Down Expand Up @@ -866,7 +868,10 @@ private synchronized void lookupCoordinator(FindCoordinatorRequest.CoordinatorTy
throw new IllegalStateException("Invalid coordinator type: " + type);
}

FindCoordinatorRequest.Builder builder = new FindCoordinatorRequest.Builder(type, coordinatorKey);
FindCoordinatorRequest.Builder builder = new FindCoordinatorRequest.Builder(
new FindCoordinatorRequestData()
.setKeyType(type.id())
.setKey(coordinatorKey));
enqueueRequest(new FindCoordinatorHandler(builder));
}

Expand Down Expand Up @@ -1193,10 +1198,11 @@ String coordinatorKey() {
public void handleResponse(AbstractResponse response) {
FindCoordinatorResponse findCoordinatorResponse = (FindCoordinatorResponse) response;
Errors error = findCoordinatorResponse.error();
CoordinatorType coordinatorType = CoordinatorType.forId(builder.data().keyType());

if (error == Errors.NONE) {
Node node = findCoordinatorResponse.node();
switch (builder.coordinatorType()) {
switch (coordinatorType) {
case GROUP:
consumerGroupCoordinator = node;
break;
Expand All @@ -1209,11 +1215,11 @@ public void handleResponse(AbstractResponse response) {
} else if (error == Errors.TRANSACTIONAL_ID_AUTHORIZATION_FAILED) {
fatalError(error.exception());
} else if (findCoordinatorResponse.error() == Errors.GROUP_AUTHORIZATION_FAILED) {
abortableError(new GroupAuthorizationException(builder.coordinatorKey()));
abortableError(new GroupAuthorizationException(builder.data().key()));
} else {
fatalError(new KafkaException(String.format("Could not find a coordinator with type %s with key %s due to" +
"unexpected error: %s", builder.coordinatorType(), builder.coordinatorKey(),
findCoordinatorResponse.error().message())));
"unexpected error: %s", coordinatorType, builder.data().key(),
findCoordinatorResponse.data().errorMessage())));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.apache.kafka.common.message.DescribeGroupsResponseData;
import org.apache.kafka.common.message.ElectPreferredLeadersRequestData;
import org.apache.kafka.common.message.ElectPreferredLeadersResponseData;
import org.apache.kafka.common.message.FindCoordinatorRequestData;
import org.apache.kafka.common.message.FindCoordinatorResponseData;
import org.apache.kafka.common.message.InitProducerIdRequestData;
import org.apache.kafka.common.message.InitProducerIdResponseData;
import org.apache.kafka.common.message.JoinGroupRequestData;
Expand Down Expand Up @@ -83,8 +85,6 @@
import org.apache.kafka.common.requests.ExpireDelegationTokenResponse;
import org.apache.kafka.common.requests.FetchRequest;
import org.apache.kafka.common.requests.FetchResponse;
import org.apache.kafka.common.requests.FindCoordinatorRequest;
import org.apache.kafka.common.requests.FindCoordinatorResponse;
import org.apache.kafka.common.requests.HeartbeatRequest;
import org.apache.kafka.common.requests.HeartbeatResponse;
import org.apache.kafka.common.requests.LeaderAndIsrRequest;
Expand Down Expand Up @@ -135,8 +135,8 @@ public enum ApiKeys {
ControlledShutdownResponseData.SCHEMAS),
OFFSET_COMMIT(8, "OffsetCommit", OffsetCommitRequestData.SCHEMAS, OffsetCommitResponseData.SCHEMAS),
OFFSET_FETCH(9, "OffsetFetch", OffsetFetchRequest.schemaVersions(), OffsetFetchResponse.schemaVersions()),
FIND_COORDINATOR(10, "FindCoordinator", FindCoordinatorRequest.schemaVersions(),
FindCoordinatorResponse.schemaVersions()),
FIND_COORDINATOR(10, "FindCoordinator", FindCoordinatorRequestData.SCHEMAS,
FindCoordinatorResponseData.SCHEMAS),
JOIN_GROUP(11, "JoinGroup", JoinGroupRequestData.SCHEMAS, JoinGroupResponseData.SCHEMAS),
HEARTBEAT(12, "Heartbeat", HeartbeatRequest.schemaVersions(), HeartbeatResponse.schemaVersions()),
LEAVE_GROUP(13, "LeaveGroup", LeaveGroupRequestData.SCHEMAS, LeaveGroupResponseData.SCHEMAS),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public static AbstractResponse parseResponse(ApiKeys apiKey, Struct struct, shor
case OFFSET_FETCH:
return new OffsetFetchResponse(struct);
case FIND_COORDINATOR:
return new FindCoordinatorResponse(struct);
return new FindCoordinatorResponse(struct, version);
case JOIN_GROUP:
return new JoinGroupResponse(struct, version);
case HEARTBEAT:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,122 +18,64 @@

import org.apache.kafka.common.Node;
import org.apache.kafka.common.errors.UnsupportedVersionException;
import org.apache.kafka.common.message.FindCoordinatorRequestData;
import org.apache.kafka.common.message.FindCoordinatorResponseData;
import org.apache.kafka.common.protocol.ApiKeys;
import org.apache.kafka.common.protocol.Errors;
import org.apache.kafka.common.protocol.types.Field;
import org.apache.kafka.common.protocol.types.Schema;
import org.apache.kafka.common.protocol.types.Struct;

import java.nio.ByteBuffer;

import static org.apache.kafka.common.protocol.CommonFields.GROUP_ID;
import static org.apache.kafka.common.protocol.types.Type.INT8;
import static org.apache.kafka.common.protocol.types.Type.STRING;

public class FindCoordinatorRequest extends AbstractRequest {
private static final String COORDINATOR_KEY_KEY_NAME = "coordinator_key";
private static final String COORDINATOR_TYPE_KEY_NAME = "coordinator_type";

private static final Schema FIND_COORDINATOR_REQUEST_V0 = new Schema(GROUP_ID);

private static final Schema FIND_COORDINATOR_REQUEST_V1 = new Schema(
new Field("coordinator_key", STRING, "Id to use for finding the coordinator (for groups, this is the groupId, " +
"for transactional producers, this is the transactional id)"),
new Field("coordinator_type", INT8, "The type of coordinator to find (0 = group, 1 = transaction)"));

/**
* The version number is bumped to indicate that on quota violation brokers send out responses before throttling.
*/
private static final Schema FIND_COORDINATOR_REQUEST_V2 = FIND_COORDINATOR_REQUEST_V1;

public static Schema[] schemaVersions() {
return new Schema[] {FIND_COORDINATOR_REQUEST_V0, FIND_COORDINATOR_REQUEST_V1, FIND_COORDINATOR_REQUEST_V2};
}

public static class Builder extends AbstractRequest.Builder<FindCoordinatorRequest> {
private final String coordinatorKey;
private final CoordinatorType coordinatorType;
private final short minVersion;
private final FindCoordinatorRequestData data;

public Builder(CoordinatorType coordinatorType, String coordinatorKey) {
public Builder(FindCoordinatorRequestData data) {
super(ApiKeys.FIND_COORDINATOR);
this.coordinatorType = coordinatorType;
this.coordinatorKey = coordinatorKey;
this.minVersion = coordinatorType == CoordinatorType.TRANSACTION ? (short) 1 : (short) 0;
this.data = data;
}

@Override
public FindCoordinatorRequest build(short version) {
if (version < minVersion)
if (version < 1 && data.keyType() == CoordinatorType.TRANSACTION.id()) {
throw new UnsupportedVersionException("Cannot create a v" + version + " FindCoordinator request " +
"because we require features supported only in " + minVersion + " or later.");
return new FindCoordinatorRequest(coordinatorType, coordinatorKey, version);
}

public String coordinatorKey() {
return coordinatorKey;
}

public CoordinatorType coordinatorType() {
return coordinatorType;
"because we require features supported only in 2 or later.");
}
return new FindCoordinatorRequest(data, version);
}

@Override
public String toString() {
StringBuilder bld = new StringBuilder();
bld.append("(type=FindCoordinatorRequest, coordinatorKey=");
bld.append(coordinatorKey);
bld.append(", coordinatorType=");
bld.append(coordinatorType);
bld.append(")");
return bld.toString();
return data.toString();
}

public FindCoordinatorRequestData data() {
return data;
}
}

private final String coordinatorKey;
private final CoordinatorType coordinatorType;
private final FindCoordinatorRequestData data;

private FindCoordinatorRequest(CoordinatorType coordinatorType, String coordinatorKey, short version) {
private FindCoordinatorRequest(FindCoordinatorRequestData data, short version) {
super(ApiKeys.FIND_COORDINATOR, version);
this.coordinatorType = coordinatorType;
this.coordinatorKey = coordinatorKey;
this.data = data;
}

public FindCoordinatorRequest(Struct struct, short version) {
super(ApiKeys.FIND_COORDINATOR, version);

if (struct.hasField(COORDINATOR_TYPE_KEY_NAME))
this.coordinatorType = CoordinatorType.forId(struct.getByte(COORDINATOR_TYPE_KEY_NAME));
else
this.coordinatorType = CoordinatorType.GROUP;
if (struct.hasField(GROUP_ID))
this.coordinatorKey = struct.get(GROUP_ID);
else
this.coordinatorKey = struct.getString(COORDINATOR_KEY_KEY_NAME);
this.data = new FindCoordinatorRequestData(struct, version);
}

@Override
public AbstractResponse getErrorResponse(int throttleTimeMs, Throwable e) {
short versionId = version();
switch (versionId) {
case 0:
return new FindCoordinatorResponse(Errors.forException(e), Node.noNode());
case 1:
case 2:
return new FindCoordinatorResponse(throttleTimeMs, Errors.forException(e), Node.noNode());

default:
throw new IllegalArgumentException(String.format("Version %d is not valid. Valid versions for %s are 0 to %d",
versionId, this.getClass().getSimpleName(), ApiKeys.FIND_COORDINATOR.latestVersion()));
FindCoordinatorResponseData response = new FindCoordinatorResponseData();
if (version() >= 2) {
response.setThrottleTimeMs(throttleTimeMs);
}
}

public String coordinatorKey() {
return coordinatorKey;
}

public CoordinatorType coordinatorType() {
return coordinatorType;
Errors error = Errors.forException(e);
return FindCoordinatorResponse.prepareResponse(error, Node.noNode());
}

public static FindCoordinatorRequest parse(ByteBuffer buffer, short version) {
Expand All @@ -142,14 +84,11 @@ public static FindCoordinatorRequest parse(ByteBuffer buffer, short version) {

@Override
protected Struct toStruct() {
Struct struct = new Struct(ApiKeys.FIND_COORDINATOR.requestSchema(version()));
if (struct.hasField(GROUP_ID))
struct.set(GROUP_ID, coordinatorKey);
else
struct.set(COORDINATOR_KEY_KEY_NAME, coordinatorKey);
if (struct.hasField(COORDINATOR_TYPE_KEY_NAME))
struct.set(COORDINATOR_TYPE_KEY_NAME, coordinatorType.id);
return struct;
return data.toStruct(version());
}

public FindCoordinatorRequestData data() {
return data;
}

public enum CoordinatorType {
Expand All @@ -161,6 +100,10 @@ public enum CoordinatorType {
this.id = id;
}

public byte id() {
return id;
}

public static CoordinatorType forId(byte id) {
switch (id) {
case 0:
Expand Down
Loading