use of org.apache.kafka.common.requests.AddPartitionsToTxnResponse in project kafka by apache.
the class SenderTest method testTransactionAbortedExceptionOnAbortWithoutError.
@Test
public void testTransactionAbortedExceptionOnAbortWithoutError() throws InterruptedException, ExecutionException {
ProducerIdAndEpoch producerIdAndEpoch = new ProducerIdAndEpoch(123456L, (short) 0);
TransactionManager txnManager = new TransactionManager(logContext, "testTransactionAbortedExceptionOnAbortWithoutError", 60000, 100, apiVersions);
setupWithTransactionState(txnManager, false, null);
doInitTransactions(txnManager, producerIdAndEpoch);
// Begin the transaction
txnManager.beginTransaction();
txnManager.maybeAddPartition(tp0);
client.prepareResponse(new AddPartitionsToTxnResponse(0, Collections.singletonMap(tp0, Errors.NONE)));
// Run it once so that the partition is added to the transaction.
sender.runOnce();
// Append a record to the accumulator.
FutureRecordMetadata metadata = appendToAccumulator(tp0, time.milliseconds(), "key", "value");
// Now abort the transaction manually.
txnManager.beginAbort();
// Try to send.
// This should abort the existing transaction and
// drain all the unsent batches with a TransactionAbortedException.
sender.runOnce();
// Now attempt to fetch the result for the record.
TestUtils.assertFutureThrows(metadata, TransactionAbortedException.class);
}
use of org.apache.kafka.common.requests.AddPartitionsToTxnResponse in project kafka by apache.
the class SenderTest method testTransactionalSplitBatchAndSend.
@Test
public void testTransactionalSplitBatchAndSend() throws Exception {
ProducerIdAndEpoch producerIdAndEpoch = new ProducerIdAndEpoch(123456L, (short) 0);
TopicPartition tp = new TopicPartition("testSplitBatchAndSend", 1);
TransactionManager txnManager = new TransactionManager(logContext, "testSplitBatchAndSend", 60000, 100, apiVersions);
setupWithTransactionState(txnManager);
doInitTransactions(txnManager, producerIdAndEpoch);
txnManager.beginTransaction();
txnManager.maybeAddPartition(tp);
client.prepareResponse(new AddPartitionsToTxnResponse(0, Collections.singletonMap(tp, Errors.NONE)));
sender.runOnce();
testSplitBatchAndSend(txnManager, producerIdAndEpoch, tp);
}
use of org.apache.kafka.common.requests.AddPartitionsToTxnResponse in project kafka by apache.
the class SenderTest method addPartitionToTxn.
private void addPartitionToTxn(Sender sender, TransactionManager txnManager, TopicPartition tp) {
txnManager.maybeAddPartition(tp);
client.prepareResponse(new AddPartitionsToTxnResponse(0, Collections.singletonMap(tp, Errors.NONE)));
runUntil(sender, () -> txnManager.isPartitionAdded(tp));
assertFalse(txnManager.hasInFlightRequest());
}
use of org.apache.kafka.common.requests.AddPartitionsToTxnResponse in project kafka by apache.
the class SenderTest method testTransactionalUnknownProducerHandlingWhenRetentionLimitReached.
@Test
public void testTransactionalUnknownProducerHandlingWhenRetentionLimitReached() throws Exception {
final long producerId = 343434L;
TransactionManager transactionManager = new TransactionManager(logContext, "testUnresolvedSeq", 60000, 100, apiVersions);
setupWithTransactionState(transactionManager);
doInitTransactions(transactionManager, new ProducerIdAndEpoch(producerId, (short) 0));
assertTrue(transactionManager.hasProducerId());
transactionManager.beginTransaction();
transactionManager.maybeAddPartition(tp0);
client.prepareResponse(new AddPartitionsToTxnResponse(0, Collections.singletonMap(tp0, Errors.NONE)));
// Receive AddPartitions response
sender.runOnce();
assertEquals(0, transactionManager.sequenceNumber(tp0).longValue());
// Send first ProduceRequest
Future<RecordMetadata> request1 = appendToAccumulator(tp0);
sender.runOnce();
assertEquals(1, client.inFlightRequestCount());
assertEquals(1, transactionManager.sequenceNumber(tp0).longValue());
assertEquals(OptionalInt.empty(), transactionManager.lastAckedSequence(tp0));
sendIdempotentProducerResponse(0, tp0, Errors.NONE, 1000L, 10L);
// receive the response.
sender.runOnce();
assertTrue(request1.isDone());
assertEquals(1000L, request1.get().offset());
assertEquals(OptionalInt.of(0), transactionManager.lastAckedSequence(tp0));
assertEquals(OptionalLong.of(1000L), transactionManager.lastAckedOffset(tp0));
// Send second ProduceRequest, a single batch with 2 records.
appendToAccumulator(tp0);
Future<RecordMetadata> request2 = appendToAccumulator(tp0);
sender.runOnce();
assertEquals(3, transactionManager.sequenceNumber(tp0).longValue());
assertEquals(OptionalInt.of(0), transactionManager.lastAckedSequence(tp0));
assertFalse(request2.isDone());
sendIdempotentProducerResponse(1, tp0, Errors.UNKNOWN_PRODUCER_ID, -1L, 1010L);
// receive response 0, should be retried since the logStartOffset > lastAckedOffset.
sender.runOnce();
// We should have reset the sequence number state of the partition because the state was lost on the broker.
assertEquals(OptionalInt.empty(), transactionManager.lastAckedSequence(tp0));
assertEquals(2, transactionManager.sequenceNumber(tp0).longValue());
assertFalse(request2.isDone());
assertFalse(client.hasInFlightRequests());
// should retry request 1
sender.runOnce();
// resend the request. Note that the expected sequence is 0, since we have lost producer state on the broker.
sendIdempotentProducerResponse(0, tp0, Errors.NONE, 1011L, 1010L);
// receive response 1
sender.runOnce();
assertEquals(OptionalInt.of(1), transactionManager.lastAckedSequence(tp0));
assertEquals(2, transactionManager.sequenceNumber(tp0).longValue());
assertFalse(client.hasInFlightRequests());
assertTrue(request2.isDone());
assertEquals(1012L, request2.get().offset());
assertEquals(OptionalLong.of(1012L), transactionManager.lastAckedOffset(tp0));
}
use of org.apache.kafka.common.requests.AddPartitionsToTxnResponse in project kafka by apache.
the class TransactionManagerTest method testCommitWithTopicAuthorizationFailureInAddPartitionsInFlight.
@Test
public void testCommitWithTopicAuthorizationFailureInAddPartitionsInFlight() throws InterruptedException {
final TopicPartition tp0 = new TopicPartition("foo", 0);
final TopicPartition tp1 = new TopicPartition("bar", 0);
doInitTransactions();
// Begin a transaction, send two records, and begin commit
transactionManager.beginTransaction();
transactionManager.maybeAddPartition(tp0);
transactionManager.maybeAddPartition(tp1);
FutureRecordMetadata firstPartitionAppend = appendToAccumulator(tp0);
FutureRecordMetadata secondPartitionAppend = appendToAccumulator(tp1);
TransactionalRequestResult commitResult = transactionManager.beginCommit();
// We send the AddPartitionsToTxn request in the first sender call
sender.runOnce();
assertFalse(transactionManager.hasError());
assertFalse(commitResult.isCompleted());
assertFalse(firstPartitionAppend.isDone());
// The AddPartitionsToTxn response returns in the next call with the error
Map<TopicPartition, Errors> errors = new HashMap<>();
errors.put(tp0, Errors.TOPIC_AUTHORIZATION_FAILED);
errors.put(tp1, Errors.OPERATION_NOT_ATTEMPTED);
client.respond(body -> {
AddPartitionsToTxnRequest request = (AddPartitionsToTxnRequest) body;
assertEquals(new HashSet<>(request.partitions()), new HashSet<>(errors.keySet()));
return true;
}, new AddPartitionsToTxnResponse(0, errors));
sender.runOnce();
assertTrue(transactionManager.hasError());
assertFalse(commitResult.isCompleted());
assertFalse(firstPartitionAppend.isDone());
assertFalse(secondPartitionAppend.isDone());
// The next call aborts the records, which have not yet been sent. It should
// not block because there are no requests pending and we still need to cancel
// the pending transaction commit.
sender.runOnce();
assertTrue(commitResult.isCompleted());
TestUtils.assertFutureThrows(firstPartitionAppend, KafkaException.class);
TestUtils.assertFutureThrows(secondPartitionAppend, KafkaException.class);
assertTrue(commitResult.error() instanceof TopicAuthorizationException);
}
Aggregations