cron: add option to force a specific job to run (#34906)

This commit is contained in:
Frédéric Péters 2019-07-16 14:59:25 +02:00
parent 189f25595a
commit bef5381961
4 changed files with 46 additions and 11 deletions

View File

@ -16,7 +16,9 @@ from django.core.management.base import CommandError
from django.http import Http404
from django.test import override_settings
from quixote import cleanup
from wcs.qommon import get_publisher_class
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.cron import CronJob
from utilities import create_temporary_pub
@ -214,3 +216,26 @@ def test_cron_command():
with mock.patch('wcs.qommon.management.commands.cron.cron_worker') as cron_worker:
call_command('cron')
assert cron_worker.call_count == 0
# run a specific job
jobs = []
def job1(pub):
jobs.append('job1')
def job2(pub):
jobs.append('job2')
def job3(pub):
jobs.append('job3')
@classmethod
def register_test_cronjobs(cls):
cls.register_cronjob(CronJob(job1, days=[10]))
cls.register_cronjob(CronJob(job2, name='job2', days=[10]))
cls.register_cronjob(CronJob(job3, name='job3', days=[10]))
with mock.patch('wcs.publisher.WcsPublisher.register_cronjobs', register_test_cronjobs):
get_publisher_class().cronjobs = []
call_command('cron', job_name='job1')
assert jobs == []
get_publisher_class().cronjobs = []
call_command('cron', job_name='job2')
assert jobs == ['job2']

View File

@ -1544,4 +1544,5 @@ def clean_drafts(publisher):
if get_publisher_class():
# once a month, look for drafts to remove
get_publisher_class().register_cronjob(CronJob(clean_drafts,
name='clean_drafts',
days=[2], hours=[0], minutes=[0]))

View File

@ -19,14 +19,16 @@ import sys
from django.conf import settings
class CronJob(object):
name = None
hours = None
minutes = None
weekdays = None
days = None
function = None
def __init__(self, function, hours=None, minutes=None, weekdays=None, days=None, hourly=False):
def __init__(self, function, name=None, hours=None, minutes=None, weekdays=None, days=None, hourly=False):
self.function = function
self.name = name
self.hours = hours
self.minutes = minutes
self.weekdays = weekdays
@ -36,7 +38,7 @@ class CronJob(object):
# prevents waking up all jobs at the same time on a server farm.
self.minutes = [ord(settings.SECRET_KEY[-1]) % 60]
def cron_worker(publisher, now):
def cron_worker(publisher, now, job_name=None):
try:
publisher.set_config()
except:
@ -47,14 +49,20 @@ def cron_worker(publisher, now):
publisher.reindex_sql()
for job in publisher.cronjobs:
if job.days and now[2] not in job.days:
continue
if job.weekdays and now[6] not in job.weekdays:
continue
if job.hours and not now[3] in job.hours:
continue
if job.minutes and not now[4] in job.minutes:
continue
if job_name:
# a specific job name is asked, run it whatever
# the current time is.
if job.name != job_name:
continue
else:
if job.days and now[2] not in job.days:
continue
if job.weekdays and now[6] not in job.weekdays:
continue
if job.hours and not now[3] in job.hours:
continue
if job.minutes and not now[4] in job.minutes:
continue
class FakeRequest(object):
language = publisher.get_site_language()

View File

@ -34,6 +34,7 @@ class Command(BaseCommand):
parser.set_defaults(verbosity=0)
parser.add_argument('--force-job', dest='force_job', action='store_true',
help='Run even if DISABLE_CRON_JOBS is set in settings')
parser.add_argument('--job', dest='job_name', metavar='NAME')
def handle(self, verbosity, **options):
if getattr(settings, 'DISABLE_CRON_JOBS', False) and not options['force_job']:
@ -54,7 +55,7 @@ class Command(BaseCommand):
if verbosity > 1:
print('cron work on %s' % hostname)
publisher.app_dir = os.path.join(app_dir, hostname)
cron_worker(publisher, now)
cron_worker(publisher, now, job_name=options.get('job_name'))
if verbosity > 2:
print('cron end (release lock %s)' % lockfile)
except locket.LockError: