use of org.apache.kafka.common.message.EndQuorumEpochRequestData in project kafka by apache.
the class RaftClientTestContext method collectEndQuorumRequests.
List<RaftRequest.Outbound> collectEndQuorumRequests(int epoch, Set<Integer> destinationIdSet, Optional<List<Integer>> preferredSuccessorsOpt) {
List<RaftRequest.Outbound> endQuorumRequests = new ArrayList<>();
Set<Integer> collectedDestinationIdSet = new HashSet<>();
for (RaftMessage raftMessage : channel.drainSendQueue()) {
if (raftMessage.data() instanceof EndQuorumEpochRequestData) {
EndQuorumEpochRequestData request = (EndQuorumEpochRequestData) raftMessage.data();
EndQuorumEpochRequestData.PartitionData partitionRequest = request.topics().get(0).partitions().get(0);
assertEquals(epoch, partitionRequest.leaderEpoch());
assertEquals(localIdOrThrow(), partitionRequest.leaderId());
preferredSuccessorsOpt.ifPresent(preferredSuccessors -> {
assertEquals(preferredSuccessors, partitionRequest.preferredSuccessors());
});
RaftRequest.Outbound outboundRequest = (RaftRequest.Outbound) raftMessage;
collectedDestinationIdSet.add(outboundRequest.destinationId());
endQuorumRequests.add(outboundRequest);
}
}
assertEquals(destinationIdSet, collectedDestinationIdSet);
return endQuorumRequests;
}
use of org.apache.kafka.common.message.EndQuorumEpochRequestData in project kafka by apache.
the class KafkaRaftClient method handleEndQuorumEpochRequest.
/**
* Handle an EndEpoch 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 EndQuorumEpochResponseData handleEndQuorumEpochRequest(RaftRequest.Inbound requestMetadata, long currentTimeMs) {
EndQuorumEpochRequestData request = (EndQuorumEpochRequestData) requestMetadata.data;
if (!hasValidClusterId(request.clusterId())) {
return new EndQuorumEpochResponseData().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 EndQuorumEpochResponseData().setErrorCode(Errors.INVALID_REQUEST.code());
}
EndQuorumEpochRequestData.PartitionData partitionRequest = request.topics().get(0).partitions().get(0);
int requestEpoch = partitionRequest.leaderEpoch();
int requestLeaderId = partitionRequest.leaderId();
Optional<Errors> errorOpt = validateVoterOnlyRequest(requestLeaderId, requestEpoch);
if (errorOpt.isPresent()) {
return buildEndQuorumEpochResponse(errorOpt.get());
}
maybeTransition(OptionalInt.of(requestLeaderId), requestEpoch, currentTimeMs);
if (quorum.isFollower()) {
FollowerState state = quorum.followerStateOrThrow();
if (state.leaderId() == requestLeaderId) {
List<Integer> preferredSuccessors = partitionRequest.preferredSuccessors();
long electionBackoffMs = endEpochElectionBackoff(preferredSuccessors);
logger.debug("Overriding follower fetch timeout to {} after receiving " + "EndQuorumEpoch request from leader {} in epoch {}", electionBackoffMs, requestLeaderId, requestEpoch);
state.overrideFetchTimeout(currentTimeMs, electionBackoffMs);
}
}
return buildEndQuorumEpochResponse(Errors.NONE);
}
Aggregations