Example #1
0
    def test_keyspace_flag_raises_before_v5(self):
        keyspace_message = QueryMessage('a', consistency_level=3, keyspace='ks')
        io = Mock(name='io')

        with self.assertRaisesRegexp(UnsupportedOperation, 'Keyspaces.*set'):
            keyspace_message.send_body(io, protocol_version=4)
        io.assert_not_called()
Example #2
0
    def test_keyspace_written_with_length(self):
        io = Mock(name='io')
        base_expected = [
            (b'\x00\x00\x00\x01', ),
            (b'a', ),
            (b'\x00\x03', ),
            (b'\x00\x00\x00\x80', ),  # options w/ keyspace flag
        ]

        QueryMessage('a', consistency_level=3,
                     keyspace='ks').send_body(io, protocol_version=5)
        self._check_calls(
            io,
            base_expected + [
                (b'\x00\x02', ),  # length of keyspace string
                (b'ks', ),
            ])

        io.reset_mock()

        QueryMessage('a', consistency_level=3,
                     keyspace='keyspace').send_body(io, protocol_version=5)
        self._check_calls(
            io,
            base_expected + [
                (b'\x00\x08', ),  # length of keyspace string
                (b'keyspace', ),
            ])
Example #3
0
    def test_keyspace_flag_raises_before_v5(self):
        keyspace_message = QueryMessage('a',
                                        consistency_level=3,
                                        keyspace='ks')
        io = Mock(name='io')

        with self.assertRaisesRegex(UnsupportedOperation, 'Keyspaces.*set'):
            keyspace_message.send_body(io, protocol_version=4)
        io.assert_not_called()
Example #4
0
    def test_continuous_paging(self):
        """
        Test to check continuous paging throws an Exception if it's not supported and the correct valuesa
        are written to the buffer if the option is enabled.

        @since DSE 2.0b3 GRAPH 1.0b1
        @jira_ticket PYTHON-694
        @expected_result the values are correctly written

        @test_category connection
        """
        max_pages = 4
        max_pages_per_second = 3
        continuous_paging_options = ContinuousPagingOptions(
            max_pages=max_pages, max_pages_per_second=max_pages_per_second)
        message = QueryMessage(
            "a", 3, continuous_paging_options=continuous_paging_options)
        io = Mock()
        for version in [
                version for version in ProtocolVersion.SUPPORTED_VERSIONS
                if not ProtocolVersion.has_continuous_paging_support(version)
        ]:
            self.assertRaises(UnsupportedOperation, message.send_body, io,
                              version)

        io.reset_mock()
        message.send_body(io, ProtocolVersion.DSE_V1)

        # continuous paging adds two write calls to the buffer
        self.assertEqual(len(io.write.mock_calls), 6)
        # Check that the appropriate flag is set to True
        self.assertEqual(
            uint32_unpack(io.write.mock_calls[3][1][0])
            & _WITH_SERIAL_CONSISTENCY_FLAG, 0)
        self.assertEqual(
            uint32_unpack(io.write.mock_calls[3][1][0]) & _PAGE_SIZE_FLAG, 0)
        self.assertEqual(
            uint32_unpack(io.write.mock_calls[3][1][0])
            & _WITH_PAGING_STATE_FLAG, 0)
        self.assertEqual(
            uint32_unpack(io.write.mock_calls[3][1][0]) & _PAGING_OPTIONS_FLAG,
            _PAGING_OPTIONS_FLAG)

        # Test max_pages and max_pages_per_second are correctly written
        self.assertEqual(uint32_unpack(io.write.mock_calls[4][1][0]),
                         max_pages)
        self.assertEqual(uint32_unpack(io.write.mock_calls[5][1][0]),
                         max_pages_per_second)
Example #5
0
    def set_keyspace_async(self, keyspace, callback):
        """
        Use this in order to avoid deadlocking the event loop thread.
        When the operation completes, `callback` will be called with
        two arguments: this connection and an Exception if an error
        occurred, otherwise :const:`None`.
        """
        if not keyspace or keyspace == self.keyspace:
            callback(self, None)
            return

        query = QueryMessage(query='USE "%s"' % (keyspace, ),
                             consistency_level=ConsistencyLevel.ONE)

        def process_result(result):
            if isinstance(result, ResultMessage):
                self.keyspace = keyspace
                callback(self, None)
            elif isinstance(result, InvalidRequestException):
                callback(self, result.to_exception())
            else:
                callback(
                    self,
                    self.defunct(
                        ConnectionException(
                            "Problem while setting keyspace: %r" % (result, ),
                            self.host)))

        self.send_msg(query, process_result, wait_for_id=True)
    def test_errback(self):
        session = self.make_session()
        pool = session._pools.get.return_value
        connection = Mock(spec=Connection)
        pool.borrow_connection.return_value = (connection, 1)

        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query, 1)
        rf._query_retries = 1
        rf.send_request()

        rf.add_errback(self.assertIsInstance, Exception)

        result = Mock(spec=UnavailableErrorMessage,
                      info={
                          "required_replicas": 2,
                          "alive_replicas": 1,
                          "consistency": 1
                      })
        result.to_exception.return_value = Exception()

        rf._set_result(None, None, None, result)
        self.assertRaises(Exception, rf.result)

        # this should get called immediately now that the error is set
        rf.add_errback(self.assertIsInstance, Exception)
    def test_multiple_errbacks(self):
        session = self.make_session()
        pool = session._pools.get.return_value
        connection = Mock(spec=Connection)
        pool.borrow_connection.return_value = (connection, 1)

        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        query.retry_policy = Mock()
        query.retry_policy.on_unavailable.return_value = (RetryPolicy.RETHROW,
                                                          None)
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query)
        rf.send_request()

        callback = Mock()
        arg = "positional"
        kwargs = {'one': 1, 'two': 2}
        rf.add_errback(callback, arg, **kwargs)

        callback2 = Mock()
        arg2 = "another"
        kwargs2 = {'three': 3, 'four': 4}
        rf.add_errback(callback2, arg2, **kwargs2)

        expected_exception = Unavailable("message", 1, 2, 3)
        result = Mock(spec=UnavailableErrorMessage, info={'something': 'here'})
        result.to_exception.return_value = expected_exception
        rf._set_result(result)
        self.assertRaises(Exception, rf.result)

        callback.assert_called_once_with(expected_exception, arg, **kwargs)
        callback2.assert_called_once_with(expected_exception, arg2, **kwargs2)
Example #8
0
    def test_multiple_connections(self):
        """
        Test multiple connections with pipelined requests.
        """
        conns = [self.get_connection() for i in range(5)]
        events = [Event() for i in range(5)]
        query = "SELECT keyspace_name FROM system.schema_keyspaces LIMIT 1"

        def cb(event, conn, count, *args, **kwargs):
            count += 1
            if count >= 10:
                conn.close()
                event.set()
            else:
                conn.send_msg(QueryMessage(
                    query=query, consistency_level=ConsistencyLevel.ONE),
                              request_id=count,
                              cb=partial(cb, event, conn, count))

        for event, conn in zip(events, conns):
            conn.send_msg(QueryMessage(query=query,
                                       consistency_level=ConsistencyLevel.ONE),
                          request_id=0,
                          cb=partial(cb, event, conn, 0))

        for event in events:
            event.wait()
    def test_add_callbacks(self):
        session = self.make_session()
        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        query.retry_policy = Mock()
        query.retry_policy.on_unavailable.return_value = (RetryPolicy.RETHROW, None)
        message = QueryMessage(query=query, consistency_level=ConsistencyLevel.ONE)

        # test errback
        rf = ResponseFuture(session, message, query, 1)
        rf.send_request()

        rf.add_callbacks(
            callback=self.assertEqual, callback_args=([{'col': 'val'}],),
            errback=self.assertIsInstance, errback_args=(Exception,))

        result = Mock(spec=UnavailableErrorMessage, info={})
        rf._set_result(None, None, None, result)
        self.assertRaises(Exception, rf.result)

        # test callback
        rf = ResponseFuture(session, message, query, 1)
        rf.send_request()

        callback = Mock()
        expected_result = [{'col': 'val'}]
        arg = "positional"
        kwargs = {'one': 1, 'two': 2}
        rf.add_callbacks(
            callback=callback, callback_args=(arg,), callback_kwargs=kwargs,
            errback=self.assertIsInstance, errback_args=(Exception,))

        rf._set_result(None, None, None, self.make_mock_response(expected_result))
        self.assertEqual(rf.result(), expected_result)

        callback.assert_called_once_with(expected_result, arg, **kwargs)
Example #10
0
    def test_add_callbacks(self):
        session = self.make_session()
        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        query.retry_policy = Mock()
        query.retry_policy.on_unavailable.return_value = (RetryPolicy.RETHROW, None)
        message = QueryMessage(query=query, consistency_level=ConsistencyLevel.ONE)

        # test errback
        rf = ResponseFuture(session, message, query)
        rf.send_request()

        rf.add_callbacks(
            callback=self.assertEqual, callback_args=([{'col': 'val'}],),
            errback=self.assertIsInstance, errback_args=(Exception,))

        result = Mock(spec=UnavailableErrorMessage, info={})
        rf._set_result(result)
        self.assertRaises(Exception, rf.result)

        # test callback
        rf = ResponseFuture(session, message, query)
        rf.send_request()

        rf.add_callbacks(
            callback=self.assertEqual, callback_args=([{'col': 'val'}],),
            errback=self.assertIsInstance, errback_args=(Exception,))

        rf._set_result(self.make_mock_response([{'col': 'val'}]))
        self.assertEqual(rf.result(), [{'col': 'val'}])
Example #11
0
    def set_keyspace_blocking(self, keyspace):
        if not keyspace or keyspace == self.keyspace:
            return

        query = QueryMessage(query='USE "%s"' % (keyspace, ),
                             consistency_level=ConsistencyLevel.ONE)
        try:
            result = self.wait_for_response(query)
        except InvalidRequestException as ire:
            # the keyspace probably doesn't exist
            raise ire.to_exception()
        except Exception as exc:
            conn_exc = ConnectionException(
                "Problem while setting keyspace: %r" % (exc, ), self.endpoint)
            self.defunct(conn_exc)
            raise conn_exc

        if isinstance(result, ResultMessage):
            self.keyspace = keyspace
        else:
            conn_exc = ConnectionException(
                "Problem while setting keyspace: %r" % (result, ),
                self.endpoint)
            self.defunct(conn_exc)
            raise conn_exc
        def send_msgs(conn, event):
            thread_responses = [False] * num_requests_per_conn
            for i in range(num_requests_per_conn):
                qmsg = QueryMessage(query=query, consistency_level=ConsistencyLevel.ONE)
                with conn.lock:
                    request_id = conn.get_request_id()
                conn.send_msg(qmsg, request_id, cb=partial(cb, conn, event, thread_responses, i))

            event.wait()
Example #13
0
 def server_version(self):
     if self._server_version is None:
         query_message = QueryMessage(
             query="SELECT release_version FROM system.local",
             consistency_level=ConsistencyLevel.ONE)
         message = self.wait_for_response(query_message)
         self._server_version = message.results[1][0][
             0]  # (col names, rows)[rows][first row][only item]
     return self._server_version
Example #14
0
    def test_retry_policy_says_retry(self):
        session = self.make_session()
        pool = session._pools.get.return_value

        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.QUORUM)

        connection = Mock(spec=Connection)
        pool.borrow_connection.return_value = (connection, 1)

        retry_policy = Mock()
        retry_policy.on_unavailable.return_value = (RetryPolicy.RETRY,
                                                    ConsistencyLevel.ONE)

        rf = ResponseFuture(session,
                            message,
                            query,
                            1,
                            retry_policy=retry_policy)
        rf.send_request()

        rf.session._pools.get.assert_called_once_with('ip1')
        pool.borrow_connection.assert_called_once_with(timeout=ANY,
                                                       routing_key=ANY)
        connection.send_msg.assert_called_once_with(
            rf.message,
            1,
            cb=ANY,
            encoder=ProtocolHandler.encode_message,
            decoder=ProtocolHandler.decode_message,
            result_metadata=[])

        result = Mock(spec=UnavailableErrorMessage, info={})
        host = Mock()
        rf._set_result(host, None, None, result)

        session.submit.assert_called_once_with(rf._retry_task, True, host)
        self.assertEqual(1, rf._query_retries)

        connection = Mock(spec=Connection)
        pool.borrow_connection.return_value = (connection, 2)

        # simulate the executor running this
        rf._retry_task(True, host)

        # it should try again with the same host since this was
        # an UnavailableException
        rf.session._pools.get.assert_called_with(host)
        pool.borrow_connection.assert_called_with(timeout=ANY, routing_key=ANY)
        connection.send_msg.assert_called_with(
            rf.message,
            2,
            cb=ANY,
            encoder=ProtocolHandler.encode_message,
            decoder=ProtocolHandler.decode_message,
            result_metadata=[])
Example #15
0
    def test_query_message(self):
        """
        Test to check the appropriate calls are made

        @since 3.9
        @jira_ticket PYTHON-713
        @expected_result the values are correctly written

        @test_category connection
        """
        message = QueryMessage("a", 3)
        io = Mock()

        message.send_body(io, 4)
        self._check_calls(io, [(b'\x00\x00\x00\x01',), (b'a',), (b'\x00\x03',), (b'\x00',)])

        io.reset_mock()
        message.send_body(io, 5)
        self._check_calls(io, [(b'\x00\x00\x00\x01',), (b'a',), (b'\x00\x03',), (b'\x00\x00\x00\x00',)])
Example #16
0
 def send_msgs(all_responses, thread_responses):
     for i in range(num_requests_per_conn):
         qmsg = QueryMessage(query=query,
                             consistency_level=ConsistencyLevel.ONE)
         with conn.lock:
             request_id = conn.get_request_id()
         conn.send_msg(qmsg,
                       request_id,
                       cb=partial(cb, all_responses, thread_responses,
                                  i))
Example #17
0
 def cb(count, *args, **kwargs):
     count += 1
     if count >= 10:
         conn.close()
         event.set()
     else:
         conn.send_msg(QueryMessage(
             query=query, consistency_level=ConsistencyLevel.ONE),
                       request_id=0,
                       cb=partial(cb, count))
Example #18
0
    def set_keyspace_async(self, keyspace, callback):
        """
        Use this in order to avoid deadlocking the event loop thread.
        When the operation completes, `callback` will be called with
        two arguments: this connection and an Exception if an error
        occurred, otherwise :const:`None`.

        This method will always increment :attr:`.in_flight` attribute, even if
        it doesn't need to make a request, just to maintain an
        ":attr:`.in_flight` is incremented" invariant.
        """
        # Here we increment in_flight unconditionally, whether we need to issue
        # a request or not. This is bad, but allows callers -- specifically
        # _set_keyspace_for_all_conns -- to assume that we increment
        # self.in_flight during this call. This allows the passed callback to
        # safely call HostConnection{Pool,}.return_connection on this
        # Connection.
        #
        # We use a busy wait on the lock here because:
        # - we'll only spin if the connection is at max capacity, which is very
        #   unlikely for a set_keyspace call
        # - it allows us to avoid signaling a condition every time a request completes
        while True:
            with self.lock:
                if self.in_flight < self.max_request_id:
                    self.in_flight += 1
                    break
            time.sleep(0.001)

        if not keyspace or keyspace == self.keyspace:
            callback(self, None)
            return

        query = QueryMessage(query='USE "%s"' % (keyspace, ),
                             consistency_level=ConsistencyLevel.ONE)

        def process_result(result):
            if isinstance(result, ResultMessage):
                self.keyspace = keyspace
                callback(self, None)
            elif isinstance(result, InvalidRequestException):
                callback(self, result.to_exception())
            else:
                callback(
                    self,
                    self.defunct(
                        ConnectionException(
                            "Problem while setting keyspace: %r" % (result, ),
                            self.host)))

        # We've incremented self.in_flight above, so we "have permission" to
        # acquire a new request id
        request_id = self.get_request_id()

        self.send_msg(query, request_id, process_result)
Example #19
0
    def test_retry_policy_says_ignore(self):
        session = self.make_session()
        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        query.retry_policy = Mock()
        query.retry_policy.on_unavailable.return_value = (RetryPolicy.IGNORE, None)
        message = QueryMessage(query=query, consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query)
        rf.send_request()

        result = Mock(spec=UnavailableErrorMessage, info={})
        rf._set_result(result)
        self.assertEqual(None, rf.result())
Example #20
0
    def test_write_timeout_error_message(self):
        session = self.make_session()
        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        query.retry_policy = Mock()
        query.retry_policy.on_write_timeout.return_value = (RetryPolicy.RETHROW, None)
        message = QueryMessage(query=query, consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query)
        rf.send_request()

        result = Mock(spec=WriteTimeoutErrorMessage, info={})
        rf._set_result(result)
        self.assertRaises(Exception, rf.result)
    def test_read_timeout_error_message(self):
        session = self.make_session()
        query = SimpleStatement("SELECT * FROM foo")
        query.retry_policy = Mock()
        query.retry_policy.on_read_timeout.return_value = (RetryPolicy.RETHROW, None)
        message = QueryMessage(query=query, consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query, 1)
        rf.send_request()

        result = Mock(spec=ReadTimeoutErrorMessage, info={})
        rf._set_result(None, None, None, result)

        self.assertRaises(Exception, rf.result)
Example #22
0
    def test_add_callbacks(self):
        session = self.make_session()
        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE)

        # test errback
        rf = ResponseFuture(session, message, query, 1)
        rf._query_retries = 1
        rf.send_request()

        rf.add_callbacks(callback=self.assertEqual,
                         callback_args=([{
                             'col': 'val'
                         }], ),
                         errback=self.assertIsInstance,
                         errback_args=(Exception, ))

        result = Mock(spec=UnavailableErrorMessage,
                      info={
                          "required_replicas": 2,
                          "alive_replicas": 1,
                          "consistency": 1
                      })
        result.to_exception.return_value = Exception()
        rf._set_result(None, None, None, result)
        self.assertRaises(Exception, rf.result)

        # test callback
        rf = ResponseFuture(session, message, query, 1)
        rf.send_request()

        callback = Mock()
        expected_result = (object(), object())
        arg = "positional"
        kwargs = {'one': 1, 'two': 2}
        rf.add_callbacks(callback=callback,
                         callback_args=(arg, ),
                         callback_kwargs=kwargs,
                         errback=self.assertIsInstance,
                         errback_args=(Exception, ))

        rf._set_result(
            None, None, None,
            self.make_mock_response(expected_result[0], expected_result[1]))
        self.assertEqual(rf.result()[0], expected_result)

        callback.assert_called_once_with([expected_result], arg, **kwargs)
    def test_write_timeout_error_message(self):
        session = self.make_session()
        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query, 1)
        rf.send_request()

        result = Mock(spec=WriteTimeoutErrorMessage,
                      info={
                          "write_type": 1,
                          "required_responses": 2,
                          "received_responses": 1,
                          "consistency": 1
                      })
        rf._set_result(None, None, None, result)
        self.assertRaises(Exception, rf.result)
    def set_keyspace_async(self, keyspace, callback):
        """
        Use this in order to avoid deadlocking the event loop thread.
        When the operation completes, `callback` will be called with
        two arguments: this connection and an Exception if an error
        occurred, otherwise :const:`None`.
        """
        if not keyspace or keyspace == self.keyspace:
            callback(self, None)
            return

        query = QueryMessage(query='USE "%s"' % (keyspace, ),
                             consistency_level=ConsistencyLevel.ONE)

        def process_result(result):
            if isinstance(result, ResultMessage):
                self.keyspace = keyspace
                callback(self, None)
            elif isinstance(result, InvalidRequestException):
                callback(self, result.to_exception())
            else:
                callback(
                    self,
                    self.defunct(
                        ConnectionException(
                            "Problem while setting keyspace: %r" % (result, ),
                            self.host)))

        request_id = None
        # we use a busy wait on the lock here because:
        # - we'll only spin if the connection is at max capacity, which is very
        #   unlikely for a set_keyspace call
        # - it allows us to avoid signaling a condition every time a request completes
        while True:
            with self.lock:
                if self.in_flight < self.max_request_id:
                    request_id = self.get_request_id()
                    self.in_flight += 1
                    break

            time.sleep(0.001)

        self.send_msg(query, request_id, process_result)
Example #25
0
def make_request():
    log.debug("\n\nMake request called\n\n")

    query = "SELECT keyspace_name FROM system.schema_keyspaces LIMIT 1"

    def cb(*args, **kargs):
        pass

    conn = connection_class.factory(host='127.0.0.1',
                                    timeout=5,
                                    protocol_version=PROTOCOL_VERSION)
    log.debug("Got connection, everything should be good for query")
    conn.send_msg(QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE),
                  request_id=0,
                  cb=cb)
    conn.close()

    log.debug("\n\nRequest ended\n\n")
Example #26
0
def wait_for_schema_agreement(control_con,
                              connection=None,
                              preloaded_results=None):
    for i in xrange(3):
        matched = wait_for_schema_agreement_origin(
            control_con,
            connection=connection,
            preloaded_results=preloaded_results)

        if matched:
            break

        # refresh schema version if schema agreement was stuck somehow

        query = QueryMessage("ALTER TABLE magnetodb.dummy WITH comment=''",
                             consistency_level=ConsistencyLevel.ONE)
        connection.wait_for_response(query)

    return matched
    def test_read_timeout_error_message(self):
        session = self.make_session()
        query = SimpleStatement("SELECT * FROM foo")
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query, 1)
        rf.send_request()

        result = Mock(spec=ReadTimeoutErrorMessage,
                      info={
                          "data_retrieved": "",
                          "required_responses": 2,
                          "received_responses": 1,
                          "consistency": 1
                      })
        rf._set_result(None, None, None, result)

        self.assertRaises(Exception, rf.result)
    def test_unavailable_error_message(self):
        session = self.make_session()
        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        query.retry_policy = Mock()
        query.retry_policy.on_unavailable.return_value = (RetryPolicy.RETHROW,
                                                          None)
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query, 1)
        rf._query_retries = 1
        rf.send_request()

        result = Mock(spec=UnavailableErrorMessage,
                      info={
                          "required_replicas": 2,
                          "alive_replicas": 1,
                          "consistency": 1
                      })
        rf._set_result(None, None, None, result)
        self.assertRaises(Exception, rf.result)
Example #29
0
    def test_single_connection_pipelined_requests(self):
        """
        Test a single connection with pipelined requests.
        """
        conn = self.get_connection()
        query = "SELECT keyspace_name FROM system.schema_keyspaces LIMIT 1"
        responses = [False] * 100
        event = Event()

        def cb(response_list, request_num, *args, **kwargs):
            response_list[request_num] = True
            if all(response_list):
                conn.close()
                event.set()

        for i in range(100):
            conn.send_msg(QueryMessage(query=query,
                                       consistency_level=ConsistencyLevel.ONE),
                          request_id=i,
                          cb=partial(cb, responses, i))

        event.wait()
Example #30
0
    def test_errback(self):
        session = self.make_session()
        pool = session._pools.get.return_value
        connection = Mock(spec=Connection)
        pool.borrow_connection.return_value = (connection, 1)

        query = SimpleStatement("INSERT INFO foo (a, b) VALUES (1, 2)")
        query.retry_policy = Mock()
        query.retry_policy.on_unavailable.return_value = (RetryPolicy.RETHROW, None)
        message = QueryMessage(query=query, consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query)
        rf.send_request()

        rf.add_errback(self.assertIsInstance, Exception)

        result = Mock(spec=UnavailableErrorMessage, info={})
        rf._set_result(result)
        self.assertRaises(Exception, rf.result)

        # this should get called immediately now that the error is set
        rf.add_errback(self.assertIsInstance, Exception)
Example #31
0
    def test_single_connection(self):
        """
        Test a single connection with sequential requests.
        """
        conn = self.get_connection()
        query = "SELECT keyspace_name FROM system.schema_keyspaces LIMIT 1"
        event = Event()

        def cb(count, *args, **kwargs):
            count += 1
            if count >= 10:
                conn.close()
                event.set()
            else:
                conn.send_msg(QueryMessage(
                    query=query, consistency_level=ConsistencyLevel.ONE),
                              request_id=0,
                              cb=partial(cb, count))

        conn.send_msg(QueryMessage(query=query,
                                   consistency_level=ConsistencyLevel.ONE),
                      request_id=0,
                      cb=partial(cb, 0))
        event.wait()
Example #32
0
    def test_heartbeat_defunct_deadlock(self):
        """
        Heartbeat defuncts all connections and clears request queues. Response future times out and even
        if it has been removed from request queue, timeout exception must be thrown. Otherwise event loop
        will deadlock on eventual ResponseFuture.result() call.

        PYTHON-1044
        """

        connection = MagicMock(spec=Connection)
        connection._requests = {}

        pool = Mock()
        pool.is_shutdown = False
        pool.borrow_connection.return_value = [connection, 1]

        session = self.make_basic_session()
        session.cluster._default_load_balancing_policy.make_query_plan.return_value = [
            Mock(), Mock()
        ]
        session._pools.get.return_value = pool

        query = SimpleStatement("SELECT * FROM foo")
        message = QueryMessage(query=query,
                               consistency_level=ConsistencyLevel.ONE)

        rf = ResponseFuture(session, message, query, 1)
        rf.send_request()

        # Simulate Connection.error_all_requests() after heartbeat defuncts
        connection._requests = {}

        # Simulate ResponseFuture timing out
        rf._on_timeout()
        self.assertRaisesRegexp(OperationTimedOut,
                                "Connection defunct by heartbeat", rf.result)