Metadata-Version: 1.1
Name: python-redis-lock
Version: 3.2.0
Summary: Lock context manager implemented via redis SETNX/BLPOP.
Home-page: https://github.com/ionelmc/python-redis-lock
Author: Ionel Cristian Mărieș
Author-email: contact@ionelmc.ro
License: BSD
Description: ========
        Overview
        ========
        
        
        
        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': 'redis://127.0.0.1:6379/1',
                    'OPTIONS': {
                        'CLIENT_CLASS': 'django_redis.client.DefaultClient'
                    }
                }
            }
        
        
        .. note::
            
        
            If using a `django-redis` < `3.8.x`, you'll probably need `redis_cache` 
            which has been deprecated in favor to `django_redis`. The `redis_cache` 
            module is removed in `django-redis` versions > `3.9.x`. See `django-redis notes <http://niwinz.github.io/django-redis/latest/#_configure_as_cache_backend>`_.
        
        
        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 timeout
        * 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%20(v3.0).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.7, 3.3 or later, 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
        =========
        
        3.2.0 (2016-10-29)
        ------------------
        
        * Changed the signal key cleanup operation do be done without any expires. This prevents lingering keys around for some time.
          Contributed by Andrew Pashkin in `#38 <https://github.com/ionelmc/python-redis-lock/pull/38>`_.
        * Allow locks with given `id` to acquire. Previously it assumed that if you specify the `id` then the lock was already
          acquired. See `#44 <https://github.com/ionelmc/python-redis-lock/issues/44>`_ and
          `#39 <https://github.com/ionelmc/python-redis-lock/issues/39>`_.
        * Allow using other redis clients with a ``strict=False``. Normally you're expected to pass in an instance
          of ``redis.StrictRedis``.
        * Added convenience method `locked_get_or_set` to Django cache backend.
        
        3.1.0 (2016-04-16)
        ------------------
        
        * Changed the auto renewal to automatically stop the renewal thread if lock gets garbage collected. Contributed by
          Andrew Pashkin in `#33 <https://github.com/ionelmc/python-redis-lock/pull/33>`_.
        
        3.0.0 (2016-01-16)
        ------------------
        
        * Changed ``release`` so that it expires signal-keys immediately. Contributed by Andrew Pashkin in `#28
          <https://github.com/ionelmc/python-redis-lock/pull/28>`_.
        * Resetting locks (``reset`` or ``reset_all``) will release the lock. If there's someone waiting on the reset lock now it will
          acquire it. Contributed by Andrew Pashkin in `#29 <https://github.com/ionelmc/python-redis-lock/pull/29>`_.
        * Added the ``extend`` method on ``Lock`` objects. Contributed by Andrew Pashkin in `#24
          <https://github.com/ionelmc/python-redis-lock/pull/24>`_.
        * Documentation improvements on ``release`` method. Contributed by Andrew Pashkin in `#22
          <https://github.com/ionelmc/python-redis-lock/pull/22>`_.
        * Fixed ``acquire(block=True)`` handling when ``expire`` option was used (it wasn't blocking indefinitely). Contributed by
          Tero Vuotila in `#35 <https://github.com/ionelmc/python-redis-lock/pull/35>`_.
        * Changed ``release`` to check if lock was acquired with he same id. If not, ``NotAcquired`` will be raised.
          Previously there was just a check if it was acquired with the same instance (self._held).
          **BACKWARDS INCOMPATIBLE**
        * Removed the ``force`` option from ``release`` - it wasn't really necessary and it only encourages sloppy programming. See
          `#25 <https://github.com/ionelmc/python-redis-lock/issues/25>`_.
          **BACKWARDS INCOMPATIBLE**
        * Dropped tests for Python 2.6. It may work but it is unsupported.
        
        2.3.0 (2015-09-27)
        ------------------
        
        * Added the ``timeout`` option. Contributed by Victor Torres in `#20 <https://github.com/ionelmc/python-redis-lock/pull/20>`_.
        
        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.
        
Keywords: redis,lock
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.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Utilities
