# django-pglock
`django-pglock` performs advisory locks, table locks, and helps manage blocking locks.
Here's some of the functionality at a glance:
* `pglock.advisory` for application-level locking, for example, ensuring that tasks don't overlap.
* `pglock.model` for locking an entire model.
* `pglock.timeout` for dynamically setting the timeout to acquire a lock.
* `pglock.prioritize` to kill blocking locks for critical code, such as migrations.
* The `PGLock` and `BlockedPGLock` models for querying active and blocked locks.
* The `pglock` management command that wraps the models and provides other utilities.
## Quickstart
### Advisory Locks
Use `pglock.advisory` to acquire a [Postgres advisory lock](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS):
```python
import pglock
with pglock.advisory("my_lock_id"):
# This code blocks until the "my_lock_id" lock is available
```
Above our code will block until the lock is available, meaning no instances of the function will run simultaneously. Use the `timeout` argument to configure how long to wait for the lock. A timeout of zero will return immediately:
```python
with pglock.advisory("my_lock_id", timeout=0) as acquired:
if acquired:
# The lock is acquired
```
Use `side_effect=pglock.Raise` to raise a `django.db.utils.OperationalError` if the lock can't be acquired. When using the decorator, you can also use `side_effect=pglock.Skip` to skip the function if the lock can't be acquired:
```python
@pglock.advisory(timeout=0, side_effect=pglock.Skip)
def non_overlapping_func():
# This function will not run if there's another one already running.
# The decorator lock ID defaults to <module_name>.<function_name>
```
### Model Locks
`pglock.model` can take a lock on an entire model during a transaction. For example:
```python
from django.db import transaction
import pglock
with transaction.atomic():
pglock.model("auth.User")
# Any operations on auth.User will be exclusive here. Even read access
# for other transactions is blocked
```
`pglock.model` uses [Postgres's LOCK statement](https://www.postgresql.org/docs/current/sql-lock.html>), and it accepts the lock mode as a argument. See the [Postgres docs for more information](https://www.postgresql.org/docs/current/sql-lock.html).
**Note** `pglock.model` is similar to `pglock.advisory`. Use the `timeout` argument to avoid waiting for locks, and supply the appropriate `side_effect` to adjust runtime behavior.
### Prioritizing Blocked Code
`pglock.prioritize` will terminate any locks blocking the wrapped code:
```python
import pglock
@pglock.prioritize()
def my_func():
# Any other statements that have conflicting locks will be killed on a
# periodic interval.
MyModel.objects.update(val="value")
```
`pglock.prioritize` is useful for prioritizing code, such as migrations, to avoid situations where locks are held for too long.
### Setting the Lock Timeout
Use `pglock.timeout` to dynamically set [Postgres's lock_timeout runtime setting](https://www.postgresql.org/docs/current/runtime-config-client.html):
```python
import pglock
@pglock.timeout(1)
def do_stuff():
# This function will throw an exception if any code takes longer than
# one second to acquire a lock
```
### Querying Locks
Use `pglock.models.PGLock` to query active locks. It wraps [Postgres's pg_locks view](https://www.postgresql.org/docs/current/view-pg-locks.html). Use `pglock.models.BlockedPGLock` to query locks and join the activity that's blocking them.
Use `python manage.py pglock` to view and kill locks from the command line. It has several options for dynamic filters and re-usable configuration.
## Compatibility
`django-pglock` is compatible with Python 3.9 - 3.13, Django 4.2 - 5.1, Psycopg 2 - 3, and Postgres 13 - 17.
## Documentation
[View the django-pglock docs here](https://django-pglock.readthedocs.io/) to learn more about:
* Using advisory locks.
* Locking models.
* Setting dynamic lock timeouts.
* Killing blocking locks.
* The proxy models and custom queryset methods.
* Using and configuring the management command.
## Installation
Install `django-pglock` with:
pip3 install django-pglock
After this, add both `pgactivity` and `pglock` to the `INSTALLED_APPS` setting of your Django project.
## Contributing Guide
For information on setting up django-pglock for development and contributing changes, view [CONTRIBUTING.md](CONTRIBUTING.md).
## Creators
- [Wes Kendall](https://github.com/wesleykendall)
- [Paul Gilmartin](https://github.com/PaulGilmartin)
Raw data
{
"_id": null,
"home_page": "https://github.com/AmbitionEng/django-pglock",
"name": "django-pglock",
"maintainer": null,
"docs_url": null,
"requires_python": "<4,>=3.9.0",
"maintainer_email": null,
"keywords": null,
"author": "Wes Kendall",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/ca/9f/3b4b2f7021b626b3981646254f04fcc2db681d7ba7b24be563552368be70/django_pglock-1.7.1.tar.gz",
"platform": null,
"description": "# django-pglock\n\n`django-pglock` performs advisory locks, table locks, and helps manage blocking locks.\nHere's some of the functionality at a glance:\n\n* `pglock.advisory` for application-level locking, for example, ensuring that tasks don't overlap.\n* `pglock.model` for locking an entire model.\n* `pglock.timeout` for dynamically setting the timeout to acquire a lock.\n* `pglock.prioritize` to kill blocking locks for critical code, such as migrations.\n* The `PGLock` and `BlockedPGLock` models for querying active and blocked locks.\n* The `pglock` management command that wraps the models and provides other utilities.\n\n## Quickstart\n\n### Advisory Locks\n\nUse `pglock.advisory` to acquire a [Postgres advisory lock](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS):\n\n```python\nimport pglock\n\nwith pglock.advisory(\"my_lock_id\"):\n # This code blocks until the \"my_lock_id\" lock is available\n```\n\nAbove our code will block until the lock is available, meaning no instances of the function will run simultaneously. Use the `timeout` argument to configure how long to wait for the lock. A timeout of zero will return immediately:\n\n```python\nwith pglock.advisory(\"my_lock_id\", timeout=0) as acquired:\n if acquired:\n # The lock is acquired\n```\n\nUse `side_effect=pglock.Raise` to raise a `django.db.utils.OperationalError` if the lock can't be acquired. When using the decorator, you can also use `side_effect=pglock.Skip` to skip the function if the lock can't be acquired:\n\n```python\n@pglock.advisory(timeout=0, side_effect=pglock.Skip)\ndef non_overlapping_func():\n # This function will not run if there's another one already running.\n # The decorator lock ID defaults to <module_name>.<function_name>\n```\n\n### Model Locks\n\n`pglock.model` can take a lock on an entire model during a transaction. For example:\n\n```python\nfrom django.db import transaction\nimport pglock\n\nwith transaction.atomic():\n pglock.model(\"auth.User\")\n\n # Any operations on auth.User will be exclusive here. Even read access\n # for other transactions is blocked\n```\n\n`pglock.model` uses [Postgres's LOCK statement](https://www.postgresql.org/docs/current/sql-lock.html>), and it accepts the lock mode as a argument. See the [Postgres docs for more information](https://www.postgresql.org/docs/current/sql-lock.html).\n\n**Note** `pglock.model` is similar to `pglock.advisory`. Use the `timeout` argument to avoid waiting for locks, and supply the appropriate `side_effect` to adjust runtime behavior.\n\n### Prioritizing Blocked Code\n\n`pglock.prioritize` will terminate any locks blocking the wrapped code:\n\n```python\nimport pglock\n\n@pglock.prioritize()\ndef my_func():\n # Any other statements that have conflicting locks will be killed on a\n # periodic interval.\n MyModel.objects.update(val=\"value\")\n```\n\n`pglock.prioritize` is useful for prioritizing code, such as migrations, to avoid situations where locks are held for too long.\n\n### Setting the Lock Timeout\n\nUse `pglock.timeout` to dynamically set [Postgres's lock_timeout runtime setting](https://www.postgresql.org/docs/current/runtime-config-client.html):\n\n```python\nimport pglock\n\n@pglock.timeout(1)\ndef do_stuff():\n # This function will throw an exception if any code takes longer than\n # one second to acquire a lock\n```\n\n### Querying Locks\n\nUse `pglock.models.PGLock` to query active locks. It wraps [Postgres's pg_locks view](https://www.postgresql.org/docs/current/view-pg-locks.html). Use `pglock.models.BlockedPGLock` to query locks and join the activity that's blocking them.\n\nUse `python manage.py pglock` to view and kill locks from the command line. It has several options for dynamic filters and re-usable configuration.\n\n## Compatibility\n\n`django-pglock` is compatible with Python 3.9 - 3.13, Django 4.2 - 5.1, Psycopg 2 - 3, and Postgres 13 - 17.\n\n## Documentation\n\n[View the django-pglock docs here](https://django-pglock.readthedocs.io/) to learn more about:\n\n* Using advisory locks.\n* Locking models.\n* Setting dynamic lock timeouts.\n* Killing blocking locks.\n* The proxy models and custom queryset methods.\n* Using and configuring the management command.\n\n## Installation\n\nInstall `django-pglock` with:\n\n pip3 install django-pglock\n\nAfter this, add both `pgactivity` and `pglock` to the `INSTALLED_APPS` setting of your Django project.\n\n## Contributing Guide\n\nFor information on setting up django-pglock for development and contributing changes, view [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Creators\n\n- [Wes Kendall](https://github.com/wesleykendall)\n- [Paul Gilmartin](https://github.com/PaulGilmartin)\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "Postgres locking routines and lock table access.",
"version": "1.7.1",
"project_urls": {
"Documentation": "https://django-pglock.readthedocs.io",
"Homepage": "https://github.com/AmbitionEng/django-pglock",
"Repository": "https://github.com/AmbitionEng/django-pglock"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "15bf6fc72033801279b4ae2003c5b93cc22dfe0814ca1f56432f7cd06975381d",
"md5": "05c8914d50e098ba86753c436bf30565",
"sha256": "15db418fb56bee37fc8707038495b5085af9b8c203ebfa300202572127bdb3f0"
},
"downloads": -1,
"filename": "django_pglock-1.7.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "05c8914d50e098ba86753c436bf30565",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4,>=3.9.0",
"size": 17343,
"upload_time": "2024-12-16T01:53:45",
"upload_time_iso_8601": "2024-12-16T01:53:45.243823Z",
"url": "https://files.pythonhosted.org/packages/15/bf/6fc72033801279b4ae2003c5b93cc22dfe0814ca1f56432f7cd06975381d/django_pglock-1.7.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ca9f3b4b2f7021b626b3981646254f04fcc2db681d7ba7b24be563552368be70",
"md5": "c720b53363a09b640a53f7dc53b219fc",
"sha256": "69050bdb522fd34585d49bb8a4798dbfbab9ec4754dd1927b1b9eef2ec0edadf"
},
"downloads": -1,
"filename": "django_pglock-1.7.1.tar.gz",
"has_sig": false,
"md5_digest": "c720b53363a09b640a53f7dc53b219fc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4,>=3.9.0",
"size": 16907,
"upload_time": "2024-12-16T01:53:47",
"upload_time_iso_8601": "2024-12-16T01:53:47.290933Z",
"url": "https://files.pythonhosted.org/packages/ca/9f/3b4b2f7021b626b3981646254f04fcc2db681d7ba7b24be563552368be70/django_pglock-1.7.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-16 01:53:47",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "AmbitionEng",
"github_project": "django-pglock",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"circle": true,
"tox": true,
"lcname": "django-pglock"
}