예제 #1
0
    async def test_sender__do_add_partitions_to_txn_ok(self):
        sender = await self._setup_sender()
        tps = [
            TopicPartition("topic", 0),
            TopicPartition("topic", 1),
            TopicPartition("topic2", 1)
        ]
        add_handler = AddPartitionsToTxnHandler(sender, tps)
        tm = sender._txn_manager
        tm.partition_added = mock.Mock()

        # Handle response
        cls = AddPartitionsToTxnResponse[0]
        resp = cls(
            throttle_time_ms=300,
            errors=[
                ("topic", [
                    (0, NoError.errno),
                    (1, NoError.errno)
                ]),
                ("topic2", [
                    (1, NoError.errno)
                ])
            ]
        )
        backoff = add_handler.handle_response(resp)
        self.assertIsNone(backoff)
        self.assertEqual(tm.partition_added.call_count, 3)
        tm.partition_added.assert_has_calls([
            mock.call(tp) for tp in tps
        ])
예제 #2
0
    async def test_sender__do_add_partitions_to_txn_ok(self):
        sender = await self._setup_sender()
        tps = [
            TopicPartition("topic", 0),
            TopicPartition("topic", 1),
            TopicPartition("topic2", 1)
        ]
        add_handler = AddPartitionsToTxnHandler(sender, tps)
        tm = sender._txn_manager
        tm.partition_added = mock.Mock()

        # Handle response
        cls = AddPartitionsToTxnResponse[0]
        resp = cls(
            throttle_time_ms=300,
            errors=[
                ("topic", [
                    (0, NoError.errno),
                    (1, NoError.errno)
                ]),
                ("topic2", [
                    (1, NoError.errno)
                ])
            ]
        )
        backoff = add_handler.handle_response(resp)
        self.assertIsNone(backoff)
        self.assertEqual(tm.partition_added.call_count, 3)
        tm.partition_added.assert_has_calls([
            mock.call(tp) for tp in tps
        ])
예제 #3
0
    async def test_sender__do_add_partitions_to_txn_create(self):
        sender = await self._setup_sender()
        tps = [
            TopicPartition("topic", 0),
            TopicPartition("topic", 1),
            TopicPartition("topic2", 1)
        ]
        add_handler = AddPartitionsToTxnHandler(sender, tps)

        req = add_handler.create_request()
        self.assertEqual(req.API_KEY, AddPartitionsToTxnRequest[0].API_KEY)
        self.assertEqual(req.API_VERSION, 0)
        self.assertEqual(req.transactional_id, "test_tid")
        self.assertEqual(req.producer_id, 120)
        self.assertEqual(req.producer_epoch, 22)
        self.assertEqual(list(sorted(req.topics)),
                         list(sorted([("topic", [0, 1]), ("topic2", [1])])))
예제 #4
0
    async def test_sender__do_add_partitions_to_txn_create(self):
        sender = await self._setup_sender()
        tps = [
            TopicPartition("topic", 0),
            TopicPartition("topic", 1),
            TopicPartition("topic2", 1)
        ]
        add_handler = AddPartitionsToTxnHandler(sender, tps)

        req = add_handler.create_request()
        self.assertEqual(req.API_KEY, AddPartitionsToTxnRequest[0].API_KEY)
        self.assertEqual(req.API_VERSION, 0)
        self.assertEqual(req.transactional_id, "test_tid")
        self.assertEqual(req.producer_id, 120)
        self.assertEqual(req.producer_epoch, 22)
        self.assertEqual(
            list(sorted(req.topics)),
            list(sorted([("topic", [0, 1]), ("topic2", [1])])))
예제 #5
0
    async def test_sender__do_add_partitions_to_txn_not_ok(self):
        sender = await self._setup_sender()
        tps = [
            TopicPartition("topic", 0),
            TopicPartition("topic", 1),
            TopicPartition("topic2", 1)
        ]
        add_handler = AddPartitionsToTxnHandler(sender, tps)
        tm = sender._txn_manager
        tm.begin_transaction()
        tm.partition_added = mock.Mock()

        def create_response(error_type):
            cls = AddPartitionsToTxnResponse[0]
            resp = cls(
                throttle_time_ms=300,
                errors=[
                    ("topic", [
                        (0, error_type.errno),
                        (1, error_type.errno)
                    ]),
                    ("topic2", [
                        (1, error_type.errno)
                    ])
                ]
            )
            return resp

        # Handle coordination errors
        for error_cls in [CoordinatorNotAvailableError, NotCoordinatorError]:
            with mock.patch.object(sender, "_coordinator_dead") as mocked:
                resp = create_response(error_cls)
                backoff = add_handler.handle_response(resp)
                self.assertEqual(backoff, 0.1)
                tm.partition_added.assert_not_called()
                mocked.assert_called_with(CoordinationType.TRANSACTION)

        # Special case for ConcurrentTransactions
        resp = create_response(ConcurrentTransactions)
        backoff = add_handler.handle_response(resp)
        self.assertEqual(backoff, 0.02)  # BACKOFF_OVERRIDE
        tm.partition_added.assert_not_called()

        # Special case for ConcurrentTransactions if this is not the first call
        tm._txn_partitions.add(tps[0])
        resp = create_response(ConcurrentTransactions)
        backoff = add_handler.handle_response(resp)
        self.assertEqual(backoff, 0.1)  # Default backoff
        tm.partition_added.assert_not_called()

        # Not coordination retriable errors
        for error_cls in [
                CoordinatorLoadInProgressError, UnknownTopicOrPartitionError]:
            resp = create_response(error_cls)
            backoff = add_handler.handle_response(resp)
            self.assertEqual(backoff, 0.1)
            tm.partition_added.assert_not_called()

        # ProducerFenced case
        resp = create_response(InvalidProducerEpoch)
        with self.assertRaises(ProducerFenced):
            add_handler.handle_response(resp)
        tm.partition_added.assert_not_called()

        for error_type in [InvalidProducerIdMapping, InvalidTxnState]:
            resp = create_response(error_type)
            with self.assertRaises(error_type):
                add_handler.handle_response(resp)
            tm.partition_added.assert_not_called()

        # Handle unknown error
        resp = create_response(UnknownError)
        with self.assertRaises(UnknownError):
            add_handler.handle_response(resp)
        tm.partition_added.assert_not_called()

        # Handle TransactionalIdAuthorizationFailed
        resp = create_response(TransactionalIdAuthorizationFailed)
        with self.assertRaises(TransactionalIdAuthorizationFailed) as cm:
            add_handler.handle_response(resp)
        tm.partition_added.assert_not_called()
        self.assertEqual(cm.exception.args[0], "test_tid")

        # TopicAuthorizationFailedError case
        resp = create_response(OperationNotAttempted)
        backoff = add_handler.handle_response(resp)
        self.assertIsNone(backoff)
        tm.partition_added.assert_not_called()

        # TopicAuthorizationFailedError case
        self.assertNotEqual(tm.state, TransactionState.ABORTABLE_ERROR)
        resp = create_response(TopicAuthorizationFailedError)
        backoff = add_handler.handle_response(resp)
        self.assertIsNone(backoff)
        tm.partition_added.assert_not_called()
        self.assertEqual(tm.state, TransactionState.ABORTABLE_ERROR)
예제 #6
0
    async def test_sender__do_add_partitions_to_txn_not_ok(self):
        sender = await self._setup_sender()
        tps = [
            TopicPartition("topic", 0),
            TopicPartition("topic", 1),
            TopicPartition("topic2", 1)
        ]
        add_handler = AddPartitionsToTxnHandler(sender, tps)
        tm = sender._txn_manager
        tm.begin_transaction()
        tm.partition_added = mock.Mock()

        def create_response(error_type):
            cls = AddPartitionsToTxnResponse[0]
            resp = cls(throttle_time_ms=300,
                       errors=[("topic", [(0, error_type.errno),
                                          (1, error_type.errno)]),
                               ("topic2", [(1, error_type.errno)])])
            return resp

        # Handle coordination errors
        for error_cls in [CoordinatorNotAvailableError, NotCoordinatorError]:
            with mock.patch.object(sender, "_coordinator_dead") as mocked:
                resp = create_response(error_cls)
                backoff = add_handler.handle_response(resp)
                self.assertEqual(backoff, 0.1)
                tm.partition_added.assert_not_called()
                mocked.assert_called_with(CoordinationType.TRANSACTION)

        # Special case for ConcurrentTransactions
        resp = create_response(ConcurrentTransactions)
        backoff = add_handler.handle_response(resp)
        self.assertEqual(backoff, 0.02)  # BACKOFF_OVERRIDE
        tm.partition_added.assert_not_called()

        # Special case for ConcurrentTransactions if this is not the first call
        tm._txn_partitions.add(tps[0])
        resp = create_response(ConcurrentTransactions)
        backoff = add_handler.handle_response(resp)
        self.assertEqual(backoff, 0.1)  # Default backoff
        tm.partition_added.assert_not_called()

        # Not coordination retriable errors
        for error_cls in [
                CoordinatorLoadInProgressError, UnknownTopicOrPartitionError
        ]:
            resp = create_response(error_cls)
            backoff = add_handler.handle_response(resp)
            self.assertEqual(backoff, 0.1)
            tm.partition_added.assert_not_called()

        # ProducerFenced case
        resp = create_response(InvalidProducerEpoch)
        with self.assertRaises(ProducerFenced):
            add_handler.handle_response(resp)
        tm.partition_added.assert_not_called()

        for error_type in [InvalidProducerIdMapping, InvalidTxnState]:
            resp = create_response(error_type)
            with self.assertRaises(error_type):
                add_handler.handle_response(resp)
            tm.partition_added.assert_not_called()

        # Handle unknown error
        resp = create_response(UnknownError)
        with self.assertRaises(UnknownError):
            add_handler.handle_response(resp)
        tm.partition_added.assert_not_called()

        # Handle TransactionalIdAuthorizationFailed
        resp = create_response(TransactionalIdAuthorizationFailed)
        with self.assertRaises(TransactionalIdAuthorizationFailed) as cm:
            add_handler.handle_response(resp)
        tm.partition_added.assert_not_called()
        self.assertEqual(cm.exception.args[0], "test_tid")

        # TopicAuthorizationFailedError case
        resp = create_response(OperationNotAttempted)
        backoff = add_handler.handle_response(resp)
        self.assertIsNone(backoff)
        tm.partition_added.assert_not_called()

        # TopicAuthorizationFailedError case
        self.assertNotEqual(tm.state, TransactionState.ABORTABLE_ERROR)
        resp = create_response(TopicAuthorizationFailedError)
        backoff = add_handler.handle_response(resp)
        self.assertIsNone(backoff)
        tm.partition_added.assert_not_called()
        self.assertEqual(tm.state, TransactionState.ABORTABLE_ERROR)