cron: add random minutes offset to all jobs, at evaluation time (#38200)

SECRET_KEY is not available early enough in uwsgi context and the
behaviour doesn't need to be optional.
This commit is contained in:
Frédéric Péters 2019-12-04 15:10:38 +01:00
parent cf2a3bdef4
commit c1925e9b32
7 changed files with 18 additions and 20 deletions

View File

@ -1659,8 +1659,8 @@ 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], hourly=True))
days=[2], hours=[0], minutes=[0]))
# once a day, look for unused files
get_publisher_class().register_cronjob(CronJob(clean_unused_files,
name='clean_unused_files',
hours=[2], minutes=[0], hourly=True))
hours=[2], minutes=[0]))

View File

@ -122,7 +122,7 @@ class WcsPublisher(StubWcsPublisher):
def register_cronjobs(cls):
super(WcsPublisher, cls).register_cronjobs()
# every hour: check for global action timeouts
cls.register_cronjob(CronJob(cls.apply_global_action_timeouts, hourly=True))
cls.register_cronjob(CronJob(cls.apply_global_action_timeouts, minutes=[0]))
def is_using_postgresql(self):
return bool(self.has_site_option('postgresql') and self.cfg.get('postgresql', {}))

View File

@ -26,17 +26,13 @@ class CronJob(object):
days = None
function = None
def __init__(self, function, name=None, hours=None, minutes=None, weekdays=None, days=None, hourly=False):
def __init__(self, function, name=None, hours=None, minutes=None, weekdays=None, days=None):
self.function = function
self.name = name
self.hours = hours
self.minutes = minutes
self.weekdays = weekdays
self.days = days
if hourly:
# set minutes to an arbitrary value based on installation, this
# 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, job_name=None):
try:
@ -55,13 +51,18 @@ def cron_worker(publisher, now, job_name=None):
if job.name != job_name:
continue
else:
minutes = job.minutes
if minutes:
# will set minutes to an arbitrary value based on installation, this
# prevents waking up all jobs at the same time on a container farm.
minutes = [(x + ord(settings.SECRET_KEY[-1])) % 60 for x in minutes]
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:
if minutes and not now[4] in minutes:
continue
class FakeRequest(object):

View File

@ -1692,6 +1692,6 @@ def handle_expired_tokens(publisher):
if get_publisher_class():
# at 6:00 in the morning, every day
get_publisher_class().register_cronjob(
CronJob(handle_unused_accounts, minutes=[0], hours=[6], hourly=True))
CronJob(handle_unused_accounts, minutes=[0], hours=[6]))
get_publisher_class().register_cronjob(
CronJob(handle_expired_tokens, minutes=[10], hours=[6], hourly=True))
CronJob(handle_expired_tokens, minutes=[0], hours=[6]))

View File

@ -631,8 +631,8 @@ class QommonPublisher(Publisher, object):
def register_cronjobs(cls):
cls.register_cronjob(CronJob(cls.clean_sessions, minutes=range(0, 60, 5)))
cls.register_cronjob(CronJob(cls.clean_nonces, minutes=range(0, 60, 5)))
cls.register_cronjob(CronJob(cls.clean_afterjobs, hourly=True))
cls.register_cronjob(CronJob(cls.clean_tempfiles, hourly=True))
cls.register_cronjob(CronJob(cls.clean_afterjobs, minutes=[0]))
cls.register_cronjob(CronJob(cls.clean_tempfiles, minutes=[0]))
_initialized = False
@classmethod

View File

@ -156,4 +156,4 @@ def send_aggregation_emails(publisher):
if get_publisher_class():
# at 6:00 in the morning, every day but the week end
get_publisher_class().register_cronjob(
CronJob(send_aggregation_emails, hours=[6], minutes=[0], hourly=True, weekdays=range(5)))
CronJob(send_aggregation_emails, hours=[6], minutes=[0], weekdays=range(5)))

View File

@ -19,7 +19,6 @@ import json
import os
import sys
from django.conf import settings
from django.utils import six
from quixote import get_publisher, get_request, redirect
@ -303,11 +302,9 @@ def _apply_timeouts(publisher):
if get_publisher_class():
# every JUMP_TIMEOUT_INTERVAL minutes check for expired status jump
# timeouts; align checks with the "hourly" check defined in
# wcs/qommon/cron.py
minutes = [(x + ord(settings.SECRET_KEY[-1])) % 60
for x in range(0, 60, JUMP_TIMEOUT_INTERVAL)]
# timeouts.
get_publisher_class().register_cronjob(
CronJob(_apply_timeouts,
name='evaluate_jumps',
hours=range(24), minutes=minutes))
hours=range(24),
minutes=range(0, 60, JUMP_TIMEOUT_INTERVAL)))