{ "info": { "author": "Brian Jay Stanley", "author_email": "brian@brianjaystanley.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "``django-failover`` provides automatic failover for services used by your\nDjango application. For example, if you are running a master and slave\ndatabase, you might configure the slave to failover to the master.\n``django-failover`` will monitor the slave and, if it goes down, will modify\nyour settings to point the slave connection at the master. When the slave\ncomes back online, ``django-failover`` will restore the settings and re-point\nthe slave connection at the slave.\n\nYou can configure ``django-failover`` to perform monitoring, failover, and\nrecovery via a middleware class. You can also specify exception classes (such\nas socket errors) that, when raised and logged using Python's logging module,\nwill trigger monitoring. ``django-failover`` provides a log handler that you\ncan hook up to your logger(s) for this purpose.\n\n``django-failover`` logs when a service goes down and when it comes back up.\nIt also periodically re-logs a service outage if the service remains down.\n\nTechnical Note\n==============\nMonitoring, failover, and recovery occur on a per-process basis. That is,\n``django-failover`` does not store information about which services are down,\nwhich are up, and when they were last monitored in any global location such\nas a database or cache. Rather, each process running your Django application\ndiscovers outages for itself. Ping frequency settings (described below) only\napply to a given process; your service may be pinged more often than your\nsettings stipulate if multiple processes are running your Django application.\nThis design is intended to keep ``django-failover`` lightweight and to\nprevent minor network hiccups from triggering failover globally across\nlarge-scale applications.\n\n``django-failover`` is best suited for environments where your webserver is\nserving multiple requests per process. A service outage will trigger failover\nwithin the process, the process will continue serving requests while in\nfailover, and then will resume serving requests normally once the service\ncomes back up. If you are working in a development environment where your\nwebserver is reloading your code for each request (using a setting such as\n``MaxRequestsPerChild`` in Apache), you should configure your webserver not\nto reload code while experimenting with ``django-failover``. Otherwise,\n``django-failover`` will start each request assuming all services are\noperational.\n\nRequirements \n============ \n``django-failover`` has been tested with Django 1.3 and Python 2.6.\n\nInstallation\n============\nYou can install ``django-failover`` with ::\n\n pip install django-failover\n\nor ::\n\n easy_install django-failover\n\nThis will add ``failover`` to your Python path. Add ``'failover'`` to your\n``INSTALLED_APPS`` if you want to run ``django-failover``'s test suite.\n\nService classes\n===============\nTo use ``django-failover``, you define and register service classes, each\nclass corresponding to a service used by your Django application, such as a\ndatabase, a cache, a message broker, etc. Each service class should inherit\nfrom ``failover.services.Service`` and override it as necessary. The base\n``Service`` class provides the following attributes, methods, and default\nbehavior:\n\n``Service.ping()``\n This method pings the service to see if it is available. Must raise an\n exception if the service is down, otherwise the service is assumed to be\n up. Default behavior: attempts to make a socket connection using\n ``Service.SOCKET_HOST`` (default None) and ``Service.SOCKET_PORT``\n (default None). Depending on your service class, you should either define\n values for ``SOCKET_HOST`` and ``SOCKET_PORT``, or override the ``ping``\n method entirely to check the service in some other way.\n\n``Service.failover()`` \n This method performs failover if the service is down. Default behavior:\n modifies ``django.conf.settings``, setting name=value for each name/value\n pair in ``Service.FAILOVER_SETTINGS`` (which is an empty dictionary by\n default).\n\n``Service.recover()`` \n This method performs recovery when a service comes back up. Default\n behavior: restores the settings that were overwritten during failover.\n\n``Service.MONITORING_PING_FREQUENCY`` \n Determines the maximum frequency (in seconds) with which\n ``django-failover`` will ping the service during normal monitoring.\n This means that, when monitoring is triggered, ``django-failover`` will not\n ping the service unless at least ``MONITORING_PING_FREQUENCY`` seconds\n have passed since the last ping. Default:\n ``settings.FAILOVER_MONITORING_PING_FREQUENCY`` (or ``120`` if\n undefined).\n\n``Service.OUTAGE_PING_FREQUENCY`` \n Like ``MONITORING_PING_FREQUENCY``, but applies when the service is down\n and is being monitored for recovery. Default:\n ``settings.FAILOVER_OUTAGE_PING_FREQUENCY`` (or ``30`` if undefined).\n \n``Service.ERROR_PING_FREQUENCY`` \n Like ``MONITORING_PING_FREQUENCY``, but applies when monitoring is\n triggered by an exception. Default:\n ``settings.FAILOVER_ERROR_PING_FREQUENCY`` (or ``5`` if undefined).\n \n``Service.outage_middleware_class``\n You can assign a middleware class to this attribute and that middleware\n will run when the service goes down (assuming you're using\n ``django-failover``'s middleware). The middleware may define\n ``process_request`` and/or ``process_view`` methods. This could be useful\n if you wanted to close down some sections of your site during the outage.\n Default: ``None``.\n\n``django-failover`` provides a few ready-to-use service classes.\n\n``failover.services.cache.Memcached``\n This service class will ping your Memcached node(s) and let you know if\n any are down. Requires ``python-memcached`` client. Doesn't perform any\n failover, as the cache fails silently and thus automatically fails over\n to the database. This service class is useful for notifying you of\n Memcached outages.\n\n``failover.services.celery.Celery``\n Can be used with ``django-celery``. Pings your message broker (using\n ``settings.BROKER_HOST`` and ``settings.BROKER_PORT``). If the message\n broker is down, sets ``CELERY_ALWAYS_EAGER`` to ``True``, meaning your\n celery tasks will execute locally during the outage.\n \n``failover.services.db.Database``\n Fails over from one of your database connections in\n ``settings.DATABASES`` to another. By default, fails over from a\n connection with alias ``\"slave\"`` to a connection with alias\n ``\"default\"``. To failover using different db aliases, subclass\n ``Database`` and define ``DB_ALIAS`` and ``FAILOVER_DB_ALIAS`` on the\n subclass.\n \n``failover.services.db.MySQL``\n A subclass of ``Database`` that sets sensible timeouts when pinging in\n order to reduce false positives and avoid hanging. Database connection\n timeout settings are backend-specific; if you use a backend other than\n MySQL and want to set timeouts, subclass ``Database`` and override the\n ``set_timeout`` method.\n\nRegistering service classes\n===========================\nYou can register a service class in several ways. The easiest way is to\ndefine ``FAILOVER_SERVICES`` in your settings file. ``FAILOVER_SERVICES``\nshould be a tuple of service classes in dot notation::\n\n FAILOVER_SERVICES = (\n \"failover.services.cache.Memcached\",\n \"failover.services.celery.Celery\",\n \"myproject.myapp.MyServiceClass\",\n )\n\nAlternatively, import ``failover.monitor.ServiceMonitor`` and call::\n\n ServiceMonitor.register(MyServiceClass)\n\nfor each service class you want to register. You can also use this as a\ndecorator::\n\n @ServiceMonitor.register\n class MyServiceClass(Service):\n\nMiddleware configuration\n========================\nAdd ``failover.middleware.FailoverMiddleware`` to your\n``MIDDLEWARE_CLASSES``, at or near the beginning::\n\n MIDDLEWARE_CLASSES = (\n \"failover.middleware.FailoverMiddleware\",\n \"django.middleware.common.CommonMiddleware\",\n ...\n )\n\nThis will trigger monitoring, failover, and recovery before each request\n(taking into account your ping frequency settings).\n\nLogging configuration\n=====================\nTo trigger monitoring when certain exception classes are raised, add\n``failover.log.FailoverHandler`` to one of your loggers. To capture\n``django-failover``'s own logging, add a handler to the ``\"failover\"``\nlogger. Service outages are logged as ``CRITICAL`` and recoveries are logged\nas ``INFO``, so you probably want to set your logger and handler levels to\n``INFO`` so you will know when services recover. ::\n\n LOGGING = {\n 'version': 1,\n 'handlers': {\n 'mail_admins': {\n 'level': 'INFO',\n 'class': 'django.utils.log.AdminEmailHandler',\n },\n 'failover': {\n 'level': 'ERROR',\n 'class': 'failover.log.FailoverHandler',\n },\n 'loggers': {\n 'django.request': {\n 'handlers': ['mail_admins', 'failover'],\n 'level': 'ERROR',\n },\n 'failover': {\n 'handlers': ['mail_admins'],\n 'level': 'INFO',\n },\n },\n }\n\nBy default, ``FailoverHandler`` will trigger monitoring for the following\nexception classes::\n \n socket.error\n django.db.DatabaseError\n urllib2.URLError\n \nTo add to this list, define ``FAILOVER_OUTAGE_EXTRA_EXCEPTION_CLASSES`` in\nsettings. To override the list, define ``FAILOVER_OUTAGE_EXCEPTION_CLASSES``. \n\nMonitoring decorators\n=====================\nYou can also trigger monitoring using several decorators ``django-failover``\nprovides. Decorating a function with ``failover.decorators.monitor`` will\ntrigger monitoring prior to the function being called. Wrapping the function\nwith ``failover.decorators.recover_from_outages`` will monitor services that\nare currently down, but won't monitor services that are operating normally.\n``recover_from_outages`` is useful in conjunction with exception-based\nmonitoring, as the latter provides no trigger for checking when a service\nrecovers. If you are only using ``django-failover``'s middleware, you\nprobably don't need either of these decorators.\n\nAdditional Settings\n===================\n``FAILOVER_OUTAGE_LOGGING_FREQUENCY`` \n Controls how often, after a service outage is discovered, the outage will\n be re-logged if the service remains down. Default: ``3600`` seconds (1\n hour).\n\n``FAILOVER_MONITORING_PING_FREQUENCY``\n Controls the ping frequency during normal monitoring on service classes\n that don't define their own value. Default: ``120`` seconds.\n\n``FAILOVER_OUTAGE_PING_FREQUENCY``\n Controls the ping frequency during outages on service classes\n that don't define their own value. Default: ``30`` seconds.\n\n``FAILOVER_ERROR_PING_FREQUENCY``\n Controls the ping frequency for exception-triggered monitoring on\n service classes that don't define their own value. Default: ``5``\n seconds.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/brianjaystanley/django-failover", "keywords": "django failover", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "django-failover", "package_url": "https://pypi.org/project/django-failover/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-failover/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/brianjaystanley/django-failover" }, "release_url": "https://pypi.org/project/django-failover/0.1.1/", "requires_dist": null, "requires_python": null, "summary": "automatic failover for Django", "version": "0.1.1" }, "last_serial": 743188, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "fdb925e487bfe7ff9a3acbb3aa891cdf", "sha256": "4cd768d273a1cc77b55868c5bb6f8768ab71b22dc6520757292357b40b5aa941" }, "downloads": -1, "filename": "django-failover-0.1.0.zip", "has_sig": false, "md5_digest": "fdb925e487bfe7ff9a3acbb3aa891cdf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25167, "upload_time": "2012-07-25T22:24:44", "url": "https://files.pythonhosted.org/packages/f6/f4/02bf32d3fda8235478aeae848cc8a1f8e9824db5e4678588de902122fa00/django-failover-0.1.0.zip" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "0014a1b15c4eb522d20c78ae90e4780a", "sha256": "97f8866ec23a14858cf5ef8c6830f5a4611c88d64e2d0a00fcbf943c7c6de552" }, "downloads": -1, "filename": "django-failover-0.1.1.zip", "has_sig": false, "md5_digest": "0014a1b15c4eb522d20c78ae90e4780a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26100, "upload_time": "2012-08-03T21:51:26", "url": "https://files.pythonhosted.org/packages/dd/0b/29f64da089369c90bd8986bc9c98a09c737fd6dc10b244c57646c8ea80b8/django-failover-0.1.1.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0014a1b15c4eb522d20c78ae90e4780a", "sha256": "97f8866ec23a14858cf5ef8c6830f5a4611c88d64e2d0a00fcbf943c7c6de552" }, "downloads": -1, "filename": "django-failover-0.1.1.zip", "has_sig": false, "md5_digest": "0014a1b15c4eb522d20c78ae90e4780a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26100, "upload_time": "2012-08-03T21:51:26", "url": "https://files.pythonhosted.org/packages/dd/0b/29f64da089369c90bd8986bc9c98a09c737fd6dc10b244c57646c8ea80b8/django-failover-0.1.1.zip" } ] }