Simplyfied and updated the lock manager app

This commit is contained in:
Roberto Rosario
2011-11-22 15:03:06 -04:00
parent 7e4110450b
commit 8a70e325c1
5 changed files with 44 additions and 42 deletions

View File

@@ -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)

View File

@@ -1,5 +1,5 @@
from django.conf import settings 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) DEFAULT_LOCK_TIMEOUT = getattr(settings, 'LOCK_MANAGER_DEFAULT_LOCK_TIMEOUT', DEFAULT_LOCK_TIMEOUT_VALUE)

View File

@@ -1,9 +1,4 @@
try: import logging
from psycopg2 import OperationalError
except ImportError:
class OperationalError(Exception):
pass
import datetime import datetime
from django.db.utils import DatabaseError from django.db.utils import DatabaseError
@@ -13,40 +8,33 @@ from django.db import models
from lock_manager.exceptions import LockError from lock_manager.exceptions import LockError
logger = logging.getLogger(__name__)
class LockManager(models.Manager): class LockManager(models.Manager):
@transaction.commit_manually @transaction.commit_on_success
def acquire_lock(self, name, timeout=None): def acquire_lock(self, name, timeout=None):
logger.debug('DEBUG: trying to acquire lock: %s' % name)
lock = self.model(name=name, timeout=timeout) lock = self.model(name=name, timeout=timeout)
try: try:
lock.save(force_insert=True) lock.save(force_insert=True)
logger.debug('DEBUG: acquired lock: %s' % name)
return lock
except IntegrityError: except IntegrityError:
transaction.rollback()
# There is already an existing lock # There is already an existing lock
# Check it's expiration date and if expired, delete it and # Check it's expiration date and if expired, reset it
# create it again try:
lock = self.model.objects.get(name=name) lock = self.model.objects.get(name=name)
transaction.rollback() 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): 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 lock.timeout=timeout
logger.debug('DEBUG: try to reacquire stale lock: %s' % name)
lock.save() lock.save()
transaction.commit() return lock
else: else:
raise LockError('Unable to acquire lock') 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()

View File

@@ -10,17 +10,28 @@ from lock_manager.conf.settings import DEFAULT_LOCK_TIMEOUT
class Lock(models.Model): class Lock(models.Model):
creation_datetime = models.DateTimeField(verbose_name=_(u'creation datetime')) creation_datetime = models.DateTimeField(verbose_name=_(u'creation datetime'))
timeout = models.IntegerField(default=DEFAULT_LOCK_TIMEOUT, verbose_name=_(u'timeout')) 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() objects = LockManager()
def __unicode__(self): def __unicode__(self):
return self.name return self.name
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.creation_datetime = datetime.datetime.now() 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) 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: class Meta:
verbose_name = _(u'lock') verbose_name = _(u'lock')
verbose_name_plural = _(u'locks') verbose_name_plural = _(u'locks')

View File

@@ -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 from django.test import TestCase