Add lock to make sure only one ical_sync can run simultaneously
This commit is contained in:
parent
d78f69abe9
commit
ee2856c5fc
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -215,6 +215,7 @@ fabric.properties
|
|||
.idea/
|
||||
|
||||
venv/
|
||||
static/
|
||||
|
||||
davinci/local.py
|
||||
|
||||
|
|
61
davinci/icalendar/decorators.py
Normal file
61
davinci/icalendar/decorators.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
import time
|
||||
import logging
|
||||
|
||||
from lockfile import FileLock, AlreadyLocked, LockTimeout
|
||||
from django.conf import settings
|
||||
|
||||
# Lock timeout value - how long to wait for the lock to become available.
|
||||
# Default behavior is to never wait for the lock to be available (fail fast)
|
||||
LOCK_WAIT_TIMEOUT = getattr(settings, "DEFAULT_LOCK_WAIT_TIMEOUT", -1)
|
||||
|
||||
|
||||
def handle_lock(handle):
|
||||
"""
|
||||
Decorate the handle method with a file lock to ensure there is only ever
|
||||
one process running at any one time.
|
||||
"""
|
||||
|
||||
def wrapper(self, *args, **options):
|
||||
|
||||
start_time = time.time()
|
||||
verbosity = options.get('verbosity', 0)
|
||||
if verbosity == 0:
|
||||
level = logging.WARNING
|
||||
elif verbosity == 1:
|
||||
level = logging.INFO
|
||||
else:
|
||||
level = logging.DEBUG
|
||||
|
||||
logging.basicConfig(level=level, format="%(message)s")
|
||||
logging.debug("-" * 72)
|
||||
|
||||
lock_name = self.__module__.split('.').pop()
|
||||
lock = FileLock(lock_name)
|
||||
|
||||
logging.debug("%s - acquiring lock..." % lock_name)
|
||||
try:
|
||||
lock.acquire(LOCK_WAIT_TIMEOUT)
|
||||
except AlreadyLocked:
|
||||
logging.debug("lock already in place. quitting.")
|
||||
return
|
||||
except LockTimeout:
|
||||
logging.debug("waiting for the lock timed out. quitting.")
|
||||
return
|
||||
logging.debug("acquired.")
|
||||
|
||||
try:
|
||||
handle(self, *args, **options)
|
||||
except:
|
||||
import traceback
|
||||
logging.warning("Command Failed")
|
||||
logging.warning('==' * 72)
|
||||
logging.warning(traceback.format_exc())
|
||||
logging.warning('==' * 72)
|
||||
|
||||
logging.debug("releasing lock...")
|
||||
lock.release()
|
||||
logging.debug("released.")
|
||||
|
||||
logging.info("done in %.2f seconds" % (time.time() - start_time))
|
||||
|
||||
return wrapper
|
|
@ -3,12 +3,14 @@ import logging
|
|||
from django.core.management.base import BaseCommand
|
||||
from django.utils import timezone
|
||||
|
||||
from davinci.icalendar.decorators import handle_lock
|
||||
from davinci.icalendar.models import ICalSync
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Sychronize iCal syncs that need to be synchronized.'
|
||||
|
||||
@handle_lock
|
||||
def handle(self, *args, **options):
|
||||
logger = logging.getLogger("davinci.icalendar.ical_sync")
|
||||
logger.debug(f"Command `ical_sync` invoked")
|
||||
|
|
|
@ -4,3 +4,4 @@ django-durationwidget>=1.0.5,<1.1
|
|||
humanize>=3.1.0,<3.2
|
||||
ics>=0.7,<0.8
|
||||
caldav>=0.7.1,<0.8
|
||||
lockfile>=0.12.2,<0.13
|
||||
|
|
Loading…
Reference in a new issue