-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
100 additions
and
397 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,100 @@ | ||
# django-bulk-update-or-create | ||
--- | ||
title: 'django-bulk-update-or-create' | ||
--- | ||
|
||
[![tests](https://github.com/fopina/django-database-locks/workflows/tests/badge.svg)](https://github.com/fopina/django-database-locks/actions?query=workflow%3Atests) | ||
|
||
.. image:: https://github.com/fopina/django-database-locks/workflows/tests/badge.svg | ||
:target: https://github.com/fopina/django-database-locks/actions?query=workflow%3Atests | ||
:alt: tests | ||
[![Test coverage status](https://codecov.io/gh/fopina/django-database-locks/branch/master/graph/badge.svg)](https://codecov.io/gh/fopina/django-database-locks) | ||
|
||
.. image:: https://codecov.io/gh/fopina/django-database-locks/branch/master/graph/badge.svg | ||
:target: https://codecov.io/gh/fopina/django-database-locks | ||
:alt: Test coverage status | ||
[![Current version on PyPi](https://img.shields.io/pypi/v/django-database-locks)](https://pypi.org/project/django-database-locks/) | ||
|
||
.. image:: https://img.shields.io/pypi/v/django-database-locks | ||
:target: https://pypi.org/project/django-database-locks/ | ||
:alt: Current version on PyPi | ||
[![monthly downloads](https://img.shields.io/pypi/dm/django-database-locks)](https://pypi.org/project/django-database-locks/) | ||
|
||
.. image:: https://img.shields.io/pypi/dm/django-database-locks | ||
:target: https://pypi.org/project/django-database-locks/ | ||
:alt: monthly downloads | ||
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/django-database-locks) | ||
|
||
.. image:: https://img.shields.io/pypi/pyversions/django-database-locks | ||
:alt: PyPI - Python Version | ||
|
||
.. image:: https://img.shields.io/pypi/djversions/django-database-locks | ||
:alt: PyPI - Django Version | ||
![PyPI - Django Version](https://img.shields.io/pypi/djversions/django-database-locks) | ||
|
||
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). | ||
Given the limitation that Percona Cluster does not support MySQL locks, | ||
this app implements locks using [select\_for\_update()]{.title-ref} (row | ||
locks). | ||
|
||
Installation | ||
------------ | ||
|
||
pip install django-database-locks | ||
============ | ||
|
||
> pip install django-database-locks | ||
Usage | ||
----- | ||
===== | ||
|
||
`django-database-locks` exposes one single the `lock` contextmanager and the `locked` decorator. | ||
[django-database-locks]{.title-ref} exposes one single the | ||
[lock]{.title-ref} contextmanager and the [locked]{.title-ref} | ||
decorator. | ||
|
||
The `locked` decorator will wrap a django management command (subclasses of `django.core.management.base.BaseCommand`) or any function with the `lock` contextmanager: | ||
The [locked]{.title-ref} decorator will wrap a django management command | ||
(subclasses of [django.core.management.base.BaseCommand]{.title-ref}) or | ||
any function with the [lock]{.title-ref} contextmanager: | ||
|
||
``` {.python} | ||
from django.core.management.base import BaseCommand | ||
.. code-block:: python | ||
from database_locks import locked | ||
from django.core.management.base import BaseCommand | ||
@locked | ||
class Command(BaseCommand): | ||
... | ||
def handle(self, *args, **options): | ||
self.stdout.write('Got the lock') | ||
``` | ||
|
||
from database_locks import locked | ||
``` {.python} | ||
from database_locks import locked | ||
@locked | ||
class Command(BaseCommand): | ||
... | ||
def handle(self, *args, **options): | ||
self.stdout.write('Got the lock') | ||
class SomeClass: | ||
def non_locked(self): | ||
pass | ||
@locked | ||
def locked(self): | ||
print('got lock') | ||
``` | ||
|
||
.. code-block:: python | ||
``` {.python} | ||
from database_locks import lock | ||
from database_locks import locked | ||
|
||
class SomeClass: | ||
def non_locked(self): | ||
pass | ||
@locked | ||
def locked(self): | ||
print('got lock') | ||
class SomeClass: | ||
def non_locked(self): | ||
pass | ||
.. code-block:: python | ||
|
||
from database_locks import lock | ||
|
||
class SomeClass: | ||
def non_locked(self): | ||
pass | ||
def locked(self): | ||
with lock(): | ||
print('got lock') | ||
def locked(self): | ||
with lock(): | ||
print('got lock') | ||
``` | ||
|
||
Docs | ||
---- | ||
|
||
Both `lock` and `locked` have the same optional args: | ||
|
||
.. code-block:: python | ||
|
||
: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`) | ||
==== | ||
|
||
Both [lock]{.title-ref} and [locked]{.title-ref} have the same optional | ||
args: | ||
|
||
``` {.python} | ||
: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]{.title-ref} | ||
|
||
- *DATABASE\_LOCKS\_STATUS\_FILE*: file that will be updated with the | ||
lock status (default [None]{.title-ref}). Useful when you have | ||
multiple shared-lock processes, to quickly inspect which one has the | ||
lock. | ||
- *DATABASE\_LOCKS\_ENABLED*: set to [False]{.title-ref} to globally | ||
disable locks (default [True]{.title-ref}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1 @@ | ||
from .locks import locked, lock | ||
|
||
default_app_config = 'database_locks.apps.DBLocksConfig' | ||
default_app_config = 'bulk_update_or_create.apps.BulkUpdateOrCreateConfig' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,5 @@ | ||
from django.apps import AppConfig | ||
from django.conf import settings | ||
|
||
APP_SETTINGS = dict(STATUS_FILE=None, ENABLED=True) | ||
|
||
|
||
class DBLocksConfig(AppConfig): | ||
name = 'database_locks' | ||
|
||
def ready(self): | ||
for k, v in APP_SETTINGS.items(): | ||
_k = 'DATABASE_LOCKS_%s' % k | ||
if not hasattr(settings, _k): | ||
setattr(settings, _k, v) | ||
class BulkUpdateOrCreateConfig(AppConfig): | ||
name = 'bulk_update_or_create' |
Oops, something went wrong.