Skip to content

Commit f924497

Browse files
committed
Idea here:
#159 (comment) * created `rqcronjobs` management command * add some tests for it * add some documentation
1 parent 5873bac commit f924497

File tree

4 files changed

+159
-0
lines changed

4 files changed

+159
-0
lines changed

README.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,33 @@ You can use also use the management command ``rqscheduler`` to start the schedul
167167

168168
python manage.py rqscheduler
169169

170+
Support for RQ Scheduler's cron
171+
-------------------------------
172+
173+
If you have `RQ Scheduler <https://github.com/ui/rq-scheduler>`_ installed,
174+
you can easily manage Your cron entries using ``settings.RQ_CRONJOBS``:
175+
176+
.. code-block:: python
177+
178+
RQ_CRONJOBS = [
179+
('*/10 * * * *', 'whatever.function'),
180+
{
181+
'cron_string': '*/10 * * * *',
182+
'func': 'whatever.function',
183+
'timeout': 50,
184+
'args': ('foo', 'bar'),
185+
'kwargs': {'foo':'bar'},
186+
'queue': 'default',
187+
},
188+
]
189+
190+
Use the management command ``rqcronjobs`` after each deployment to reinstall all
191+
cronjobs in the scheduler::
192+
193+
python manage.py rqcronjobs
194+
195+
Note, that this command will remove all previous jobs in the default scheduler.
196+
170197
Support for django-redis and django-redis-cache
171198
-----------------------------------------------
172199

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# -*- coding: utf-8 -*-
2+
from optparse import make_option
3+
4+
from django.core.management.base import BaseCommand
5+
6+
from django_rq import get_scheduler
7+
from django_rq import settings
8+
9+
10+
class Command(BaseCommand):
11+
help = 'Remove all cronjobs from scheduer and install new ones defined in RQ_CRONJOBS setting (by default). ' \
12+
'See possible options to get more...'
13+
option_list = BaseCommand.option_list + (
14+
make_option(
15+
'-i',
16+
'--install',
17+
action='store_true',
18+
dest='install',
19+
default=False,
20+
help='Limit only to installing cronjobs defined in RQ_CRONJOBS setting.'
21+
),
22+
make_option(
23+
'-r',
24+
'--remove',
25+
action='store_true',
26+
dest='remove',
27+
default=False,
28+
help='Limit only to removing all cronjobs from scheduler.'
29+
),
30+
make_option(
31+
'-l',
32+
'--list',
33+
action='store_true',
34+
dest='list',
35+
default=False,
36+
help='List cronjobs defined in RQ_CRONJOBS setting and defined in scheduler.'
37+
),
38+
)
39+
40+
def handle(self, *args, **options):
41+
scheduler = get_scheduler()
42+
43+
if options.get('list'):
44+
print('Cronjobs from scheduler:')
45+
for cronjob in scheduler.get_jobs():
46+
print('* {}'.format(cronjob))
47+
print('')
48+
print('Cronjobs defined in settings.RQ_CRONJOBS:')
49+
for cronjob_entry in settings.CRONJOBS:
50+
print('* {}'.format(cronjob_entry))
51+
print('')
52+
else:
53+
reinstall = not (options.get('install') or options.get('remove'))
54+
55+
if reinstall or options.get('remove'):
56+
print('Removed cronjobs from scheduler:')
57+
for cronjob in scheduler.get_jobs():
58+
print('* {}'.format(cronjob))
59+
cronjob.delete()
60+
print('')
61+
62+
if reinstall or options.get('install'):
63+
print('Cronjobs installed from settings.RQ_CRONJOBS:')
64+
for cronjob_entry in settings.CRONJOBS:
65+
if type(cronjob_entry) is dict:
66+
args = []
67+
kwargs = cronjob_entry
68+
else:
69+
args = cronjob_entry
70+
kwargs = {}
71+
cronjob = scheduler.cron(
72+
*args, **kwargs
73+
)
74+
print('* {}'.format(cronjob))
75+
print('')

django_rq/settings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.conf import settings
44
from django.core.exceptions import ImproperlyConfigured
5+
from django.utils.functional import lazy
56

67
from .queues import get_unique_connection_configs
78

@@ -22,3 +23,10 @@
2223

2324
# Get exception handlers
2425
EXCEPTION_HANDLERS = getattr(settings, 'RQ_EXCEPTION_HANDLERS', [])
26+
27+
28+
# laizly get RQ_CRONJOBS from django settings
29+
# for override_settings support in tests
30+
def get_cronjobs():
31+
return getattr(settings, 'RQ_CRONJOBS', [])
32+
CRONJOBS = lazy(get_cronjobs, list)()

django_rq/tests/tests.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,3 +592,52 @@ def test_get_queue_django_redis_cache(self):
592592
self.assertEqual(connection_kwargs['port'], int(cachePort))
593593
self.assertEqual(connection_kwargs['db'], int(cacheDBNum))
594594
self.assertEqual(connection_kwargs['password'], None)
595+
596+
597+
class RqcronjobsTest(TestCase):
598+
RQ_CRONJOBS = [
599+
('*/10 * * * *', 'whatever.function'),
600+
{
601+
'cron_string': '*/10 * * * *',
602+
'func': 'whatever.function',
603+
'timeout': 5,
604+
},
605+
]
606+
607+
def setUp(self):
608+
self.scheduler = get_scheduler()
609+
self.clear_scheduler()
610+
611+
def tearDown(self):
612+
self.clear_scheduler()
613+
614+
def clear_scheduler(self):
615+
for scheduled_job in self.scheduler.get_jobs():
616+
scheduled_job.delete()
617+
618+
def add_one_job_to_scheduler(self):
619+
self.scheduler.cron(
620+
*self.RQ_CRONJOBS[0]
621+
)
622+
623+
@skipIf(RQ_SCHEDULER_INSTALLED is False, 'RQ Scheduler not installed')
624+
def test_remove(self):
625+
self.add_one_job_to_scheduler()
626+
self.assertEqual(len(self.scheduler.get_jobs()), 1)
627+
call_command('rqcronjobs', remove=True)
628+
self.assertEqual(len(self.scheduler.get_jobs()), 0)
629+
630+
@skipIf(RQ_SCHEDULER_INSTALLED is False, 'RQ Scheduler not installed')
631+
@override_settings(RQ_CRONJOBS=RQ_CRONJOBS)
632+
def test_install(self):
633+
self.assertEqual(len(self.scheduler.get_jobs()), 0)
634+
call_command('rqcronjobs', install=True)
635+
self.assertEqual(len(self.scheduler.get_jobs()), 2)
636+
637+
@skipIf(RQ_SCHEDULER_INSTALLED is False, 'RQ Scheduler not installed')
638+
@override_settings(RQ_CRONJOBS=RQ_CRONJOBS)
639+
def test_reinstall(self):
640+
self.add_one_job_to_scheduler()
641+
self.assertEqual(len(self.scheduler.get_jobs()), 1)
642+
call_command('rqcronjobs')
643+
self.assertEqual(len(self.scheduler.get_jobs()), 2)

0 commit comments

Comments
 (0)