def test_circuitbreaker_should_clear_last_exception_on_success_call(): cb = CircuitBreaker(name='Foobar') cb._last_failure = IOError() assert isinstance(cb.last_failure, IOError) cb.call(lambda: True) assert cb.last_failure is None
def test_circuitbreaker_error__str__(): cb = CircuitBreaker(name='Foobar') cb._last_failure = Exception() error = CircuitBreakerError(cb) assert str(error).startswith('Circuit "Foobar" OPEN until ') assert str(error).endswith( '(0 failures, 30 sec remaining) (last_failure: Exception())')
def test_circuitbreaker_should_save_last_exception_on_failure_call(): cb = CircuitBreaker(name='Foobar') func = Mock(side_effect=IOError) with raises(IOError): cb.call(func) assert isinstance(cb.last_failure, IOError)
def test_circuitbreaker_should_call_fallback_function_if_open(): fallback = Mock(return_value=True) func = Mock(return_value=False) CircuitBreaker.opened = lambda self: True cb = CircuitBreaker(name='WithFallback', fallback_function=fallback) cb.call(func) fallback.assert_called_once_with()
def next(self, service_type): cache_status = SUCCESS sleep(0.3) #give some time for processing previous request cache = CacheDriver() service1 = None service2 = None try: service1 = cache.do("custom", 'rpoplpush', [ "services-" + str(service_type), "services-" + str(service_type) ]) except Exception as e: test_logger.error( "ERROR: Custom cache rpoplpush command failed on" + str([ "services-" + str(service_type), "services-" + str(service_type) ])) test_logger.error(str(e)) cache_status = CUSTOM_CACHE_FAILED try: service2 = cache.do("redis", 'rpoplpush', [ "services-" + str(service_type), "services-" + str(service_type) ]) if service2 is not None: service2 = service2.decode('utf-8') except Exception as e: test_logger.error( "ERROR: Redis cache rpoplpush command failed on" + str([ "services-" + str(service_type), "services-" + str(service_type) ])) test_logger.error(str(e)) cache_status = REDIS_CACHE_FAILED if SUCCESS else BOTH_CACHES_FAILED if cache_status == BOTH_CACHES_FAILED: test_logger.error( "ERROR: Alert! Both caches rpoplpush command failed on " + str([ "services-" + str(service_type), "services-" + str(service_type) ])) if service1 is not None: circuitbreaker = CircuitBreaker(service1, service_type) elif service2 is not None: circuitbreaker = CircuitBreaker(service2, service_type) return circuitbreaker
def __init__(self, name, failure_threshold=5, recovery_timeout=60, expected_exception=RequestException): self.breaker = CircuitBreaker(failure_threshold, recovery_timeout, expected_exception, name)
import requests from rest_framework.views import APIView, Response from uuid import UUID import logging from .baseview import BaseView from circuitbreaker import CircuitBreaker, CircuitBreakerError from requests.exceptions import RequestException RCB = CircuitBreaker(failure_threshold=5, recovery_timeout=30, expected_exception=RequestException) class Room(BaseView): URL = 'http://localhost:8001/api/room/' URL1 = 'http://localhost:8002/api/guest/' URL2 = 'http://localhost:8003/api/menus/' @RCB def get_room(self, request, n_uuid): self.info(request) response = requests.get(self.URL + f'{n_uuid}') return Response(self.safeResponse(response), status=response.status_code) @RCB def patch_room(self, request, n_uuid): self.info(request) response = requests.patch(self.URL + f'{n_uuid}', request.data) return Response(self.safeResponse(response),
def test_circuitbreaker__str__(): cb = CircuitBreaker(name='Foobar') assert str(cb) == 'Foobar'
class TestIntent(unittest.TestCase): def setUp(self): request = SimpleNamespace() request.json = { "context": { "attributes": {}, "intent": "TELEKOM_Demo_Intent", "locale": "de", "tokens": {} }, "session": { "new": True, "id": "12345", "attributes": { "key-1": "value-1", "key-2": "value-2" } }, } request.headers = {} self.ctx = Context(request) self.ctx.tracer = Tracer(request) @patch.object(logging.Logger, 'warning') def test_init_exceptions(self, warn_mock): with self.assertRaises(TypeError): Intent({}) with self.assertRaises(ValueError): Intent('', None) with self.assertRaises(ValueError): Intent('demo_intent', 'random.does_not_exist') @patch('random.randint', return_value=1) def test_call_bad_return_type(self, mock_gde): mock_gde.__name__ = 'mock_gde' intent = Intent('TELEKOM_Demo_Intent', random.randint) with self.assertRaises(ValueError): intent(self.ctx).dict(self.ctx) @patch('random.randint', return_value=ErrorResponse(999, 'some error')) def test_call_error_999(self, mock_gde): mock_gde.__name__ = 'mock_gde' intent = Intent('TELEKOM_Demo_Intent', random.randint) self.assertIsInstance(intent(self.ctx), ErrorResponse) @patch('random.randint', side_effect=RequestException()) def test_call_requests_error(self, mock_gde): mock_gde.__name__ = 'mock_gde' intent = Intent('TELEKOM_Demo_Intent', random.randint) response = intent(self.ctx) self.assertIsInstance(response, Response) self.assertEqual(response.text, 'GENERIC_HTTP_ERROR_RESPONSE') @patch('random.randint', side_effect=CircuitBreakerError(CircuitBreaker())) def test_call_circuit_breaker_open(self, mock_gde): mock_gde.__name__ = 'mock_gde' intent = Intent('TELEKOM_Demo_Intent', random.randint) response = intent(self.ctx) self.assertIsInstance(response, Response) self.assertEqual(response.text, 'GENERIC_HTTP_ERROR_RESPONSE') @patch('random.randint', return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL)) def test_append_push_messages_empty(self, mock_gde): mock_gde.__name__ = 'mock_gde' context = create_context('TELEKOM_Demo_Intent') intent = Intent('TELEKOM_Demo_Intent', random.randint) response = intent(context) response = intent._append_push_messages(context, response) self.assertEqual(response.push_notification, None) @patch('random.randint', return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL)) def test_append_push_messages_one(self, mock_gde): mock_gde.__name__ = 'mock_gde' context = create_context('TELEKOM_Demo_Intent') intent = Intent('TELEKOM_Demo_Intent', random.randint) response = intent(context) context.push_messages = {'device': [{'payload': 1}]} response = intent._append_push_messages(context, response) self.assertEqual(response.push_notification, { 'targetName': 'device', 'messagePayload': { 'payload': 1 } }) @patch('random.randint', return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL)) def test_append_push_messages_two_messages(self, mock_gde): mock_gde.__name__ = 'mock_gde' context = create_context('TELEKOM_Demo_Intent') intent = Intent('TELEKOM_Demo_Intent', random.randint) response = intent(context) context.push_messages = {'device': [{'payload': 1}, {'payload': 2}]} with self.assertRaises(ValueError): _ = intent._append_push_messages(context, response) @patch('random.randint', return_value=Response(text='some text', type_=RESPONSE_TYPE_TELL)) def test_append_push_messages_two_devices(self, mock_gde): mock_gde.__name__ = 'mock_gde' context = create_context('TELEKOM_Demo_Intent') intent = Intent('TELEKOM_Demo_Intent', random.randint) response = intent(context) context.push_messages = { 'device': [{ 'payload': 1 }], 'device2': [{ 'payload': 2 }] } with self.assertRaises(ValueError): _ = intent._append_push_messages(context, response) def test_repr(self): self.assertIn('TELEKOM_Demo_Intent', repr(Intent('TELEKOM_Demo_Intent', random.randint))) def test_response_returns_message(self): """ Test if context._ returns l10n.Message """ l10n.translations = {'de': l10n.Translations()} context = create_context('TELEKOM_Demo_Intent') with patch('random.randint', return_value=Response( text=context._('some text'))) as mock_gde: mock_gde.__name__ = 'mock_gde' intent = Intent('TELEKOM_Demo_Intent', random.randint) response = intent(context) self.assertIsInstance(response.text, l10n.Message)
def __init__(self, service, config, signer, type_mapping, **kwargs): validate_config(config, signer=signer) self.signer = signer # Default to true (is a regional client) if there is nothing explicitly set. Regional # clients allow us to call set_region and that'll also set the endpoint. For non-regional # clients we require an endpoint self.regional_client = kwargs.get('regional_client', True) self._endpoint = None self._base_path = kwargs.get('base_path') self.service_endpoint_template = kwargs.get( 'service_endpoint_template') self.endpoint_service_name = kwargs.get('endpoint_service_name') if self.regional_client: if kwargs.get('service_endpoint'): self.endpoint = kwargs.get('service_endpoint') else: region_to_use = None if 'region' in config and config['region']: region_to_use = config.get('region') elif hasattr(signer, 'region'): region_to_use = signer.region self.endpoint = regions.endpoint_for( service, service_endpoint_template=self.service_endpoint_template, region=region_to_use, endpoint=config.get('endpoint'), endpoint_service_name=self.endpoint_service_name) else: if not kwargs.get('service_endpoint'): raise exceptions.MissingEndpointForNonRegionalServiceClientError( 'An endpoint must be provided for a non-regional service client' ) self.endpoint = kwargs.get('service_endpoint') self.service = service self.complex_type_mappings = type_mapping self.type_mappings = merge_type_mappings(self.primitive_type_map, type_mapping) self.session = requests.Session() # If the user doesn't specify timeout explicitly we would use default timeout. self.timeout = kwargs.get('timeout') if 'timeout' in kwargs else ( DEFAULT_CONNECTION_TIMEOUT, DEFAULT_READ_TIMEOUT) self.user_agent = build_user_agent( get_config_value_or_default(config, "additional_user_agent")) self.logger = logging.getLogger("{}.{}".format(__name__, id(self))) self.logger.addHandler(logging.NullHandler()) if get_config_value_or_default(config, "log_requests"): self.logger.disabled = False self.logger.setLevel(logging.DEBUG) is_http_log_enabled(True) else: self.logger.disabled = True is_http_log_enabled(False) self.skip_deserialization = kwargs.get('skip_deserialization') # Circuit Breaker at client level self.circuit_breaker_strategy = kwargs.get('circuit_breaker_strategy') self.circuit_breaker_name = None # Log if Circuit Breaker Strategy is not enabled or if using Default Circuit breaker Strategy if self.circuit_breaker_strategy is None or isinstance( self.circuit_breaker_strategy, NoCircuitBreakerStrategy): self.logger.debug('No circuit breaker strategy enabled!') else: # Enable Circuit breaker if a valid circuit breaker strategy is available if not isinstance(self.circuit_breaker_strategy, CircuitBreakerStrategy): raise TypeError('Invalid Circuit Breaker Strategy!') self.circuit_breaker_name = str( uuid.uuid4() ) if self.circuit_breaker_strategy.name is None else self.circuit_breaker_strategy.name # Re-use Circuit breaker if sharing a Circuit Breaker Strategy. circuit_breaker = CircuitBreakerMonitor.get( self.circuit_breaker_name) if circuit_breaker is None: circuit_breaker = CircuitBreaker( failure_threshold=self.circuit_breaker_strategy. failure_threshold, recovery_timeout=self.circuit_breaker_strategy. recovery_timeout, expected_exception=self.circuit_breaker_strategy. expected_exception, name=self.circuit_breaker_name) # Equivalent to decorating the request function with Circuit Breaker self.request = circuit_breaker(self.request) self.logger.debug('Endpoint: {}'.format(self._endpoint))
def test_init_with_circuit_breaker(self): cb = CircuitBreaker() zcbs = CircuitBreakerSession(circuit_breaker=cb) self.assertEqual(zcbs.internal, False) self.assertEqual(zcbs.circuit_breaker, cb) self.assertTrue(isinstance(zcbs, Session))