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)
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'}])
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)
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, 1) 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)
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_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(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(self.make_mock_response(expected_result)) self.assertEqual(rf.result(), expected_result) callback.assert_called_once_with(expected_result, arg, **kwargs)
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)") query.retry_policy = Mock() query.retry_policy.on_unavailable.return_value = (RetryPolicy.RETRY, ConsistencyLevel.ONE) message = QueryMessage(query=query, consistency_level=ConsistencyLevel.QUORUM) rf = ResponseFuture(session, message, query) rf.send_request() rf.session._pools.get.assert_called_once_with('ip1') pool.borrow_connection.assert_called_once_with(timeout=ANY) connection = pool.borrow_connection.return_value connection.send_msg.assert_called_once_with(rf.message, cb=ANY) result = Mock(spec=UnavailableErrorMessage, info={}) rf._set_result(result) session.submit.assert_called_once_with(rf._retry_task, True) self.assertEqual(1, rf._query_retries) # simulate the executor running this rf._retry_task(True) # it should try again with the same host since this was # an UnavailableException rf.session._pools.get.assert_called_with('ip1') pool.borrow_connection.assert_called_with(timeout=ANY) connection = pool.borrow_connection.return_value connection.send_msg.assert_called_with(rf.message, cb=ANY)
def test_request_error_with_prepare_message(self): session = self.make_session() query = SimpleStatement("SELECT * FROM foobar") retry_policy = Mock() retry_policy.on_request_error.return_value = (RetryPolicy.RETHROW, None) message = PrepareMessage(query=query) rf = ResponseFuture(session, message, query, 1, retry_policy=retry_policy) rf._query_retries = 1 rf.send_request() result = Mock(spec=OverloadedErrorMessage) result.to_exception.return_value = result rf._set_result(None, None, None, result) self.assertIsInstance(rf._final_exception, OverloadedErrorMessage) rf = ResponseFuture(session, message, query, 1, retry_policy=retry_policy) rf._query_retries = 1 rf.send_request() result = Mock(spec=ConnectionException) rf._set_result(None, None, None, result) self.assertIsInstance(rf._final_exception, ConnectionException)
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)") query.retry_policy = Mock() query.retry_policy.on_unavailable.return_value = (RetryPolicy.RETRY, ConsistencyLevel.ONE) message = QueryMessage(query=query, consistency_level=ConsistencyLevel.QUORUM) rf = ResponseFuture(session, message, query) rf.send_request() rf.session._pools.get.assert_called_once_with('ip1') pool.borrow_connection.assert_called_once_with(timeout=ANY) connection = pool.borrow_connection.return_value connection.send_msg.assert_called_once_with(rf.message, cb=ANY) result = Mock(spec=UnavailableErrorMessage, info={}) rf._set_result(result) session.submit.assert_called_once_with(rf._retry_task, True) self.assertEqual(1, rf._query_retries) # simulate the executor running this rf._retry_task(True) # it should try again with the same host since this was # an UnavailableException rf.session._pools.get.assert_called_with('ip1') pool.borrow_connection.assert_called_with(timeout=ANY) connection = pool.borrow_connection.return_value connection.send_msg.assert_called_with(rf.message, cb=ANY)
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.assertEquals, 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.assertEquals, callback_args=([{'col': 'val'}],), errback=self.assertIsInstance, errback_args=(Exception,)) response = Mock(spec=ResultMessage, kind=ResultMessage.KIND_ROWS, results=[{'col': 'val'}]) rf._set_result(response) self.assertEqual(rf.result(), [{'col': 'val'}])
def test_all_pools_shutdown(self): session = self.make_basic_session() session._load_balancer.make_query_plan.return_value = ['ip1', 'ip2'] session._pools.get.return_value.is_shutdown = True rf = ResponseFuture(session, Mock(), Mock()) rf.send_request() self.assertRaises(NoHostAvailable, rf.result)
def test_all_pools_shutdown(self): session = self.make_basic_session() session._load_balancer.make_query_plan.return_value = ['ip1', 'ip2'] session._pools.get.return_value.is_shutdown = True rf = ResponseFuture(session, Mock(), Mock()) rf.send_request() self.assertRaises(NoHostAvailable, rf.result)
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=[])
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 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_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())
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_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_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())
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)
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)
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(result) self.assertRaises(Exception, rf.result)
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_errback(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) 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)
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 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_errback(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) 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)
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)
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_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)
def _send_query_message(self, session, timeout, **kwargs): query = "SELECT * FROM test3rf.test" message = QueryMessage(query=query, **kwargs) future = ResponseFuture(session, message, query=None, timeout=timeout) future.send_request() return future
def _send_query_message(self, session, timeout, **kwargs): query = "SELECT * FROM test3rf.test" message = QueryMessage(query=query, **kwargs) future = ResponseFuture(session, message, query=None, timeout=timeout) future.send_request() return future