Skip to main content

Distributed locks for Django using DB (MySQL/Postgres).

Project description

tests Test coverage status Current version on PyPi monthly downloads PyPI - Python Version PyPI - Django Version

Distributed locks for Django using DB (MySQL/Postgres)

Given the limitation that Percona Cluster does not support MySQL locks, this app implements locks using select_for_update() (row locks).

Installation

pip install django-database-locks

Usage

django-database-locks exposes one single the lock contextmanager and the locked decorator.

The locked decorator will wrap a django management command (subclasses of django.core.management.base.BaseCommand) or any function with the lock contextmanager:

from django.core.management.base import BaseCommand

from database_locks import locked

@locked
class Command(BaseCommand):
    ...
    def handle(self, *args, **options):
        self.stdout.write('Got the lock')
from database_locks import locked

class SomeClass:
  def non_locked(self):
    pass

  @locked
  def locked(self):
    print('got lock')
from database_locks import lock

class SomeClass:
  def non_locked(self):
    pass

  def locked(self):
    with lock():
        print('got lock')

Docs

Both lock and locked have the same optional args:

:param lock_name: unique name in DB for this function
:param timeout: numbers of seconds to wait to acquire lock
:param lock_ttl: expiration timer of the lock, in seconds (set to None to infinite)
:param locked_by: owner id for the lock (if lock is active but owner is the same, returns acquired)
:param auto_renew: if set to True will re-acquire lock (for `lock_ttl` seconds) before `lock_ttl` is over.
                   auto_renew thread will raise KeyboardInterrupt on the main thread in case re-acquiring fails
:param retry: retry every `retry` seconds acquiring until successful. set to None or 0 to disable.
:param lost_lock_cb: callback function when lock is lost (when re-acquiring). defaults to raising LockException

There are also the following options you can specify in the project settings.py

  • DATABASE_LOCKS_STATUS_FILE: file that will be updated with the lock status (default None). Useful when you have multiple shared-lock processes, to quickly inspect which one has the lock.

  • DATABASE_LOCKS_ENABLED: set to False to globally disable locks (default True)

  • DATABASE_LOCKS_DEFAULT_TTL: global lock TTL value (default 10) which is ignored when lock_ttl is specified

  • DATABASE_LOCKS_DEFAULT_TTL_RENEW: number of seconds to renew lock before TTL expires (default 2)

Testing

Tox is used by the Github Action to test several python and django versions, with both MySQL and Postgres.

To quickly test locally, kick off a MySQL and/or Postgres docker container:

docker run -d –name locks-test

-p 8877:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.7

docker run -d –name locks-test-psql

-p 8878:5432 -e POSTGRES_PASSWORD=postgres postgres:10

List available environments with tox -l and then run the one you want/have:

tox -e py39-dj32-mysql # or tox -e py39-dj32-postgresql -e py39-dj32-mysql

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

django-database-locks-0.5.tar.gz (8.4 kB view hashes)

Uploaded Source

Built Distribution

django_database_locks-0.5-py3-none-any.whl (8.5 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page