{"id":19277838,"url":"https://github.com/seankerr/py-postgresql-lock","last_synced_at":"2025-07-04T09:36:02.857Z","repository":{"id":170836417,"uuid":"647051246","full_name":"seankerr/py-postgresql-lock","owner":"seankerr","description":"Lock mechanism implemented with PostgreSQL advisory locks.","archived":false,"fork":false,"pushed_at":"2025-06-11T02:53:29.000Z","size":76,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-11T04:00:48.944Z","etag":null,"topics":["distributed-lock","lock","postgres","postgresql","python"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/postgresql-lock/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seankerr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-05-30T00:46:27.000Z","updated_at":"2025-06-11T02:53:33.000Z","dependencies_parsed_at":"2023-07-10T07:45:41.405Z","dependency_job_id":"2b747013-643d-4ce6-9316-25bfe21fc17f","html_url":"https://github.com/seankerr/py-postgresql-lock","commit_stats":null,"previous_names":["seankerr/py-postgres-lock","seankerr/py-postgresql-lock"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/seankerr/py-postgresql-lock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seankerr%2Fpy-postgresql-lock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seankerr%2Fpy-postgresql-lock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seankerr%2Fpy-postgresql-lock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seankerr%2Fpy-postgresql-lock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seankerr","download_url":"https://codeload.github.com/seankerr/py-postgresql-lock/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seankerr%2Fpy-postgresql-lock/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263483950,"owners_count":23473670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed-lock","lock","postgres","postgresql","python"],"created_at":"2024-11-09T21:07:03.482Z","updated_at":"2025-07-04T09:36:02.849Z","avatar_url":"https://github.com/seankerr.png","language":"Python","readme":"## postgresql-lock\n\nLock mechanism implemented with PostgreSQL advisory locks.\n\nEasily implement distributed database locking.\n\n### Install\n\n```sh\npip install postgresql-lock\n```\n\n### Supported database interfaces\n\n-   **asyncpg**\n    -   asynchronous\n-   **psycopg2**\n    -   synchronous\n-   **psycopg3**\n    -   asynchronous\n    -   synchronous\n-   **sqlalchemy** (supports version 1 \u0026 2; can use any underlying database interface)\n    -   asynchronous\n    -   synchronous\n\n### Why would I use this?\n\n-   PostgreSQL table locks aren't sufficient for your use-case\n-   PostgreSQL row locks don't work on `INSERT`\n-   You want to prevent race conditions between `INSERT` and `UPDATE` on the same primary key\n-   None of the aforementioned details fit your use-case, but you have PostgreSQL installed and need to prevent race conditions in a distributed system\n\n### Default operation\n\nBy default `postgresql-lock` will use `session` lock scope in `blocking` mode with\n`rollback_on_error` enabled. The `session` lock scope means only a single database connection can\nacquire the lock at a time.\n\n### Usage\n\nAll work revolves around the `Lock` class.\n\nThe easiest way to use `Lock` is with `with` or `async with` statements. The lock will be\nreleased automatically. If `rollback_on_error` is enabled (default), rollbacks are automatically\nhandled prior to release.\n\n_Using `with` and `async with` implies blocking mode._\n\n```python\nfrom postgresql_lock import Lock\n\n# setup connection\nconn = ...\n\n# create and use lock\nwith Lock(conn, \"shared-identifier\"):\n    print(\"Acquired lock!\")\n\n    # do something here\n```\n\nNow compare the above example to the equivalent try/finally example below:\n\n```python\nfrom postgresql_lock import Lock\n\n# setup connection\nconn = ...\n\n# create lock\nlock = Lock(conn, \"shared-identifier\")\n\ntry:\n    # acquire lock\n    lock.acquire()\n\n    print(\"Acquired lock!\")\n\n    try:\n        # do something here\n        pass\n\n    except Exception as exc:\n        # handle_error() will rollback the transaction by default\n        lock.handle_error(exc)\n\n        raise exc\nfinally:\n    # release lock (this is safe to run even if the lock has not been acquired)\n    lock.release()\n```\n\n### Asynchronous usage (without `async with`)\n\n```python\nfrom postgresql_lock import Lock\n\n# setup connection\nconn = ...\n\n# create lock\nlock = Lock(conn, \"shared-identifier\")\n\ntry:\n    # acquire lock\n    await lock.acquire_async()\n\n    print(\"Acquired lock!\")\n\n    try:\n        # do something here\n        pass\n\n    except Exception as exc:\n        # handle_error_async() will rollback the transaction by default\n        await lock.handle_error_async(exc)\n\n        raise exc\nfinally:\n    # release lock (this is safe to run even if the lock has not been acquired)\n    await lock.release_async()\n```\n\n### Non-blocking mode (supports async as well)\n\n```python\nfrom postgresql_lock import Lock\n\n# setup connection\nconn = ...\n\n# create lock\nlock = Lock(conn, \"shared-identifier\")\n\n# acquire lock\nif lock.acquire(block=False):\n    # do something here\n    pass\n\nelse:\n    # could not acquire lock\n    pass\n\n# release lock (this is safe to run even if the lock has not been acquired)\nlock.release()\n```\n\n### Specify the database interface manually\n\n```python\nfrom postgresql_lock import Lock\n\n# setup connection\nconn = ...\n\n# create and use lock\nlock = Lock(conn, \"shared-identifier\", interface=\"asyncpg\")\n\n# do things with the lock\n```\n\n### Handle rollbacks manually\n\n```python\nfrom postgresql_lock import Lock\n\n# setup connection\nconn = ...\n\n# create and use lock\nlock = Lock(conn, \"shared-identifier\", rollback_on_error=False)\n\n# do things with the lock\n```\n\n### Changelog\n\n-   **0.2.1**\n    -   Moved public Lock fields to properties\n-   **0.1.9**\n    -   Fix: release_async() bug for sqlalchemy connections\n-   **0.1.8**\n    -   Add logger() function\n    -   Use \"postgresql_lock\" logger name\n-   **0.1.7**\n    -   Add logging statements\n-   **0.1.6**\n    -   Use int.from_bytes() to convert lock key into integer\n    -   Fix: psycopg3 close() not being awaited bug\n-   **0.1.5**\n    -   Rename package from postgres-lock to postgresql-lock\n-   **0.1.4**\n    -   Add py.typed for mypy\n-   **0.1.3**\n    -   Key can be any object\n-   **0.1.2**\n    -   Add Lock.rollback_on_error (default true)\n    -   Add Lock.handle_error() \u0026 Lock.handle_error_async()\n-   **0.1.1**\n    -   Key can be str or int\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseankerr%2Fpy-postgresql-lock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseankerr%2Fpy-postgresql-lock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseankerr%2Fpy-postgresql-lock/lists"}