vikingco / django-db-locking Goto Github PK
View Code? Open in Web Editor NEWUse the Django ORM to lock objects in the database
Use the Django ORM to lock objects in the database
https://github.com/vikingco/django-locking/blob/master/locking/models.py#L81 loops through all locks in python.
Isn't this already possible by supplying lock_name
to aquire_lock instead of the model instance
Applying locking.0004_auto_20150915_1411...
django.db.utils.ProgrammingError: column "id" cannot be cast automatically to type uuid
HINT: Specify a USING expression to perform the conversion.
It would be handy to have a manger method that returns the lock for an object. This will allow verifying the lock held by the client is the active lock for the object in question.
It would be handy to have a release_lock method on the manager when the client only has the lock id
Not sure what is going on here:
(django-locking) D:\path\to\django-locking>ver
Microsoft Windows [Version 6.3.9600]
(django-locking) D:\path\to\django-locking>python setup.py test > fail-test-log.log 2>&1
running test
Searching for freezegun
Best match: freezegun 0.3.5
Processing freezegun-0.3.5-py2.7.egg
Using d:\path\to\django-locking\.eggs\freezegun-0.3.5-py2.7.egg
Searching for python-dateutil!=2.0,>=1.0
Best match: python-dateutil 2.4.2
Processing python_dateutil-2.4.2-py2.7.egg
Using d:\path\to\django-locking\.eggs\python_dateutil-2.4.2-py2.7.egg
Searching for six
Best match: six 1.9.0
Processing six-1.9.0-py2.7.egg
Using d:\path\to\django-locking\.eggs\six-1.9.0-py2.7.egg
running egg_info
writing django_locking.egg-info\PKG-INFO
writing top-level names to django_locking.egg-info\top_level.txt
writing dependency_links to django_locking.egg-info\dependency_links.txt
reading manifest file 'django_locking.egg-info\SOURCES.txt'
writing manifest file 'django_locking.egg-info\SOURCES.txt'
running build_ext
EEEEEEEEEE
======================================================================
ERROR: test_acquire_and_release (locking.tests.NonBlockingLockTest)
Tests an aquire/release cycle
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 20, in test_acquire_and_release
l = NonBlockingLock.objects.acquire_lock(self.user)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_acquire_and_renew (locking.tests.NonBlockingLockTest)
Tests an aquire/renew cycle
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 39, in test_acquire_and_renew
l = NonBlockingLock.objects.acquire_lock(self.user)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_context_manager (locking.tests.NonBlockingLockTest)
A lock can be used as a context manager
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 106, in test_context_manager
with NonBlockingLock.objects.acquire_lock(self.user):
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_expired (locking.tests.NonBlockingLockTest)
Test the expired locks
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 96, in test_expired
l = NonBlockingLock.objects.acquire_lock(self.user, max_age=0)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_lock_twice (locking.tests.NonBlockingLockTest)
Tests a double locking (lock and try to lock again)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 51, in test_lock_twice
l = NonBlockingLock.objects.acquire_lock(self.user)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_model (locking.tests.NonBlockingLockTest)
Test the model
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 67, in test_model
l = NonBlockingLock.objects.acquire_lock(self.user, max_age=10)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_obj_with_expired_lock_is_not_locked (locking.tests.NonBlockingLockTest)
Tests that manager.is_locked returns False if locks are expired
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 32, in test_obj_with_expired_lock_is_not_locked
NonBlockingLock.objects.acquire_lock(self.user, max_age=1)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_reloCreating test database for alias 'default'...
Destroying test database for alias 'default'...
ck (locking.tests.NonBlockingLockTest)
Test to allow lock if lock is expired
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 86, in test_relock
l = NonBlockingLock.objects.acquire_lock(self.user, max_age=10)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_unicode (locking.tests.NonBlockingLockTest)
Test the __unicode__
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 78, in test_unicode
l = NonBlockingLock.objects.acquire_lock(self.user)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
======================================================================
ERROR: test_unlock_twice (locking.tests.NonBlockingLockTest)
Tests a double unlocking (unlock and try to unlock again)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\path\to\django-locking\locking\tests.py", line 59, in test_unlock_twice
l = NonBlockingLock.objects.acquire_lock(self.user)
File "D:\path\to\django-locking\locking\models.py", line 58, in acquire_lock
raise AlreadyLocked()
AlreadyLocked
----------------------------------------------------------------------
Ran 10 tests in 0.385s
FAILED (errors=10)
Raising the issue until I can look into it further
per #13 (comment)
It would be very beneficial to use UUID primary keys for the Lock model to allow their use in the front end.
Because of the nature of locks and how the interaction interface is written, I don't think it would be very disruptive to migrate from an AutoField id to a UUIDField id.
Writing something like this:
with NonBlockingLock.objects.acquire_lock(lock_name='update_user_' + str(user.id)):
pass
...is too hard for me.
I think we can made API more shorter and pretty. In my vision it could be function which accepts lock_name
argument and returns context manager, decorator or Lock instance.
from locking import db_locking
def update_user(request):
with db_locking.lock('update_user'):
pass
@db_locking.lock('update_user')
def update_user(request):
pass
def update_user(request):
lock = db_locking.lock('update_user')
lock.acquire()
lock.release()
What you think?
Should the context manager use a thread to keep the lock active automatically on enter until releasing it on exit? https://github.com/vikingco/django-db-locking/blob/master/locking/models.py#L198
The file locking/management/commands/clean_expired_locks.py
uses NoArgsCommand
, but this is removed as of Django 1.10:
docs/releases/1.10.txt:* The class ``django.core.management.NoArgsCommand`` is removed.
This causes tox tests to fail.
Hi, I'm seeing some import errors when using python 3.5.2 and django 1.8.6:
File "/home/projects/venv/lib/python3.5/site-packages/locking/__init__.py", line 3, in <module>
import urls
ImportError: No module named 'urls'
or after changing that to from . import urls
File "/home/projects/venv/lib/python3.5/site-packages/locking/urls.py", line 1, in <module>
from django.conf.urls.defaults import *
ImportError: No module named 'django.conf.urls.defaults'
Is this module python3/django1.8.x compatible or am I doing something wrong?
Best,
gehaxelt
Right now, a lock must expire before it can be renewed as read from https://github.com/vikingco/django-locking/blob/master/locking/models.py#L58
For my use case it would be preferable to allow the lock holder to renew the lock before it expires to prevent from losing the lock resulting in duplicate action.
Shouldn't Manager.is_locked() additionally check if the existing locks have already expired?
In other words https://github.com/vikingco/django-locking/blob/master/locking/models.py#L71 should read something like the following:
return qs and any([not lock.is_expired for lock in qs])
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.