use of org.apache.kafka.common.message.ApiVersionsResponseData.ApiVersion in project kafka by apache.
the class RequestResponseTest method testApiVersionResponseWithUnsupportedError.
@Test
public void testApiVersionResponseWithUnsupportedError() {
for (short version : API_VERSIONS.allVersions()) {
ApiVersionsRequest request = new ApiVersionsRequest.Builder().build(version);
ApiVersionsResponse response = request.getErrorResponse(0, Errors.UNSUPPORTED_VERSION.exception());
assertEquals(Errors.UNSUPPORTED_VERSION.code(), response.data().errorCode());
ApiVersion apiVersion = response.data().apiKeys().find(API_VERSIONS.id);
assertNotNull(apiVersion);
assertEquals(API_VERSIONS.id, apiVersion.apiKey());
assertEquals(API_VERSIONS.oldestVersion(), apiVersion.minVersion());
assertEquals(API_VERSIONS.latestVersion(), apiVersion.maxVersion());
}
}
use of org.apache.kafka.common.message.ApiVersionsResponseData.ApiVersion in project kafka by apache.
the class TransactionManagerTest method testAbortTransactionAndResetSequenceNumberOnUnknownProducerId.
@Test
public void testAbortTransactionAndResetSequenceNumberOnUnknownProducerId() throws InterruptedException {
// Set the InitProducerId version such that bumping the epoch number is not supported. This will test the case
// where the sequence number is reset on an UnknownProducerId error, allowing subsequent transactions to
// append to the log successfully
apiVersions.update("0", new NodeApiVersions(Arrays.asList(new ApiVersion().setApiKey(ApiKeys.INIT_PRODUCER_ID.id).setMinVersion((short) 0).setMaxVersion((short) 1), new ApiVersion().setApiKey(ApiKeys.PRODUCE.id).setMinVersion((short) 0).setMaxVersion((short) 7))));
doInitTransactions();
transactionManager.beginTransaction();
transactionManager.maybeAddPartition(tp1);
Future<RecordMetadata> successPartitionResponseFuture = appendToAccumulator(tp1);
prepareAddPartitionsToTxnResponse(Errors.NONE, tp1, epoch, producerId);
prepareProduceResponse(Errors.NONE, producerId, epoch, tp1);
runUntil(successPartitionResponseFuture::isDone);
assertTrue(transactionManager.isPartitionAdded(tp1));
transactionManager.maybeAddPartition(tp0);
Future<RecordMetadata> responseFuture0 = appendToAccumulator(tp0);
prepareAddPartitionsToTxnResponse(Errors.NONE, tp0, epoch, producerId);
prepareProduceResponse(Errors.NONE, producerId, epoch);
runUntil(responseFuture0::isDone);
assertTrue(transactionManager.isPartitionAdded(tp0));
Future<RecordMetadata> responseFuture1 = appendToAccumulator(tp0);
prepareProduceResponse(Errors.NONE, producerId, epoch);
runUntil(responseFuture1::isDone);
Future<RecordMetadata> responseFuture2 = appendToAccumulator(tp0);
client.prepareResponse(produceRequestMatcher(producerId, epoch, tp0), produceResponse(tp0, 0, Errors.UNKNOWN_PRODUCER_ID, 0, 0));
runUntil(responseFuture2::isDone);
assertTrue(transactionManager.hasAbortableError());
TransactionalRequestResult abortResult = transactionManager.beginAbort();
prepareEndTxnResponse(Errors.NONE, TransactionResult.ABORT, producerId, epoch);
runUntil(abortResult::isCompleted);
assertTrue(abortResult.isSuccessful());
abortResult.await();
// make sure we are ready for a transaction now.
assertTrue(transactionManager.isReady());
transactionManager.beginTransaction();
transactionManager.maybeAddPartition(tp0);
prepareAddPartitionsToTxnResponse(Errors.NONE, tp0, epoch, producerId);
runUntil(() -> transactionManager.isPartitionAdded(tp0));
assertEquals(0, transactionManager.sequenceNumber(tp0).intValue());
assertEquals(1, transactionManager.sequenceNumber(tp1).intValue());
}
use of org.apache.kafka.common.message.ApiVersionsResponseData.ApiVersion in project kafka by apache.
the class TransactionManagerTest method testTransitionToFatalErrorWhenRetriedBatchIsExpired.
@Test
public void testTransitionToFatalErrorWhenRetriedBatchIsExpired() throws InterruptedException {
apiVersions.update("0", new NodeApiVersions(Arrays.asList(new ApiVersion().setApiKey(ApiKeys.INIT_PRODUCER_ID.id).setMinVersion((short) 0).setMaxVersion((short) 1), new ApiVersion().setApiKey(ApiKeys.PRODUCE.id).setMinVersion((short) 0).setMaxVersion((short) 7))));
doInitTransactions();
transactionManager.beginTransaction();
transactionManager.maybeAddPartition(tp0);
Future<RecordMetadata> responseFuture = appendToAccumulator(tp0);
assertFalse(responseFuture.isDone());
prepareAddPartitionsToTxnResponse(Errors.NONE, tp0, epoch, producerId);
assertFalse(transactionManager.transactionContainsPartition(tp0));
assertFalse(transactionManager.isSendToPartitionAllowed(tp0));
// Check that only addPartitions was sent.
runUntil(() -> transactionManager.transactionContainsPartition(tp0));
assertTrue(transactionManager.isSendToPartitionAllowed(tp0));
prepareProduceResponse(Errors.NOT_LEADER_OR_FOLLOWER, producerId, epoch);
runUntil(() -> !client.hasPendingResponses());
assertFalse(responseFuture.isDone());
TransactionalRequestResult commitResult = transactionManager.beginCommit();
// Sleep 10 seconds to make sure that the batches in the queue would be expired if they can't be drained.
time.sleep(10000);
// Disconnect the target node for the pending produce request. This will ensure that sender will try to
// expire the batch.
Node clusterNode = metadata.fetch().nodes().get(0);
client.disconnect(clusterNode.idString());
client.backoff(clusterNode, 100);
// We should try to flush the produce, but expire it instead without sending anything.
runUntil(responseFuture::isDone);
try {
// make sure the produce was expired.
responseFuture.get();
fail("Expected to get a TimeoutException since the queued ProducerBatch should have been expired");
} catch (ExecutionException e) {
assertTrue(e.getCause() instanceof TimeoutException);
}
runUntil(commitResult::isCompleted);
// the commit should have been dropped.
assertFalse(commitResult.isSuccessful());
assertTrue(transactionManager.hasFatalError());
assertFalse(transactionManager.hasOngoingTransaction());
}
use of org.apache.kafka.common.message.ApiVersionsResponseData.ApiVersion in project kafka by apache.
the class SaslAuthenticatorTest method testApiVersionsRequestWithServerUnsupportedVersion.
/**
* Tests that unsupported version of ApiVersionsRequest before SASL handshake request
* returns error response and does not result in authentication failure. This test
* is similar to {@link #testUnauthenticatedApiVersionsRequest(SecurityProtocol, short)}
* where a non-SASL client is used to send requests that are processed by
* {@link SaslServerAuthenticator} of the server prior to client authentication.
*/
@Test
public void testApiVersionsRequestWithServerUnsupportedVersion() throws Exception {
short handshakeVersion = ApiKeys.SASL_HANDSHAKE.latestVersion();
SecurityProtocol securityProtocol = SecurityProtocol.SASL_PLAINTEXT;
configureMechanisms("PLAIN", Arrays.asList("PLAIN"));
server = createEchoServer(securityProtocol);
// Send ApiVersionsRequest with unsupported version and validate error response.
String node = "1";
createClientConnection(SecurityProtocol.PLAINTEXT, node);
RequestHeader header = new RequestHeader(new RequestHeaderData().setRequestApiKey(ApiKeys.API_VERSIONS.id).setRequestApiVersion(Short.MAX_VALUE).setClientId("someclient").setCorrelationId(1), (short) 2);
ApiVersionsRequest request = new ApiVersionsRequest.Builder().build();
selector.send(new NetworkSend(node, request.toSend(header)));
ByteBuffer responseBuffer = waitForResponse();
ResponseHeader.parse(responseBuffer, ApiKeys.API_VERSIONS.responseHeaderVersion((short) 0));
ApiVersionsResponse response = ApiVersionsResponse.parse(responseBuffer, (short) 0);
assertEquals(Errors.UNSUPPORTED_VERSION.code(), response.data().errorCode());
ApiVersion apiVersion = response.data().apiKeys().find(ApiKeys.API_VERSIONS.id);
assertNotNull(apiVersion);
assertEquals(ApiKeys.API_VERSIONS.id, apiVersion.apiKey());
assertEquals(ApiKeys.API_VERSIONS.oldestVersion(), apiVersion.minVersion());
assertEquals(ApiKeys.API_VERSIONS.latestVersion(), apiVersion.maxVersion());
// Send ApiVersionsRequest with a supported version. This should succeed.
sendVersionRequestReceiveResponse(node);
// Test that client can authenticate successfully
sendHandshakeRequestReceiveResponse(node, handshakeVersion);
authenticateUsingSaslPlainAndCheckConnection(node, handshakeVersion > 0);
}
use of org.apache.kafka.common.message.ApiVersionsResponseData.ApiVersion in project kafka by apache.
the class ApiVersionsResponse method intersect.
public static Optional<ApiVersion> intersect(ApiVersion thisVersion, ApiVersion other) {
if (thisVersion == null || other == null)
return Optional.empty();
if (thisVersion.apiKey() != other.apiKey())
throw new IllegalArgumentException("thisVersion.apiKey: " + thisVersion.apiKey() + " must be equal to other.apiKey: " + other.apiKey());
short minVersion = (short) Math.max(thisVersion.minVersion(), other.minVersion());
short maxVersion = (short) Math.min(thisVersion.maxVersion(), other.maxVersion());
return minVersion > maxVersion ? Optional.empty() : Optional.of(new ApiVersion().setApiKey(thisVersion.apiKey()).setMinVersion(minVersion).setMaxVersion(maxVersion));
}
Aggregations