Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.clients.consumer.internals;
import org.apache.kafka.clients.ApiVersions;
import org.apache.kafka.clients.Metadata;
import org.apache.kafka.clients.NodeApiVersions;
import org.apache.kafka.clients.StaleMetadataException;
import org.apache.kafka.clients.consumer.LogTruncationException;
import org.apache.kafka.clients.consumer.OffsetAndTimestamp;
import org.apache.kafka.clients.consumer.internals.OffsetFetcherUtils.ListOffsetData;
import org.apache.kafka.clients.consumer.internals.OffsetFetcherUtils.ListOffsetResult;
import org.apache.kafka.clients.consumer.internals.events.BackgroundEventHandler;
import org.apache.kafka.clients.consumer.internals.events.ErrorBackgroundEvent;
import org.apache.kafka.common.ClusterResource;
import org.apache.kafka.common.ClusterResourceListener;
import org.apache.kafka.common.IsolationLevel;
import org.apache.kafka.common.Node;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.message.ListOffsetsRequestData;
import org.apache.kafka.common.requests.AbstractRequest;
import org.apache.kafka.common.requests.ListOffsetsRequest;
import org.apache.kafka.common.requests.ListOffsetsResponse;
import org.apache.kafka.common.requests.OffsetsForLeaderEpochRequest;
import org.apache.kafka.common.requests.OffsetsForLeaderEpochResponse;
import org.apache.kafka.common.utils.LogContext;
import org.apache.kafka.common.utils.Time;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
import static org.apache.kafka.clients.consumer.internals.OffsetFetcherUtils.hasUsableOffsetForLeaderEpochVersion;
import static org.apache.kafka.clients.consumer.internals.OffsetFetcherUtils.regroupFetchPositionsByLeader;
/**
* Manager responsible for building the following requests to retrieve partition offsets, and
* processing its responses.
*
*
ListOffset request
*
OffsetForLeaderEpoch request
*
* Requests are kept in-memory ready to be sent on the next call to {@link #poll(long)}.
*
* Partition leadership information required to build ListOffset requests is retrieved from the
* {@link ConsumerMetadata}, so this implements {@link ClusterResourceListener} to get notified
* when the cluster metadata is updated.
*/
public class OffsetsRequestManager implements RequestManager, ClusterResourceListener {
private final ConsumerMetadata metadata;
private final IsolationLevel isolationLevel;
private final Logger log;
private final OffsetFetcherUtils offsetFetcherUtils;
private final SubscriptionState subscriptionState;
private final Set requestsToRetry;
private final List requestsToSend;
private final long requestTimeoutMs;
private final Time time;
private final ApiVersions apiVersions;
private final NetworkClientDelegate networkClientDelegate;
private final BackgroundEventHandler backgroundEventHandler;
@SuppressWarnings("this-escape")
public OffsetsRequestManager(final SubscriptionState subscriptionState,
final ConsumerMetadata metadata,
final IsolationLevel isolationLevel,
final Time time,
final long retryBackoffMs,
final long requestTimeoutMs,
final ApiVersions apiVersions,
final NetworkClientDelegate networkClientDelegate,
final BackgroundEventHandler backgroundEventHandler,
final LogContext logContext) {
requireNonNull(subscriptionState);
requireNonNull(metadata);
requireNonNull(isolationLevel);
requireNonNull(time);
requireNonNull(apiVersions);
requireNonNull(networkClientDelegate);
requireNonNull(backgroundEventHandler);
requireNonNull(logContext);
this.metadata = metadata;
this.isolationLevel = isolationLevel;
this.log = logContext.logger(getClass());
this.requestsToRetry = new HashSet<>();
this.requestsToSend = new ArrayList<>();
this.subscriptionState = subscriptionState;
this.time = time;
this.requestTimeoutMs = requestTimeoutMs;
this.apiVersions = apiVersions;
this.networkClientDelegate = networkClientDelegate;
this.backgroundEventHandler = backgroundEventHandler;
this.offsetFetcherUtils = new OffsetFetcherUtils(logContext, metadata, subscriptionState,
time, retryBackoffMs, apiVersions);
// Register the cluster metadata update callback. Note this only relies on the
// requestsToRetry initialized above, and won't be invoked until all managers are
// initialized and the network thread started.
this.metadata.addClusterUpdateListener(this);
}
/**
* Determine if there are pending fetch offsets requests to be sent and build a
* {@link NetworkClientDelegate.PollResult}
* containing it.
*/
@Override
public NetworkClientDelegate.PollResult poll(final long currentTimeMs) {
// Copy the outgoing request list and clear it.
List unsentRequests = new ArrayList<>(requestsToSend);
requestsToSend.clear();
return new NetworkClientDelegate.PollResult(unsentRequests);
}
/**
* Retrieve offsets for the given partitions and timestamp. For each partition, this will
* retrieve the offset of the first message whose timestamp is greater than or equals to the
* target timestamp.
*
* @param timestampsToSearch Partitions and target timestamps to get offsets for
* @param requireTimestamps True if this should fail with an UnsupportedVersionException if the
* broker does not support fetching precise timestamps for offsets
* @return Future containing the map of {@link TopicPartition} and {@link OffsetAndTimestamp}
* found .The future will complete when the requests responses are received and
* processed, following a call to {@link #poll(long)}
*/
public CompletableFuture