Lock mechanism implemented with PostgreSQL advisory locks.
Project description
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.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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file postgresql_lock-0.2.1.tar.gz.
File metadata
- Download URL: postgresql_lock-0.2.1.tar.gz
- Upload date:
- Size: 7.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-26-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d601059932d717a68affc12f9c25c4b5667e6d176f44e1a6cceeb17d1daf8e73
|
|
| MD5 |
f6b75f2d49dae59dee380a50654b8193
|
|
| BLAKE2b-256 |
ae1c1ce9031a036f2a0b688573f9d6f45e707b2ea13150e3db6169a66b76556e
|
File details
Details for the file postgresql_lock-0.2.1-py3-none-any.whl.
File metadata
- Download URL: postgresql_lock-0.2.1-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-26-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fce20bfa69845652ee6d565b4d262891fc3d72408280d8b63a974d457917b0ec
|
|
| MD5 |
afc0071f710b648468d3e824b926d0c9
|
|
| BLAKE2b-256 |
d11316ecce84c23180aae3dd3b611e1a26423bc7039e3eb991830c1e680aa31f
|