I have a Django project that has many custom management commands that get executed from crontab. I need to implement locking in these commands to prevent cron from starting multiple instances of the command executions. So I am going through each of my custom management commands and changing:
def handle(self, *args, **options):
...
to:
from lockmgr.lockmgr import LockMgr, Locked
...
def run_handle(self, *args, **options):
''' I renamed handle() to run_handle(). '''
...
def handle(self, *args, **options):
command = sys.argv[1]
try:
with LockMgr(f'{command}_lock') as l:
self.run_handle(*args, **options)
except Locked as e:
errmsg = f'{command} failed to lock. Reason: {e}.'
self.stdout.write(errmsg)
self.logger.error(errmsg)
Then I started thinking that I should probably use a "decorator" here, but I am not quite sure how to do that. Any help would be great.
Thanks.
Ah figured it out. I need to create a python file ...
myproject/decorators/lock_cron_job.py
from lockmgr.lockmgr import LockMgr, Locked
import logging
import sys
def lock_cron_job():
"""Decorator that uses LockMgr."""
def decorator(handle_func):
def wrapped(*args, **kwargs):
command = sys.argv[1]
log = logging.getLogger(command)
try:
with LockMgr(f'{command}_lock'):
handle_func(*args, **kwargs)
except Locked as e:
errmsg = f'{command} failed to lock. Reason: {e}'
log.error(errmsg)
return wrapped
return decorator
and then in my custom management commands I would do this:
from myproject.decorators.lock_cron_job import lock_cron_job
...
@lock_cron_job()
def handle(self, *args, **options):
...