django_pglocks provides useful context managers for advisory locks for PostgreSQL.
django-pglocks provides a useful context manager to manage PostgreSQL advisory locks. It requires Django (tested with 1.5), PostgreSQL, and (probably) psycopg2.
Advisory locks are application-level locks that are acquired and released purely by the client of the database; PostgreSQL never acquires them on its own. They are very useful as a way of signalling to other sessions that a higher-level resource than a single row is in use, without having to lock an entire table or some other structure.
It’s entirely up to the application to correctly acquire the right lock.
Advisory locks are either session locks or transaction locks. A session lock is held until the database session disconnects (or is reset); a transaction lock is held until the transaction terminates.
Currently, the context manager only creates session locks, as the behavior of a lock persisting after the context body has been exited is surprising, and there’s no way of releasing a transaction-scope advisory lock except to exit the transaction.
Just use pip:
pip install django-pglocks
This assumes you are controlling transactions within the view; do not use this if you controlling transactions through the Django transation middleware.
from django_pglocks import advisory_lock lock_id = 'some lock' with advisory_lock(lock_id) as acquired: # code that should be inside of the lock.
The context manager attempts to take the lock, and then executes the code inside the context with the lock acquired. The lock is released when the context exits, either normally or via exception.
The parameters are:
To run the test suite, you must create a user and a database:
$ createuser -s -P django_pglocks Enter password for new role: django_pglocks Enter it again: django_pglocks $ createdb django_pglocks -O django_pglocks
You can then run the tests with:
$ DJANGO_SETTINGS_MODULE=django_pglocks.test_settings PYTHONPATH=. django-admin.py test
It’s released under the MIT License.
Fixed bug where lock would not be released when acquired with wait=False. Many thanks to Aymeric Augustin for finding this!
Removed transaction-level locks, as their behavior was somewhat surprising (having the lock persist after the context manager exited was unexpected behavior).