Metadata-Version: 1.1
Name: python-redis-lock
Version: 2.2.0
Summary: Lock context manager implemented via redis SETNX/BLPOP.
Home-page: https://github.com/ionelmc/python-redis-lock
Author: Ionel Cristian Maries
Author-email: contact@ionelmc.ro
License: BSD
Description: ===============================
        redis-lock
        ===============================
        
        | |docs| |travis| |coveralls| |landscape| |scrutinizer|
        | |version| |downloads| |wheel| |supported-versions| |supported-implementations|
        
        .. |docs| image:: https://readthedocs.org/projects/python-redis-lock/badge/?style=flat
            :target: https://readthedocs.org/projects/python-redis-lock
            :alt: Documentation Status
        
        .. |travis| image:: http://img.shields.io/travis/ionelmc/python-redis-lock/master.png?style=flat
            :alt: Travis-CI Build Status
            :target: https://travis-ci.org/ionelmc/python-redis-lock
        
        .. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/ionelmc/python-redis-lock?branch=master
            :alt: AppVeyor Build Status
            :target: https://ci.appveyor.com/project/ionelmc/python-redis-lock
        
        .. |coveralls| image:: http://img.shields.io/coveralls/ionelmc/python-redis-lock/master.png?style=flat
            :alt: Coverage Status
            :target: https://coveralls.io/r/ionelmc/python-redis-lock
        
        .. |landscape| image:: https://landscape.io/github/ionelmc/python-redis-lock/master/landscape.svg?style=flat
            :target: https://landscape.io/github/ionelmc/python-redis-lock/master
            :alt: Code Quality Status
        
        .. |version| image:: http://img.shields.io/pypi/v/python-redis-lock.png?style=flat
            :alt: PyPI Package latest release
            :target: https://pypi.python.org/pypi/python-redis-lock
        
        .. |downloads| image:: http://img.shields.io/pypi/dm/python-redis-lock.png?style=flat
            :alt: PyPI Package monthly downloads
            :target: https://pypi.python.org/pypi/python-redis-lock
        
        .. |wheel| image:: https://pypip.in/wheel/python-redis-lock/badge.png?style=flat
            :alt: PyPI Wheel
            :target: https://pypi.python.org/pypi/python-redis-lock
        
        .. |supported-versions| image:: https://pypip.in/py_versions/python-redis-lock/badge.png?style=flat
            :alt: Supported versions
            :target: https://pypi.python.org/pypi/python-redis-lock
        
        .. |supported-implementations| image:: https://pypip.in/implementation/python-redis-lock/badge.png?style=flat
            :alt: Supported imlementations
            :target: https://pypi.python.org/pypi/python-redis-lock
        
        .. |scrutinizer| image:: https://img.shields.io/scrutinizer/g/ionelmc/python-redis-lock/master.png?style=flat
            :alt: Scrtinizer Status
            :target: https://scrutinizer-ci.com/g/ionelmc/python-redis-lock/
        
        Lock context manager implemented via redis SETNX/BLPOP.
        
        * Free software: BSD license
        
        Interface targeted to be exactly like `threading.Lock <http://docs.python.org/2/library/threading.html#threading.Lock>`_.
        
        Usage
        =====
        
        Because we don't want to require users to share the lock instance across processes you will have to give them names.
        Eg::
        
            conn = StrictRedis()
            with redis_lock.Lock(conn, "name-of-the-lock"):
                print("Got the lock. Doing some work ...")
                time.sleep(5)
        
        Eg::
        
            lock = redis_lock.Lock(conn, "name-of-the-lock")
            if lock.acquire(blocking=False):
                print("Got the lock.")
            else:
                print("Someone else has the lock.")
        
        
        You can also associate an identifier along with the lock so that it can be retrieved later by the same process, or by a
        different one. This is useful in cases where the application needs to identify the lock owner (find out who currently
        owns the lock). Eg::
        
            import socket
            host_id = "owned-by-%s" % socket.gethostname()
            lock = redis_lock.Lock(conn, "name-of-the-lock", id=host_id)
            if lock.acquire(blocking=False):
                print("Got the lock.")
            else:
                if lock.get_owner_id() == host_id:
                    print("I already acquired this in another process.")
                else:
                    print("The lock is held on another machine.")
        
        
        Avoid dogpile effect in django
        ------------------------------
        
        The dogpile is also known as the thundering herd effect or cache stampede. Here's a pattern to avoid the problem
        without serving stale data. The work will be performed a single time and every client will wait for the fresh data.
        
        To use this you will need `django-redis <https://github.com/niwibe/django-redis>`_, however, ``python-redis-lock``
        provides you a cache backend that has a cache method for your convenience. Just install ``python-redis-lock`` like
        this::
        
            pip install "python-redis-lock[django]"
        
        Now put something like this in your settings::
        
            CACHES = {
                'default': {
                    'BACKEND': 'redis_lock.django_cache.RedisCache',
                    'LOCATION': '127.0.0.1:6379',
                    'OPTIONS': {
                        'DB': 1
                    }
                }
            }
        
        This backend just adds a convenient ``.lock(name, expire=None)`` function to django-redis's cache backend.
        
        You would write your functions like this::
        
            from django.core.cache import cache
        
            def function():
                val = cache.get(key)
                if val:
                    return val
                else:
                    with cache.lock(key):
                        val = cache.get(key)
                        if val:
                            return val
                        else:
                            # DO EXPENSIVE WORK
                            val = ...
        
                            cache.set(key, value)
                            return val
        
        
        Troubleshooting
        ---------------
        
        In some cases, the lock remains in redis forever (like a server blackout / redis or application crash / an unhandled
        exception). In such cases, the lock is not removed by restarting the application. One solution is to turn on the
        `auto_renewal` parameter in combination with `expire` to set a time-out on the lock, but let `Lock()` automatically
        keep resetting the expire time while your application code is executing::
        
            # Get a lock with a 60-second lifetime but keep renewing it automatically
            # to ensure the lock is held for as long as the Python process is running.
            with redis_lock.Lock('my-lock', expire=60, auto_renewal=True):
                # Do work....
        
        Another solution is to use the ``reset_all()`` function when the application starts::
        
            # On application start/restart
            import redis_lock
            redis_lock.reset_all()
        
        Alternativelly, you can reset individual locks via the ``reset`` method.
        
        Use these carefully, if you understand what you do.
        
        
        Features
        ========
        
        * based on the standard SETNX recipe
        * optional expiry
        * optional lock renewal (use a low expire but keep the lock active)
        * no spinloops at acquire
        
        Implementation
        ==============
        
        ``redis_lock`` will use 2 keys for each lock named ``<name>``:
        
        * ``lock:<name>`` - a string value for the actual lock
        * ``lock-signal:<name>`` - a list value for signaling the waiters when the lock is released
        
        This is how it works:
        
        .. image:: https://raw.github.com/ionelmc/python-redis-lock/master/docs/redis-lock%20diagram.png
            :alt: python-redis-lock flow diagram
        
        Documentation
        =============
        
        https://python-redis-lock.readthedocs.org/
        
        Development
        ===========
        
        To run the all tests run::
        
            tox
        
        Requirements
        ============
        
        :OS: Any
        :Runtime: Python 2.6, 2.7, 3.2, 3.3 or PyPy
        :Services: Redis 2.6.12 or later.
        
        Similar projects
        ================
        
        * `bbangert/retools <https://github.com/bbangert/retools/blob/master/retools/lock.py>`_ - acquire does spinloop
        * `distributing-locking-python-and-redis <https://chris-lamb.co.uk/posts/distributing-locking-python-and-redis>`_ - acquire does polling
        * `cezarsa/redis_lock <https://github.com/cezarsa/redis_lock/blob/master/redis_lock/__init__.py>`_ - acquire does not block
        * `andymccurdy/redis-py <https://github.com/andymccurdy/redis-py/blob/master/redis/client.py#L2167>`_ - acquire does spinloop
        * `mpessas/python-redis-lock <https://github.com/mpessas/python-redis-lock/blob/master/redislock/lock.py>`_ - blocks fine but no expiration
        
        
        Changelog
        =========
        
        2.2.0 (2015-08-19)
        ------------------
        
        * Added the ``auto_renewal`` option. Contributed by Nick Groenen in `#18 <https://github.com/ionelmc/python-redis-lock/pull/18>`_.
        
        2.1.0 (2015-03-12)
        ------------------
        
        * New specific exception classes: ``AlreadyAcquired`` and ``NotAcquired``.
        * Slightly improved efficiency when non-waiting acquires are used.
        
        2.0.0 (2014-12-29)
        ------------------
        
        * Rename ``Lock.token`` to ``Lock.id``. Now only allowed to be set via constructor. Contributed by Jardel Weyrich in `#11 <https://github.com/ionelmc/python-redis-lock/pull/11>`_.
        
        1.0.0 (2014-12-23)
        ------------------
        
        * Fix Django integration. (reported by Jardel Weyrich)
        * Reorganize tests to use py.test.
        * Add test for Django integration.
        * Add ``reset_all`` functionality. Contributed by Yokotoka in `#7 <https://github.com/ionelmc/python-redis-lock/pull/7>`_.
        * Add ``Lock.reset`` functionality.
        * Expose the ``Lock.token`` attribute.
        
        0.1.2 (2013-11-05)
        ------------------
        
        * ?
        
        0.1.1 (2013-10-26)
        ------------------
        
        * ?
        
        0.1.0 (2013-10-26)
        ------------------
        
        * ?
        
        0.0.1 (2013-10-25)
        ------------------
        
        * First release on PyPI.
        
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: Unix
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Utilities
