### Failsafe Event Handlers for Logging Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Shows how to attach event handlers to RetryPolicy and CircuitBreaker during initialization for actions like logging or metrics. Examples include `on_retry`, `on_open`, and `on_close`. ```python import logging from failsafe import Failsafe, CircuitBreaker, RetryPolicy logger = logging.getLogger("MyLogger") circuit_breaker = CircuitBreaker(on_open=lambda: logger.error("Circuit open!")) retry_policy = RetryPolicy(on_retry=lambda: logger.warning("Retrying...")) failsafe = Failsafe(retry_policy=retry_policy, circuit_breaker=circuit_breaker) ``` -------------------------------- ### Development Environment and Testing Commands Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Provides shell commands for setting up a Python virtual environment, running unit tests with pytest, and checking code quality with flake8. ```bash # Setup virtual environment python3 -m venv venv source venv/bin/activate pip install -r requirements_test.txt # Run tests py.test tests/ -v # Run linting flake8 failsafe/ tests/ examples/ ``` -------------------------------- ### Configure Service Fallbacks with FallbackFailsafe Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Shows how to use the FallbackFailsafe class to automatically attempt requests against multiple endpoints. This simplifies failover logic when a primary service is unreachable. ```python import aiohttp from urllib.parse import urljoin from failsafe import FallbackFailsafe class SortingClient: def __init__(self): endpoint_main = "http://eu-west-1.sorting-service.local" endpoint_secondary = "http://eu-central-1.sorting-service.local" self.fallback_failsafe = FallbackFailsafe([endpoint_main, endpoint_secondary]) async def get_sorting(self, name, age): query_path = "/v1/sort/name/{0}/age/{1}".format(name, age) return await self.fallback_failsafe.run(self._request, query_path) async def _request(self, endpoint, query_path): url = urljoin(endpoint, query_path) async with aiohttp.ClientSession() as session: async with session.get(url) as resp: if resp.status != 200: raise Exception() return await resp.json() ``` -------------------------------- ### Basic Failsafe Execution in Python Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Demonstrates the fundamental usage of Failsafe to execute an asynchronous function. This is equivalent to a direct call but allows for future integration with retry or circuit breaker policies. It takes an async function as input and returns its result. ```python from failsafe import Failsafe async def my_async_function(): return 'done' # this is the same as just calling: # result = await my_async_function() result = await Failsafe().run(my_async_function) assert result == 'done' ``` -------------------------------- ### Apache 2.0 License Header for New Files Source: https://github.com/skyscanner/pyfailsafe/blob/master/CONTRIBUTING.md This is a standard header to be included at the beginning of new files in the Pyfailsafe project. It specifies the copyright holder and the terms of the Apache 2.0 license, ensuring compliance and clarity. ```python # Copyright 2016 Skyscanner Limited. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ``` -------------------------------- ### Failsafe with Backoff Strategy in Python Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Demonstrates using the `Backoff` class within `RetryPolicy` for more sophisticated retry delay strategies, including incremental delays and optional jitter. This helps manage load on external services and provides a more resilient retry mechanism. ```python from datetime import timedelta from failsafe import Failsafe, RetryPolicy, Backoff async def my_async_function(): raise Exception() # by default, every exception will cause a retry backoff = Backoff( delay=timedelta(seconds=2), # the initial delay max_delay=timedelta(seconds=15), jitter=False # if True, the wait time will be random between 0 and the actual time for this attempt ) retry_policy = RetryPolicy(allowed_retries=3, backoff=backoff) await Failsafe(retry_policy=retry_policy).run(my_async_function) # raises failsafe.RetriesExhausted # my_async_function was called 4 times, waiting for 2, 4 and 8 seconds respectively. ``` -------------------------------- ### Combining Circuit Breaker and Retry Policy Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Demonstrates the recommended practice of using CircuitBreakers in conjunction with RetryPolicies. Failures during retries are counted towards the circuit breaker's failure threshold. ```python from failsafe import Failsafe, CircuitBreaker, RetryPolicy async def my_async_function(): raise Exception() circuit_breaker = CircuitBreaker() retry_policy = RetryPolicy() failsafe = Failsafe(circuit_breaker=circuit_breaker, retry_policy=retry_policy) await failsafe.run(my_async_function) ``` -------------------------------- ### Implement HTTP Requests with Failsafe Policies Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Demonstrates how to wrap an asynchronous HTTP request using Failsafe's RetryPolicy and CircuitBreaker. It requires an aiohttp session and handles exceptions to trigger retry logic. ```python from failsafe import Failsafe, RetryPolicy, CircuitBreaker, FailsafeError import aiohttp circuit_breaker = CircuitBreaker() retry_policy = RetryPolicy() failsafe = Failsafe(circuit_breaker=circuit_breaker, retry_policy=retry_policy) async def make_get_request(url): async def _make_get_request(_url): with aiohttp.ClientSession() as session: async with session.get(_url) as resp: if resp.status != 200: raise Exception() # exception tells Failsafe to retry return await resp.json() try: return await failsafe.run(_make_get_request, url) except FailsafeError: raise RuntimeError("Error while getting data") ``` -------------------------------- ### Standalone Circuit Breaker Operations Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Illustrates manual control over a CircuitBreaker instance, allowing direct opening, closing, and state checking. It also shows how to report success or failure after an execution attempt. ```python from failsafe import CircuitBreaker circuit_breaker = CircuitBreaker() circuit_breaker.open() # executions won't be allowed when circuit breaker is open circuit_breaker.close() circuit_breaker.current_state # 'open' or 'closed' if circuit_breaker.allows_execution(): try: do_something() circuit_breaker.report_success() except: circuit_breaker.report_failure() ``` -------------------------------- ### Failsafe with Delayed Retries in Python Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Shows how to implement delayed retries using `Failsafe` and `RetryPolicy` with a specified delay between attempts. The `Delay` class, using `timedelta`, controls the waiting period. This prevents immediate, rapid retries and can be useful for external service interactions. ```python from datetime import timedelta from failsafe import Failsafe, RetryPolicy, Delay async def my_async_function(): raise Exception() # by default, every exception will cause a retry delay = Delay(timedelta(seconds=5)) retry_policy = RetryPolicy(allowed_retries=3, backoff=delay) await Failsafe(retry_policy=retry_policy).run(my_async_function) # raises failsafe.RetriesExhausted # my_async_function was called 4 times, waiting for 5 seconds between each call. ``` -------------------------------- ### Failsafe with Abortable Exceptions Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Demonstrates how to configure Failsafe to not retry on specific exceptions by listing them in `abortable_exceptions`. This prevents unnecessary retries for known non-recoverable errors. ```python from failsafe import Failsafe, RetryPolicy async def my_async_function(): raise ValueError() # ValueError is an abortable exception, so it will not cause retry retry_policy = RetryPolicy(allowed_retries=4, abortable_exceptions=[ValueError]) await Failsafe(retry_policy=retry_policy).run(my_async_function) # raises ValueError # my_async_function was called 1 time (1 regular call) ``` -------------------------------- ### Failsafe with Specific Retriable Exceptions in Python Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Shows how to configure `RetryPolicy` to only retry on specific types of exceptions, defined in `retriable_exceptions`. Other exceptions will cause the operation to fail immediately. This provides fine-grained control over retry behavior. ```python from failsafe import Failsafe, RetryPolicy async def my_async_function(): return 3/0 retry_policy = RetryPolicy(allowed_retries=3, retriable_exceptions=[ZeroDivisionError]) await Failsafe(retry_policy=retry_policy).run(my_async_function) # raises failsafe.RetriesExhausted # my_async_function was called 4 times (1 regular call + 3 retries) ``` ```python from failsafe import Failsafe, RetryPolicy async def my_async_function(): raise TypeError() retry_policy = RetryPolicy(allowed_retries=3, retriable_exceptions=[ZeroDivisionError]) await Failsafe(retry_policy=retry_policy).run(my_async_function) # TypeError is not ZeroDivisionError, so my_async_function was called just once in this example ``` -------------------------------- ### Failsafe with Retries in Python Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Illustrates how to configure Failsafe to automatically retry an operation upon failure. It utilizes the `RetryPolicy` class to specify the maximum number of retries. By default, any exception triggers a retry. If retries are exhausted, a `RetriesExhausted` exception is raised. ```python from failsafe import Failsafe, RetryPolicy async def my_async_function(): raise Exception() # by default, every exception will cause a retry retry_policy = RetryPolicy(allowed_retries=3) await Failsafe(retry_policy=retry_policy).run(my_async_function) # raises failsafe.RetriesExhausted # my_async_function was called 4 times (1 regular call + 3 retries) ``` -------------------------------- ### Circuit Breaker Implementation Source: https://github.com/skyscanner/pyfailsafe/blob/master/README.md Shows how to use a CircuitBreaker to temporarily disable execution of a function after a certain number of failures. This prevents system overload by failing fast. ```python from failsafe import Failsafe, CircuitBreaker async def my_async_function(): raise Exception() circuit_breaker = CircuitBreaker(maximum_failures=3, reset_timeout_seconds=60) failsafe = Failsafe(circuit_breaker=circuit_breaker) await failsafe.run(my_async_function) await failsafe.run(my_async_function) await failsafe.run(my_async_function) # now circuit breaker will get open and other calls to Failsafe.run will # immediately raise the failsafe.CircuitOpen exception and the passed # function will not even be called. # Circuit will be closed again in 60 seconds. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.