postgresql-lock
Lock mechanism implemented with PostgreSQL advisory locks.
Easily implement distributed database locking.
Install
pip install postgresql-lock
Supported database interfaces
- asyncpg
- asynchronous
- psycopg2
- synchronous
- psycopg3
- asynchronous
- synchronous
- sqlalchemy (supports version 1 & 2; can use any underlying database interface)
- asynchronous
- synchronous
Why would I use this?
- PostgreSQL table locks aren't sufficient for your use-case
- PostgreSQL row locks don't work on
INSERT - You want to prevent race conditions between
INSERTandUPDATEon the same primary key - None of the aforementioned details fit your use-case, but you have PostgreSQL installed and need to prevent race conditions in a distributed system
Default operation
By default postgresql-lock will use session lock scope in blocking mode with
rollback_on_error enabled. The session lock scope means only a single database connection can
acquire the lock at a time.
Usage
All work revolves around the Lock class.
The easiest way to use Lock is with with or async with statements. The lock will be
released automatically. If rollback_on_error is enabled (default), rollbacks are automatically
handled prior to release.
Using with and async with implies blocking mode.
from postgresql_lock import Lock
# setup connection
conn = ...
# create and use lock
with Lock(conn, "shared-identifier"):
print("Acquired lock!")
# do something here
Now compare the above example to the equivalent try/finally example below:
from postgresql_lock import Lock
# setup connection
conn = ...
# create lock
lock = Lock(conn, "shared-identifier")
try:
# acquire lock
lock.acquire()
print("Acquired lock!")
try:
# do something here
pass
except Exception as exc:
# handle_error() will rollback the transaction by default
lock.handle_error(exc)
raise exc
finally:
# release lock (this is safe to run even if the lock has not been acquired)
lock.release()
Asynchronous usage (without async with)
from postgresql_lock import Lock
# setup connection
conn = ...
# create lock
lock = Lock(conn, "shared-identifier")
try:
# acquire lock
await lock.acquire_async()
print("Acquired lock!")
try:
# do something here
pass
except Exception as exc:
# handle_error_async() will rollback the transaction by default
await lock.handle_error_async(exc)
raise exc
finally:
# release lock (this is safe to run even if the lock has not been acquired)
await lock.release_async()
Non-blocking mode (supports async as well)
from postgresql_lock import Lock
# setup connection
conn = ...
# create lock
lock = Lock(conn, "shared-identifier")
# acquire lock
if lock.acquire(block=False):
# do something here
pass
else:
# could not acquire lock
pass
# release lock (this is safe to run even if the lock has not been acquired)
lock.release()
Specify the database interface manually
from postgresql_lock import Lock
# setup connection
conn = ...
# create and use lock
lock = Lock(conn, "shared-identifier", interface="asyncpg")
# do things with the lock
Handle rollbacks manually
from postgresql_lock import Lock
# setup connection
conn = ...
# create and use lock
lock = Lock(conn, "shared-identifier", rollback_on_error=False)
# do things with the lock
Changelog
- 0.2.2
- Fix: error raised when releasing transaction level locks
- 0.2.1
- Moved public Lock fields to properties
- 0.1.9
- Fix: release_async() bug for sqlalchemy connections
- 0.1.8
- Add logger() function
- Use "postgresql_lock" logger name
- 0.1.7
- Add logging statements
- 0.1.6
- Use int.from_bytes() to convert lock key into integer
- Fix: psycopg3 close() not being awaited bug
- 0.1.5
- Rename package from postgres-lock to postgresql-lock
- 0.1.4
- Add py.typed for mypy
- 0.1.3
- Key can be any object
- 0.1.2
- Add Lock.rollback_on_error (default true)
- Add Lock.handle_error() & Lock.handle_error_async()
- 0.1.1
- Key can be str or int
Release files for postgresql-lock 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| postgresql_lock-0.2.2.tar.gz | 7.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| postgresql_lock-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.0 kB
Release files / postgresql_lock-0.2.2.tar.gz
| Download URL | postgresql_lock-0.2.2.tar.gz |
|---|---|
| Size | 7.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
48135101d3daafbc4b81c6adb8f8e448ae30d84535e0f2cfa9beb0f6f4cf911f
|
|
BLAKE2b-256 checksum How to use checksums |
b7637e05c9c85933b2a390bbb3e00b74a6fa9968f28fee8d67796d7f348d714e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-29-generic
|
Release files / postgresql_lock-0.2.2-py3-none-any.whl
| Download URL | postgresql_lock-0.2.2-py3-none-any.whl |
|---|---|
| Size | 10.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
12b3850ac76b7891d27fc5fce26cab33294b25c198a46f09cfd2588941ea433d
|
|
BLAKE2b-256 checksum How to use checksums |
69f88a8a389b328d540f06a6990c4b30fef1009337661f73aecd8e4d7d333c01
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-29-generic
|