redishilok


Nameredishilok JSON
Version 1.1.0 PyPI version JSON
download
home_pagehttps://github.com/puzzlefin/redishilok
SummaryRedis-based read-write distributed and hierarchical locking library
upload_time2024-11-26 01:59:26
maintainerNone
docs_urlNone
authorErik Aronesty
requires_python<4.0,>=3.11
licenseMIT
keywords redis locking distributed-locking hierarchical-locking python
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Redis Hierarchical Distributed Read-Write Locking

This is a lightweight implementation of a hierarchical distributed read-write lock using Redis.

It supports concurrent readers and exclusive writers in a tree-like hierarchy, ensuring locks on ancestors affect descendants.

## Features
- Hierarchical locking with customizable path separators (e.g., `/`, `:`).
- Concurrent read locks on the same path or ancestors.
- Exclusive write locks on paths or descendants.
- Timeout and non-blocking lock options.
- Automatic lock refreshing for long-running operations.

## Installation

```bash
pip install redishilok
```

## Usage

```python
import asyncio
from redishilok import RedisHiLok

async def main():
    hilok = RedisHiLok('redis://localhost:6379/0')

    # Acquire a read lock
    async with hilok.read('a/b'):
        print("Read lock acquired on 'a/b'")

        # Acquire a write lock with non-blocking mode
        try:
            async with hilok.write('a', block=False):
                print("Write lock acquired on 'a'")
            print("Never gets here")
        except RuntimeError:
            print("Failed to acquire write lock on 'a'")

asyncio.run(main())
```

## Examples

### Basic Hierarchical Locking

```python
import asyncio
from redishilok import RedisHiLok

async def main():
    hilok = RedisHiLok('redis://localhost:6379/0')

    # Concurrent readers
    async with hilok.read('a'):
        async with hilok.read('a/b/c'):
            print("Both read locks succeed")

    # Write lock blocks descendants
    async with hilok.write('a'):
        try:
            async with hilok.read('a/b/c', timeout=0.1):
                pass
        except RuntimeError:
            print("Failed to acquire read lock on 'a/b/c' due to write lock on 'a'")

asyncio.run(main())
```

### Custom Separator

```python
import asyncio
from redishilok import RedisHiLok

async def main():
    hilok = RedisHiLok('redis://localhost', separator=':')
    async with hilok.write('a:b:c'):
        print("Write lock acquired on 'a:b:c'")

asyncio.run(main())
```

### Long-Running Operations with Refresh

```python
import asyncio
from redishilok import RedisHiLok

async def main():
    hilok = RedisHiLok('redis://localhost', ttl=2000, refresh_interval=1000)
    async with hilok.write('a/b'):
        print("Long operation starts")
        await asyncio.sleep(5)  # Lock is automatically refreshed

asyncio.run(main())
```



### Manually-managed Operations with Handles

```python
import asyncio
from redishilok import RedisHiLok

async def main():
    hilok = RedisHiLok('redis://localhost')
    uuid = await hilok.acquire_write('a/b')
    await asyncio.sleep(1)  # Lock is not automatically refreshed, caller must "restore" the lock

    # refresh by uuid, manually
    manual = RedisHiLok('redis://localhost')
    await manual.acquire_write("a/b", uuid=uuid)

    # refresh automatically
    other = RedisHiLok('redis://localhost', refresh_interval=1000)
    async with other.write('a/b', uuid=uuid):
        # lock is auto-refreshing in the background
        pass

    # free resources
    await hilok.close()
    await manual.close()
    await other.close()

asyncio.run(main())
```

## Limitations
- Requires a running Redis instance.
- Not suitable for high-frequency locking scenarios (due to Redis round-trips).
- Lock fairness is not guaranteed (e.g., no queue for blocked writers).

## License
MIT

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/puzzlefin/redishilok",
    "name": "redishilok",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.11",
    "maintainer_email": null,
    "keywords": "redis, locking, distributed-locking, hierarchical-locking, python",
    "author": "Erik Aronesty",
    "author_email": "erik@q32.com",
    "download_url": "https://files.pythonhosted.org/packages/8a/43/d0545d4b8d2befe773fb85e803bd190bbbc3d92071890dc0c47dfb8778cd/redishilok-1.1.0.tar.gz",
    "platform": null,
    "description": "# Redis Hierarchical Distributed Read-Write Locking\n\nThis is a lightweight implementation of a hierarchical distributed read-write lock using Redis.\n\nIt supports concurrent readers and exclusive writers in a tree-like hierarchy, ensuring locks on ancestors affect descendants.\n\n## Features\n- Hierarchical locking with customizable path separators (e.g., `/`, `:`).\n- Concurrent read locks on the same path or ancestors.\n- Exclusive write locks on paths or descendants.\n- Timeout and non-blocking lock options.\n- Automatic lock refreshing for long-running operations.\n\n## Installation\n\n```bash\npip install redishilok\n```\n\n## Usage\n\n```python\nimport asyncio\nfrom redishilok import RedisHiLok\n\nasync def main():\n    hilok = RedisHiLok('redis://localhost:6379/0')\n\n    # Acquire a read lock\n    async with hilok.read('a/b'):\n        print(\"Read lock acquired on 'a/b'\")\n\n        # Acquire a write lock with non-blocking mode\n        try:\n            async with hilok.write('a', block=False):\n                print(\"Write lock acquired on 'a'\")\n            print(\"Never gets here\")\n        except RuntimeError:\n            print(\"Failed to acquire write lock on 'a'\")\n\nasyncio.run(main())\n```\n\n## Examples\n\n### Basic Hierarchical Locking\n\n```python\nimport asyncio\nfrom redishilok import RedisHiLok\n\nasync def main():\n    hilok = RedisHiLok('redis://localhost:6379/0')\n\n    # Concurrent readers\n    async with hilok.read('a'):\n        async with hilok.read('a/b/c'):\n            print(\"Both read locks succeed\")\n\n    # Write lock blocks descendants\n    async with hilok.write('a'):\n        try:\n            async with hilok.read('a/b/c', timeout=0.1):\n                pass\n        except RuntimeError:\n            print(\"Failed to acquire read lock on 'a/b/c' due to write lock on 'a'\")\n\nasyncio.run(main())\n```\n\n### Custom Separator\n\n```python\nimport asyncio\nfrom redishilok import RedisHiLok\n\nasync def main():\n    hilok = RedisHiLok('redis://localhost', separator=':')\n    async with hilok.write('a:b:c'):\n        print(\"Write lock acquired on 'a:b:c'\")\n\nasyncio.run(main())\n```\n\n### Long-Running Operations with Refresh\n\n```python\nimport asyncio\nfrom redishilok import RedisHiLok\n\nasync def main():\n    hilok = RedisHiLok('redis://localhost', ttl=2000, refresh_interval=1000)\n    async with hilok.write('a/b'):\n        print(\"Long operation starts\")\n        await asyncio.sleep(5)  # Lock is automatically refreshed\n\nasyncio.run(main())\n```\n\n\n\n### Manually-managed Operations with Handles\n\n```python\nimport asyncio\nfrom redishilok import RedisHiLok\n\nasync def main():\n    hilok = RedisHiLok('redis://localhost')\n    uuid = await hilok.acquire_write('a/b')\n    await asyncio.sleep(1)  # Lock is not automatically refreshed, caller must \"restore\" the lock\n\n    # refresh by uuid, manually\n    manual = RedisHiLok('redis://localhost')\n    await manual.acquire_write(\"a/b\", uuid=uuid)\n\n    # refresh automatically\n    other = RedisHiLok('redis://localhost', refresh_interval=1000)\n    async with other.write('a/b', uuid=uuid):\n        # lock is auto-refreshing in the background\n        pass\n\n    # free resources\n    await hilok.close()\n    await manual.close()\n    await other.close()\n\nasyncio.run(main())\n```\n\n## Limitations\n- Requires a running Redis instance.\n- Not suitable for high-frequency locking scenarios (due to Redis round-trips).\n- Lock fairness is not guaranteed (e.g., no queue for blocked writers).\n\n## License\nMIT\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Redis-based read-write distributed and hierarchical locking library",
    "version": "1.1.0",
    "project_urls": {
        "Homepage": "https://github.com/puzzlefin/redishilok",
        "Repository": "https://github.com/puzzlefin/redishilok"
    },
    "split_keywords": [
        "redis",
        " locking",
        " distributed-locking",
        " hierarchical-locking",
        " python"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d1b4e62943ef569f4ded3b7459e313abd738314beec4f73410722cffccedbe02",
                "md5": "98ae5adc5439b8e060d6c9c6561b8260",
                "sha256": "b5c507bbaa18c91f0f8836334052caca397ac48cb5940c0c2cd9ffcf2bb528d7"
            },
            "downloads": -1,
            "filename": "redishilok-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "98ae5adc5439b8e060d6c9c6561b8260",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.11",
            "size": 7879,
            "upload_time": "2024-11-26T01:59:24",
            "upload_time_iso_8601": "2024-11-26T01:59:24.759038Z",
            "url": "https://files.pythonhosted.org/packages/d1/b4/e62943ef569f4ded3b7459e313abd738314beec4f73410722cffccedbe02/redishilok-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8a43d0545d4b8d2befe773fb85e803bd190bbbc3d92071890dc0c47dfb8778cd",
                "md5": "9ae299783678cb976577f8da643d3d78",
                "sha256": "60d761e36e7dff915c066776186109d296fb5d04d2abd38cfa0cd08e54885d8b"
            },
            "downloads": -1,
            "filename": "redishilok-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "9ae299783678cb976577f8da643d3d78",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.11",
            "size": 7454,
            "upload_time": "2024-11-26T01:59:26",
            "upload_time_iso_8601": "2024-11-26T01:59:26.289919Z",
            "url": "https://files.pythonhosted.org/packages/8a/43/d0545d4b8d2befe773fb85e803bd190bbbc3d92071890dc0c47dfb8778cd/redishilok-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-26 01:59:26",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "puzzlefin",
    "github_project": "redishilok",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "circle": true,
    "lcname": "redishilok"
}
        
Elapsed time: 0.57462s