diff --git a/HISTORY.rst b/HISTORY.rst index 3a76214bf1..7268847dfe 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,7 @@ - Update the gunicorn worker class to synchronous. - Update the way the BaseTransformationType metaclass is passed to work on Python 3. +- Add locking to the file metadata document processing task. 3.3.3 (2019-12-05) ================== diff --git a/mayan/apps/file_metadata/literals.py b/mayan/apps/file_metadata/literals.py index 3cfea47b34..44efbe358f 100644 --- a/mayan/apps/file_metadata/literals.py +++ b/mayan/apps/file_metadata/literals.py @@ -1,3 +1,4 @@ from __future__ import unicode_literals DEFAULT_EXIF_PATH = '/usr/bin/exiftool' +LOCK_EXPIRE = 60 * 10 # Adjust to worst case scenario diff --git a/mayan/apps/file_metadata/tasks.py b/mayan/apps/file_metadata/tasks.py index 25e7a3167b..6dccc2e1f7 100644 --- a/mayan/apps/file_metadata/tasks.py +++ b/mayan/apps/file_metadata/tasks.py @@ -4,8 +4,12 @@ import logging from django.apps import apps +from mayan.apps.lock_manager.exceptions import LockError +from mayan.apps.lock_manager.runtime import locking_backend from mayan.celery import app +from .literals import LOCK_EXPIRE + from .classes import FileMetadataDriver logger = logging.getLogger(__name__) @@ -19,6 +23,17 @@ def task_process_document_version(document_version_id): document_version = DocumentVersion.objects.get(pk=document_version_id) - FileMetadataDriver.process_document_version( - document_version=document_version - ) + lock_id = 'task_process_document_version-%d' % document_version_id + try: + logger.debug('trying to acquire lock: %s', lock_id) + # Acquire lock to avoid processing the same document version more + # than once concurrently + lock = locking_backend.acquire_lock(name=lock_id, timeout=LOCK_EXPIRE) + logger.debug('acquired lock: %s', lock_id) + except LockError: + logger.debug('unable to obtain lock: %s' % lock_id) + else: + FileMetadataDriver.process_document_version( + document_version=document_version + ) + lock.release()