diff --git a/apps/lock_manager/admin.py b/apps/lock_manager/admin.py new file mode 100644 index 0000000000..12dbee8fe1 --- /dev/null +++ b/apps/lock_manager/admin.py @@ -0,0 +1,10 @@ +from django.contrib import admin + +from lock_manager.models import Lock + + +class LockAdmin(admin.ModelAdmin): + model = Lock + + +admin.site.register(Lock, LockAdmin) diff --git a/apps/lock_manager/conf/settings.py b/apps/lock_manager/conf/settings.py index 05f4ae374c..869e121f4d 100644 --- a/apps/lock_manager/conf/settings.py +++ b/apps/lock_manager/conf/settings.py @@ -1,5 +1,5 @@ from django.conf import settings -DEFAULT_LOCK_TIMEOUT_VALUE = 10 +DEFAULT_LOCK_TIMEOUT_VALUE = 30 DEFAULT_LOCK_TIMEOUT = getattr(settings, 'LOCK_MANAGER_DEFAULT_LOCK_TIMEOUT', DEFAULT_LOCK_TIMEOUT_VALUE) diff --git a/apps/lock_manager/managers.py b/apps/lock_manager/managers.py index 96c57ca02b..206df912b6 100644 --- a/apps/lock_manager/managers.py +++ b/apps/lock_manager/managers.py @@ -1,9 +1,4 @@ -try: - from psycopg2 import OperationalError -except ImportError: - class OperationalError(Exception): - pass - +import logging import datetime from django.db.utils import DatabaseError @@ -13,40 +8,33 @@ from django.db import models from lock_manager.exceptions import LockError +logger = logging.getLogger(__name__) + class LockManager(models.Manager): - @transaction.commit_manually + @transaction.commit_on_success def acquire_lock(self, name, timeout=None): + logger.debug('DEBUG: trying to acquire lock: %s' % name) lock = self.model(name=name, timeout=timeout) try: lock.save(force_insert=True) + logger.debug('DEBUG: acquired lock: %s' % name) + return lock except IntegrityError: - transaction.rollback() # There is already an existing lock - # Check it's expiration date and if expired, delete it and - # create it again - lock = self.model.objects.get(name=name) - transaction.rollback() + # Check it's expiration date and if expired, reset it + try: + lock = self.model.objects.get(name=name) + except self.model.DoesNotExist: + # Table based locking + logger.debug('DEBUG: lock: %s does not exist' % name) + raise LockError('Unable to acquire lock') if datetime.datetime.now() > lock.creation_datetime + datetime.timedelta(seconds=lock.timeout): - self.release_lock(name) + logger.debug('DEBUG: reseting deleting stale lock: %s' % name) lock.timeout=timeout + logger.debug('DEBUG: try to reacquire stale lock: %s' % name) lock.save() - transaction.commit() + return lock else: raise LockError('Unable to acquire lock') - except DatabaseError: - transaction.rollback() - # Special case for ./manage.py syncdb - except (OperationalError, ImproperlyConfigured): - transaction.rollback() - # Special for DjangoZoom, which executes collectstatic media - # doing syncdb and creating the database tables - else: - transaction.commit() - - @transaction.commit_manually - def release_lock(self, name): - lock = self.model.objects.get(name=name) - lock.delete() - transaction.commit() diff --git a/apps/lock_manager/models.py b/apps/lock_manager/models.py index 53c6b6e49d..535d3366a6 100644 --- a/apps/lock_manager/models.py +++ b/apps/lock_manager/models.py @@ -10,17 +10,28 @@ from lock_manager.conf.settings import DEFAULT_LOCK_TIMEOUT class Lock(models.Model): creation_datetime = models.DateTimeField(verbose_name=_(u'creation datetime')) timeout = models.IntegerField(default=DEFAULT_LOCK_TIMEOUT, verbose_name=_(u'timeout')) - name = models.CharField(max_length=32, verbose_name=_(u'name'), unique=True) - + name = models.CharField(max_length=48, verbose_name=_(u'name'), unique=True) + objects = LockManager() - + def __unicode__(self): return self.name - + def save(self, *args, **kwargs): self.creation_datetime = datetime.datetime.now() + if not self.timeout and not kwarget.get('timeout'): + self.timeout = DEFAULT_LOCK_TIMEOUT + super(Lock, self).save(*args, **kwargs) - + + def release(self): + try: + lock = Lock.objects.get(name=self.name, creation_datetime=self.creation_datetime) + lock.delete() + except Lock.DoesNotExist: + # Out lock expired and was reassigned + pass + class Meta: verbose_name = _(u'lock') verbose_name_plural = _(u'locks') diff --git a/apps/lock_manager/tests.py b/apps/lock_manager/tests.py index 501deb776c..140393d027 100644 --- a/apps/lock_manager/tests.py +++ b/apps/lock_manager/tests.py @@ -1,10 +1,3 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" - from django.test import TestCase