{ "info": { "author": "Fabian Fuelling", "author_email": "pypi@fabfuel.de", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: MacOS", "Operating System :: POSIX", "Operating System :: Unix", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3" ], "description": "CircuitBreaker\n--------------\n\n.. image:: https://badge.fury.io/py/circuitbreaker.svg\n :target: https://badge.fury.io/py/circuitbreaker\n\n.. image:: https://travis-ci.org/fabfuel/circuitbreaker.svg?branch=master\n :target: https://travis-ci.org/fabfuel/circuitbreaker\n\n.. image:: https://scrutinizer-ci.com/g/fabfuel/circuitbreaker/badges/coverage.png?b=master\n :target: https://scrutinizer-ci.com/g/fabfuel/circuitbreaker\n\n.. image:: https://scrutinizer-ci.com/g/fabfuel/circuitbreaker/badges/quality-score.png?b=master\n :target: https://scrutinizer-ci.com/g/fabfuel/circuitbreaker\n\nThis is a Python implementation of the \"Circuit Breaker\" Pattern (http://martinfowler.com/bliki/CircuitBreaker.html).\nInspired by Michael T. Nygard's highly recommendable book *Release It!* (https://pragprog.com/book/mnee/release-it).\n\n\nInstallation\n------------\n\nThe project is available on PyPI. Simply run::\n\n $ pip install circuitbreaker\n\n\nUsage\n-----\n\nThis is the simplest example. Just decorate a function with the ``@circuit`` decorator::\n\n from circuitbreaker import circuit\n \n @circuit\n def external_call():\n ...\n\n\nThis decorator sets up a circuit breaker with the default settings. The circuit breaker:\n\n- monitors the function execution and counts failures\n- resets the failure count after every successful execution (while it is closed)\n- opens and prevents further executions after 5 subsequent failures\n- switches to half-open and allows one test-execution after 30 seconds recovery timeout\n- closes if the test-execution succeeded\n- considers all raised exceptions (based on class ``Exception``) as an expected failure\n- is named \"external_call\" - the name of the function it decorates\n\n\nWhat does *failure* mean?\n=========================\nA *failure* is a raised exception, which was not caught during the function call.\nBy default, the circuit breaker listens for all exceptions based on the class ``Exception``. \nThat means, that all exceptions raised during the function call are considered as an \n\"expected failure\" and will increase the failure count.\n\nGet specific about the expected failure\n=======================================\nIt is important, to be **as specific as possible**, when defining the expected exception. \nThe main purpose of a circuit breaker is to protect your distributed system from a cascading failure.\nThat means, you probably want to open the circuit breaker only, if the integration point on the other\nend is unavailable. So e.g. if there is an ``ConnectionError`` or a request ``Timeout``.\n\nIf you are e.g. using the requests library (http://docs.python-requests.org/) for making HTTP calls, \nits ``RequestException`` class would be a great choice for the ``expected_exception`` parameter.\n\nAll recognized exceptions will be re-raised anyway, but the goal is, to let the circuit breaker only\nrecognize those exceptions which are related to the communication to your integration point.\n\nWhen it comes to monitoring (see Monitoring_), it may lead to falsy conclusions, if a\ncircuit breaker opened, due to a local ``OSError`` or ``KeyError``, etc.\n\n\nConfiguration\n-------------\nThe following configuration options can be adjusted via decorator parameters. For example::\n\n from circuitbreaker import circuit\n \n @circuit(failure_threshold=10, expected_exception=ConnectionError)\n def external_call():\n ...\n\n\n\nfailure threshold\n=================\nBy default, the circuit breaker opens after 5 subsequent failures. You can adjust this value with the ``failure_threshold`` parameter.\n\nrecovery timeout\n================\nBy default, the circuit breaker stays open for 30 seconds to allow the integration point to recover.\nYou can adjust this value with the ``recovery_timeout`` parameter.\n\nexpected exception\n==================\nBy default, the circuit breaker listens for all exceptions which are based on the ``Exception`` class.\nYou can adjust this with the ``expected_exception`` parameter. It can be either an exception class or a tuple of exception classes.\n\nname\n====\nBy default, the circuit breaker name is the name of the function it decorates. You can adjust the name with parameter ``name``.\n\n\nAdvanced Usage\n--------------\nIf you apply circuit breakers to a couple of functions and you always set specific options other than the default values,\nyou can extend the ``CircuitBreaker`` class and create your own circuit breaker subclass instead::\n\n from circuitbreaker import CircuitBreaker\n \n class MyCircuitBreaker(CircuitBreaker):\n FAILURE_THRESHOLD = 10\n RECOVERY_TIMEOUT = 60\n EXPECTED_EXCEPTION = RequestException\n \n \nNow you have two options to apply your circuit breaker to a function. As an Object directly::\n\n @MyCircuitBreaker()\n def external_call():\n ...\n\nPlease note, that the circuit breaker class has to be initialized, you have to use a class instance as decorator (``@MyCircuitBreaker()``), not the class itself (``@MyCircuitBreaker``).\n \nOr via the decorator proxy::\n\n @circuit(cls=MyCircuitBreaker)\n def external_call():\n ...\n\n\n.. _Monitoring:\n\nMonitoring\n----------\nTo keep track of the health of your application and the state of your circuit breakers, every circuit breaker registers itself at the ``CircuitBreakerMonitor``. You can receive all registered circuit breakers via ``CircuitBreakerMonitor.get_circuits()``.\n\nTo get an aggregated health status, you can ask the Monitor via ``CircuitBreakerMonitor.all_closed()``. Or you can retrieve the currently open circuits via ``CircuitBreakerMonitor.get_open()`` and the closed circuits via ``CircuitBreakerMonitor.get_closed()``.\n\n\nTodo\n----\n- add unit tests", "description_content_type": "", "docs_url": null, "download_url": "https://github.com/fabfuel/circuitbreaker/archive/1.2.0.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/fabfuel/circuitbreaker", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "circuitbreaker", "package_url": "https://pypi.org/project/circuitbreaker/", "platform": "any", "project_url": "https://pypi.org/project/circuitbreaker/", "project_urls": { "Download": "https://github.com/fabfuel/circuitbreaker/archive/1.2.0.tar.gz", "Homepage": "https://github.com/fabfuel/circuitbreaker" }, "release_url": "https://pypi.org/project/circuitbreaker/1.2.0/", "requires_dist": null, "requires_python": "", "summary": "Python Circuit Breaker pattern implementation", "version": "1.2.0" }, "last_serial": 5466914, "releases": { "1.0.1": [ { "comment_text": "", "digests": { "md5": "d3aba09f9ee499d88fe08503cde3b506", "sha256": "0f3bf83fb4f6b4cb8c08f08d044927b3f18cca3fb8d4d854f534dcfd68df3708" }, "downloads": -1, "filename": "circuitbreaker-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "d3aba09f9ee499d88fe08503cde3b506", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7574, "upload_time": "2016-10-30T06:48:58", "url": "https://files.pythonhosted.org/packages/d8/13/0c70b458eaf8a1d3f280a77eb652ca3f84dd9430212af338d9c3e831f801/circuitbreaker-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "01324830d0c57795a470142e7c41d9c5", "sha256": "9748e94006882cbba945e81a5be66358b3b711c0512ee6ca7279fbafb1e45875" }, "downloads": -1, "filename": "circuitbreaker-1.0.1.tar.gz", "has_sig": false, "md5_digest": "01324830d0c57795a470142e7c41d9c5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5630, "upload_time": "2016-10-30T06:49:00", "url": "https://files.pythonhosted.org/packages/00/af/93e16602af0d7993048db4684ef7a277d3b29d8c4e984b3d2babb5addb5c/circuitbreaker-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "fdb1a7a8547698e46fa4d8e3830f5b37", "sha256": "7573b5fb4fca2305de2220f1b120efdf2119c42a90f4e225c02807305d0a902f" }, "downloads": -1, "filename": "circuitbreaker-1.0.2.tar.gz", "has_sig": false, "md5_digest": "fdb1a7a8547698e46fa4d8e3830f5b37", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5640, "upload_time": "2018-02-24T07:21:53", "url": "https://files.pythonhosted.org/packages/2b/53/c93dc34b981c5163db12bdda5504302acf72fad1ba06afaa5e8b1fef65f5/circuitbreaker-1.0.2.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "f82babcc107651739b333a3eb8b17062", "sha256": "3c53b76e88e5b73eeb2ff75890ad3e5b8b09c7d38b9d258b7f54224593f3615c" }, "downloads": -1, "filename": "circuitbreaker-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f82babcc107651739b333a3eb8b17062", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7753, "upload_time": "2018-07-07T06:26:04", "url": "https://files.pythonhosted.org/packages/19/e8/ff32d477af3f5fd42d9538816458bada9d89804c2069c89da83d858c0768/circuitbreaker-1.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b0a150dc5ab27287820726c5835a6efc", "sha256": "04d8182c127f53ae9811fb57944cd2e13e0f48cb969211eaa5ba5f36c91ec8d3" }, "downloads": -1, "filename": "circuitbreaker-1.1.0.tar.gz", "has_sig": false, "md5_digest": "b0a150dc5ab27287820726c5835a6efc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5864, "upload_time": "2018-07-07T06:26:05", "url": "https://files.pythonhosted.org/packages/15/a2/f88fc7e2406f0cdcbb322159ea1fd0e48e0b8724fd2722a3e7cc2178c4e6/circuitbreaker-1.1.0.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "f82d26ac8e864d81e6d70d2713db5271", "sha256": "477defb0c9fef68f8e943a24b829570d63605d0441cf37934e342a6c131a4750" }, "downloads": -1, "filename": "circuitbreaker-1.2.0.tar.gz", "has_sig": false, "md5_digest": "f82d26ac8e864d81e6d70d2713db5271", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5916, "upload_time": "2019-06-30T04:03:38", "url": "https://files.pythonhosted.org/packages/c1/00/28ac871522b1af3c12d14567f66646a8e6587440ef8896acd84cbd59082b/circuitbreaker-1.2.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f82d26ac8e864d81e6d70d2713db5271", "sha256": "477defb0c9fef68f8e943a24b829570d63605d0441cf37934e342a6c131a4750" }, "downloads": -1, "filename": "circuitbreaker-1.2.0.tar.gz", "has_sig": false, "md5_digest": "f82d26ac8e864d81e6d70d2713db5271", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5916, "upload_time": "2019-06-30T04:03:38", "url": "https://files.pythonhosted.org/packages/c1/00/28ac871522b1af3c12d14567f66646a8e6587440ef8896acd84cbd59082b/circuitbreaker-1.2.0.tar.gz" } ] }