|
56 | 56 | import org.apache.kafka.clients.admin.ListTransactionsOptions; |
57 | 57 | import org.apache.kafka.clients.admin.ListTransactionsResult; |
58 | 58 | import org.apache.kafka.clients.admin.NewTopic; |
| 59 | +import org.apache.kafka.clients.admin.TransactionDescription; |
59 | 60 | import org.apache.kafka.clients.admin.TransactionListing; |
60 | 61 | import org.apache.kafka.clients.consumer.ConsumerConfig; |
61 | 62 | import org.apache.kafka.clients.consumer.ConsumerRecord; |
|
87 | 88 | @Slf4j |
88 | 89 | public class TransactionTest extends KopProtocolHandlerTestBase { |
89 | 90 |
|
| 91 | + private static final int TRANSACTION_TIMEOUT_CONFIG_VALUE = 600 * 1000; |
| 92 | + |
90 | 93 | protected void setupTransactions() { |
91 | 94 | this.conf.setDefaultNumberOfNamespaceBundles(4); |
92 | 95 | this.conf.setOffsetsTopicNumPartitions(10); |
@@ -1162,7 +1165,7 @@ private KafkaProducer<Integer, String> buildTransactionProducer(String transacti |
1162 | 1165 | producerProps.put(ProducerConfig.TRANSACTION_TIMEOUT_CONFIG, txTimeout); |
1163 | 1166 | } else { |
1164 | 1167 | // very long time-out |
1165 | | - producerProps.put(ProducerConfig.TRANSACTION_TIMEOUT_CONFIG, 600 * 1000); |
| 1168 | + producerProps.put(ProducerConfig.TRANSACTION_TIMEOUT_CONFIG, TRANSACTION_TIMEOUT_CONFIG_VALUE); |
1166 | 1169 | } |
1167 | 1170 | producerProps.put(CLIENT_ID_CONFIG, "dummy_client_" + UUID.randomUUID()); |
1168 | 1171 | addCustomizeProps(producerProps); |
@@ -1491,10 +1494,10 @@ public void testAbortedTxEventuallyPurged() throws Exception { |
1491 | 1494 | } |
1492 | 1495 | } |
1493 | 1496 |
|
1494 | | - @Test(timeOut = 100000 * 30) |
1495 | | - public void testListTransactions() throws Exception { |
| 1497 | + @Test(timeOut = 1000 * 30) |
| 1498 | + public void testListAndDescribeTransactions() throws Exception { |
1496 | 1499 |
|
1497 | | - String topicName = "testListTransactions"; |
| 1500 | + String topicName = "testListAndDescribeTransactions"; |
1498 | 1501 | String transactionalId = "myProducer_" + UUID.randomUUID(); |
1499 | 1502 |
|
1500 | 1503 | @Cleanup |
@@ -1599,116 +1602,33 @@ private static void assertTransactionState(AdminClient kafkaAdmin, String transa |
1599 | 1602 | .findFirst() |
1600 | 1603 | .get(); |
1601 | 1604 | assertEquals(transactionState, transactionListing.state()); |
1602 | | - } |
1603 | | - |
1604 | | - @Test(timeOut = 100000 * 30) |
1605 | | - public void testListTransactions() throws Exception { |
1606 | | - |
1607 | | - String topicName = "testListTransactions"; |
1608 | | - String transactionalId = "myProducer_" + UUID.randomUUID(); |
1609 | | - |
1610 | | - @Cleanup |
1611 | | - KafkaProducer<Integer, String> producer = buildTransactionProducer(transactionalId); |
1612 | | - @Cleanup |
1613 | | - AdminClient kafkaAdmin = AdminClient.create(newKafkaAdminClientProperties()); |
1614 | | - |
1615 | | - producer.initTransactions(); |
1616 | | - producer.beginTransaction(); |
1617 | | - assertTransactionState(kafkaAdmin, transactionalId, |
1618 | | - org.apache.kafka.clients.admin.TransactionState.EMPTY); |
1619 | | - producer.send(new ProducerRecord<>(topicName, 1, "bar")).get(); |
1620 | | - producer.flush(); |
1621 | | - |
1622 | | - ListTransactionsResult listTransactionsResult = kafkaAdmin.listTransactions(); |
1623 | | - listTransactionsResult.all().get().forEach(t -> { |
1624 | | - log.info("Found transactionalId: {} {} {}", |
1625 | | - t.transactionalId(), |
1626 | | - t.producerId(), |
1627 | | - t.state()); |
1628 | | - }); |
1629 | | - assertTransactionState(kafkaAdmin, transactionalId, |
1630 | | - org.apache.kafka.clients.admin.TransactionState.ONGOING); |
1631 | | - Awaitility.await().untilAsserted(() -> { |
1632 | | - assertTransactionState(kafkaAdmin, transactionalId, |
1633 | | - org.apache.kafka.clients.admin.TransactionState.ONGOING); |
1634 | | - }); |
1635 | | - producer.commitTransaction(); |
1636 | | - Awaitility.await().untilAsserted(() -> { |
1637 | | - assertTransactionState(kafkaAdmin, transactionalId, |
1638 | | - org.apache.kafka.clients.admin.TransactionState.COMPLETE_COMMIT); |
1639 | | - }); |
1640 | | - producer.beginTransaction(); |
1641 | | - |
1642 | | - assertTransactionState(kafkaAdmin, transactionalId, |
1643 | | - org.apache.kafka.clients.admin.TransactionState.COMPLETE_COMMIT); |
1644 | | - |
1645 | | - producer.send(new ProducerRecord<>(topicName, 1, "bar")).get(); |
1646 | | - producer.flush(); |
1647 | | - producer.abortTransaction(); |
1648 | | - Awaitility.await().untilAsserted(() -> { |
1649 | | - assertTransactionState(kafkaAdmin, transactionalId, |
1650 | | - org.apache.kafka.clients.admin.TransactionState.COMPLETE_ABORT); |
1651 | | - }); |
1652 | | - producer.close(); |
1653 | | - assertTransactionState(kafkaAdmin, transactionalId, |
1654 | | - org.apache.kafka.clients.admin.TransactionState.COMPLETE_ABORT); |
1655 | | - } |
1656 | 1605 |
|
1657 | | - private static void assertTransactionState(AdminClient kafkaAdmin, String transactionalId, |
1658 | | - org.apache.kafka.clients.admin.TransactionState transactionState) |
1659 | | - throws Exception { |
1660 | | - ListTransactionsResult listTransactionsResult = kafkaAdmin.listTransactions(); |
1661 | | - Collection<TransactionListing> transactionListings = listTransactionsResult.all().get(); |
1662 | | - transactionListings.forEach(t -> { |
1663 | | - log.info("Found transactionalId: {} {} {}", |
1664 | | - t.transactionalId(), |
1665 | | - t.producerId(), |
1666 | | - t.state()); |
1667 | | - }); |
1668 | | - TransactionListing transactionListing = transactionListings |
1669 | | - .stream() |
1670 | | - .filter(t -> t.transactionalId().equals(transactionalId)) |
1671 | | - .findFirst() |
1672 | | - .get(); |
1673 | | - assertEquals(transactionState, transactionListing.state()); |
1674 | | - |
1675 | | - // filter for the same state |
1676 | | - ListTransactionsOptions optionFilterState = new ListTransactionsOptions() |
1677 | | - .filterStates(Collections.singleton(transactionState)); |
1678 | | - listTransactionsResult = kafkaAdmin.listTransactions(optionFilterState); |
1679 | | - transactionListings = listTransactionsResult.all().get(); |
1680 | | - transactionListing = transactionListings |
1681 | | - .stream() |
1682 | | - .filter(t -> t.transactionalId().equals(transactionalId)) |
1683 | | - .findFirst() |
1684 | | - .get(); |
1685 | | - assertEquals(transactionState, transactionListing.state()); |
1686 | | - |
1687 | | - |
1688 | | - // filter for the same producer id |
1689 | | - ListTransactionsOptions optionFilterProducer = new ListTransactionsOptions() |
1690 | | - .filterProducerIds(Collections.singleton(transactionListing.producerId())); |
1691 | | - listTransactionsResult = kafkaAdmin.listTransactions(optionFilterProducer); |
1692 | | - transactionListings = listTransactionsResult.all().get(); |
1693 | | - transactionListing = transactionListings |
1694 | | - .stream() |
1695 | | - .filter(t -> t.transactionalId().equals(transactionalId)) |
1696 | | - .findFirst() |
1697 | | - .get(); |
1698 | | - assertEquals(transactionState, transactionListing.state()); |
| 1606 | + Map<String, TransactionDescription> map = |
| 1607 | + kafkaAdmin.describeTransactions(Collections.singleton(transactionalId)) |
| 1608 | + .all().get(); |
| 1609 | + assertEquals(1, map.size()); |
| 1610 | + TransactionDescription transactionDescription = map.get(transactionalId); |
| 1611 | + log.info("transactionDescription {}", transactionDescription); |
| 1612 | + assertNotNull(transactionDescription); |
| 1613 | + assertEquals(transactionDescription.state(), transactionState); |
| 1614 | + assertTrue(transactionDescription.producerEpoch() >= 0); |
| 1615 | + assertEquals(TRANSACTION_TIMEOUT_CONFIG_VALUE, transactionDescription.transactionTimeoutMs()); |
| 1616 | + assertTrue(transactionDescription.transactionStartTimeMs().isPresent()); |
| 1617 | + assertTrue(transactionDescription.coordinatorId() >= 0); |
| 1618 | + |
| 1619 | + switch (transactionState) { |
| 1620 | + case EMPTY: |
| 1621 | + case COMPLETE_COMMIT: |
| 1622 | + case COMPLETE_ABORT: |
| 1623 | + assertEquals(0, transactionDescription.topicPartitions().size()); |
| 1624 | + break; |
| 1625 | + case ONGOING: |
| 1626 | + assertEquals(1, transactionDescription.topicPartitions().size()); |
| 1627 | + break; |
| 1628 | + default: |
| 1629 | + fail("unhandled " + transactionState); |
| 1630 | + } |
1699 | 1631 |
|
1700 | | - // filter for the same producer id and state |
1701 | | - ListTransactionsOptions optionFilterProducerAndState = new ListTransactionsOptions() |
1702 | | - .filterStates(Collections.singleton(transactionState)) |
1703 | | - .filterProducerIds(Collections.singleton(transactionListing.producerId())); |
1704 | | - listTransactionsResult = kafkaAdmin.listTransactions(optionFilterProducerAndState); |
1705 | | - transactionListings = listTransactionsResult.all().get(); |
1706 | | - transactionListing = transactionListings |
1707 | | - .stream() |
1708 | | - .filter(t -> t.transactionalId().equals(transactionalId)) |
1709 | | - .findFirst() |
1710 | | - .get(); |
1711 | | - assertEquals(transactionState, transactionListing.state()); |
1712 | 1632 | } |
1713 | 1633 |
|
1714 | 1634 | /** |
|
0 commit comments