Metadata-Version: 2.1
Name: redis-lock-py
Version: 0.3.0
Summary: Redis distributed lock implementation for Python based on Pub/Sub messaging
Project-URL: Homepage, https://github.com/miintto/redis-lock-py
Author-email: Minjae Park <miintto.log@gmail.com>
License-Expression: MIT
License-File: LICENCE
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Requires-Python: >=3.7
Requires-Dist: redis>=4.2.0
Provides-Extra: test
Requires-Dist: coverage==7.1.0; extra == 'test'
Requires-Dist: pytest-asyncio==0.20.3; extra == 'test'
Requires-Dist: pytest==7.2.1; extra == 'test'
Description-Content-Type: text/markdown

[![License](https://img.shields.io/badge/license-MIT-lightgray.svg)](./LICENSE)
[![PyPI Release](https://img.shields.io/pypi/v/redis-lock-py)](https://pypi.org/project/redis-lock-py/)
![Python Support](https://img.shields.io/pypi/pyversions/redis-lock-py)
![Implementation](https://img.shields.io/pypi/implementation/redis-lock-py.svg)
[![codecov](https://codecov.io/gh/miintto/redis-lock-py/branch/master/graph/badge.svg?token=I9A9JKIWKF)](https://codecov.io/gh/miintto/redis-lock-py)

# Redis Lock with PubSub

Redis distributed lock implementation for Python based on Pub/Sub messaging.

## 1. Features

- Ensure atomicity by using SETNX operation
- Pub/Sub messaging system between the client waiting to get the lock and holding the lock
- Force timeout to avoid infinite loops when trying to acquire lock
- Async is supported

## 2. Installation

```bash
$> pip install redis-lock-py
```

### Dependencies
- Python >= 3.7
- redis-py >= 4.2.0

## 3. Usage

### 3.1 Basic Example

```python
import redis
from redis_lock import RedisLock

client = redis.Redis(host="127.0.0.1", port=6379)

name = "foo"
lock = RedisLock(client, name)
if not lock.acquire():
    raise Exception("Fail to acquire lock")
print("Acquired lock successfully!")
lock.release()
```

[redis-py](https://github.com/redis/redis-py) library is required for redis connection objects.
The `RedisLock.release` method must be invoked to release the lock after acquiring a lock successfully by calling `RedisLock.acquire` method with returned `True`.

### 3.2 Using Context Managers

```python
import redis
from redis_lock import RedisLock

client = redis.Redis(host="127.0.0.1", port=6379)

with RedisLock(client, "foo", blocking_timeout=10):
    print("Acquired lock successfully!")
```

If the part that releases the lock is missing after acquire a lock, 
all the clients that access the same `name` may not be able to acquire the lock.
To prevent this unexpected malfunction from happening, programmed to unlock the lock by itself at the end of the `with` context.
Both examples in **3.1** and **3.2** work the same way.

### 3.3 Using Spin Lock

```python
import redis
from redis_lock import RedisSpinLock

client = redis.Redis(host="127.0.0.1", port=6379)

lock = RedisSpinLock(client, "foo")
if not lock.acquire(blocking=True, sleep_time=0.1):
    raise Exception("Fail to acquire lock")
print("Acquired lock successfully!")
lock.release()
```

Spin lock is also available,
but not recommended unless there is a compelling reason to use them because of inefficiency compare to the Pub/Sub messaging system.

### System Flow

![redis-lock-flow](https://user-images.githubusercontent.com/37063580/215324117-ff55fc4e-cc14-42c1-8628-e472adf8b865.png)

