use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.
the class RaftClientTestContext method assertSentBeginQuorumEpochResponse.
void assertSentBeginQuorumEpochResponse(Errors partitionError, int epoch, OptionalInt leaderId) {
List<RaftResponse.Outbound> sentMessages = drainSentResponses(ApiKeys.BEGIN_QUORUM_EPOCH);
assertEquals(1, sentMessages.size());
RaftMessage raftMessage = sentMessages.get(0);
assertTrue(raftMessage.data() instanceof BeginQuorumEpochResponseData);
BeginQuorumEpochResponseData response = (BeginQuorumEpochResponseData) raftMessage.data();
assertEquals(Errors.NONE, Errors.forCode(response.errorCode()));
BeginQuorumEpochResponseData.PartitionData partitionResponse = response.topics().get(0).partitions().get(0);
assertEquals(epoch, partitionResponse.leaderEpoch());
assertEquals(leaderId.orElse(-1), partitionResponse.leaderId());
assertEquals(partitionError, Errors.forCode(partitionResponse.errorCode()));
}
use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.
the class RaftClientTestContext method assertSentBeginQuorumEpochResponse.
void assertSentBeginQuorumEpochResponse(Errors responseError) {
List<RaftResponse.Outbound> sentMessages = drainSentResponses(ApiKeys.BEGIN_QUORUM_EPOCH);
assertEquals(1, sentMessages.size());
RaftMessage raftMessage = sentMessages.get(0);
assertTrue(raftMessage.data() instanceof BeginQuorumEpochResponseData);
BeginQuorumEpochResponseData response = (BeginQuorumEpochResponseData) raftMessage.data();
assertEquals(responseError, Errors.forCode(response.errorCode()));
}
use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.
the class KafkaRaftClient method handleBeginQuorumEpochResponse.
private boolean handleBeginQuorumEpochResponse(RaftResponse.Inbound responseMetadata, long currentTimeMs) {
int remoteNodeId = responseMetadata.sourceId();
BeginQuorumEpochResponseData response = (BeginQuorumEpochResponseData) responseMetadata.data;
Errors topLevelError = Errors.forCode(response.errorCode());
if (topLevelError != Errors.NONE) {
return handleTopLevelError(topLevelError, responseMetadata);
}
if (!hasValidTopicPartition(response, log.topicPartition())) {
return false;
}
BeginQuorumEpochResponseData.PartitionData partitionResponse = response.topics().get(0).partitions().get(0);
Errors partitionError = Errors.forCode(partitionResponse.errorCode());
OptionalInt responseLeaderId = optionalLeaderId(partitionResponse.leaderId());
int responseEpoch = partitionResponse.leaderEpoch();
Optional<Boolean> handled = maybeHandleCommonResponse(partitionError, responseLeaderId, responseEpoch, currentTimeMs);
if (handled.isPresent()) {
return handled.get();
} else if (partitionError == Errors.NONE) {
if (quorum.isLeader()) {
LeaderState<T> state = quorum.leaderStateOrThrow();
state.addAcknowledgementFrom(remoteNodeId);
} else {
logger.debug("Ignoring BeginQuorumEpoch response {} since " + "this node is not the leader anymore", response);
}
return true;
} else {
return handleUnexpectedError(partitionError, responseMetadata);
}
}
use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.
the class KafkaRaftClient method handleBeginQuorumEpochRequest.
/**
* Handle a BeginEpoch request. This API may return the following errors:
*
* - {@link Errors#INCONSISTENT_CLUSTER_ID} if the cluster id is presented in request
* but different from this node
* - {@link Errors#BROKER_NOT_AVAILABLE} if this node is currently shutting down
* - {@link Errors#INCONSISTENT_VOTER_SET} if the request suggests inconsistent voter membership (e.g.
* if this node or the sender is not one of the current known voters)
* - {@link Errors#FENCED_LEADER_EPOCH} if the epoch is smaller than this node's epoch
*/
private BeginQuorumEpochResponseData handleBeginQuorumEpochRequest(RaftRequest.Inbound requestMetadata, long currentTimeMs) {
BeginQuorumEpochRequestData request = (BeginQuorumEpochRequestData) requestMetadata.data;
if (!hasValidClusterId(request.clusterId())) {
return new BeginQuorumEpochResponseData().setErrorCode(Errors.INCONSISTENT_CLUSTER_ID.code());
}
if (!hasValidTopicPartition(request, log.topicPartition())) {
// Until we support multi-raft, we treat topic partition mismatches as invalid requests
return new BeginQuorumEpochResponseData().setErrorCode(Errors.INVALID_REQUEST.code());
}
BeginQuorumEpochRequestData.PartitionData partitionRequest = request.topics().get(0).partitions().get(0);
int requestLeaderId = partitionRequest.leaderId();
int requestEpoch = partitionRequest.leaderEpoch();
Optional<Errors> errorOpt = validateVoterOnlyRequest(requestLeaderId, requestEpoch);
if (errorOpt.isPresent()) {
return buildBeginQuorumEpochResponse(errorOpt.get());
}
maybeTransition(OptionalInt.of(requestLeaderId), requestEpoch, currentTimeMs);
return buildBeginQuorumEpochResponse(Errors.NONE);
}
use of org.apache.kafka.common.message.BeginQuorumEpochResponseData in project kafka by apache.
the class KafkaRaftClientTest method testClusterAuthorizationFailedInBeginQuorumEpoch.
@Test
public void testClusterAuthorizationFailedInBeginQuorumEpoch() throws Exception {
int localId = 0;
int otherNodeId = 1;
int epoch = 5;
Set<Integer> voters = Utils.mkSet(localId, otherNodeId);
RaftClientTestContext context = new RaftClientTestContext.Builder(localId, voters).updateRandom(r -> r.mockNextInt(DEFAULT_ELECTION_TIMEOUT_MS, 0)).withUnknownLeader(epoch - 1).build();
context.time.sleep(context.electionTimeoutMs());
context.expectAndGrantVotes(epoch);
context.pollUntilRequest();
int correlationId = context.assertSentBeginQuorumEpochRequest(epoch, 1);
BeginQuorumEpochResponseData response = new BeginQuorumEpochResponseData().setErrorCode(Errors.CLUSTER_AUTHORIZATION_FAILED.code());
context.deliverResponse(correlationId, otherNodeId, response);
assertThrows(ClusterAuthorizationException.class, context.client::poll);
}
Aggregations