From 0d86499368c0e7a7175005257fce0acebd5fb839 Mon Sep 17 00:00:00 2001 From: Jack Ward Date: Tue, 23 Jul 2019 12:13:45 +1200 Subject: [PATCH] Add minimum-expected-workers command, update tests --- .travis.yml | 5 +++++ AUTHORS.rst | 2 +- HISTORY.rst | 5 +++++ README.rst | 3 +++ django_rq_pulse/__init__.py | 2 +- .../management/commands/rq_pulse_check.py | 18 ++++++++++----- django_rq_pulse/urls.py | 2 ++ setup.cfg | 2 +- setup.py | 4 +++- tests/test_commands.py | 22 ++++++++++++++++++- tests/urls.py | 4 +--- tox.ini | 9 +++++--- 12 files changed, 61 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index c541941..d812964 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,17 @@ python: - "3.5" env: + - TOX_ENV=py36-django-18 - TOX_ENV=py35-django-18 - TOX_ENV=py27-django-18 + - TOX_ENV=py36-django-19 - TOX_ENV=py35-django-19 - TOX_ENV=py27-django-19 + - TOX_ENV=py36-django-111 - TOX_ENV=py35-django-111 - TOX_ENV=py27-django-111 + - TOX_ENV=py36-django-22 + - TOX_ENV=py35-django-22 matrix: fast_finish: true diff --git a/AUTHORS.rst b/AUTHORS.rst index a86c397..a5629c8 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -10,4 +10,4 @@ Development Lead Contributors ------------ -None yet. Why not be the first? +* Jack Ward diff --git a/HISTORY.rst b/HISTORY.rst index e7d8f77..f16c346 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,11 @@ History ------- +0.1.5 (2019-07-23) +++++++++++++++++++ + +* Add argument --minimum-expected-workers [value], for when workers are not expected to be a constant value. + 0.1.4 (2018-02-13) ++++++++++++++++++ diff --git a/README.rst b/README.rst index 39b84c6..c230477 100644 --- a/README.rst +++ b/README.rst @@ -47,9 +47,12 @@ Check that rqworkers are running:: If the actual number of workers is not equal the expected number of workers or If there are items in the queue but the queue size is not changing notify admins by email. +'--minimum-num-workers [value]' will report whether a minimum number is running rather than an exact number. + The above command will run with default parameters where:: --expected-num-workers=2 + --minimum-num-workers=0 --seconds-to-sleep=5 --num-retries=5 --queue-name="default" diff --git a/django_rq_pulse/__init__.py b/django_rq_pulse/__init__.py index 7525d19..66a87bb 100644 --- a/django_rq_pulse/__init__.py +++ b/django_rq_pulse/__init__.py @@ -1 +1 @@ -__version__ = '0.1.4' +__version__ = '0.1.5' diff --git a/django_rq_pulse/management/commands/rq_pulse_check.py b/django_rq_pulse/management/commands/rq_pulse_check.py index 0532631..c7608d6 100644 --- a/django_rq_pulse/management/commands/rq_pulse_check.py +++ b/django_rq_pulse/management/commands/rq_pulse_check.py @@ -23,11 +23,14 @@ class Command(BaseCommand): If the queue has items but its size does not change over time then it is likely that the workers are down so we notify admins. """ + WORKERS_DOWN_SUBJECT = 'WARNING: RQ Workers maybe down!' def add_arguments(self, parser): """Add command arguments.""" parser.add_argument('--expected-num-workers', dest='expected_num_workers', type=int, default=2, help='The expected number of running workers.') + parser.add_argument('--minimum-num-workers', dest='minimum_num_workers', type=int, default=0, + help='The minimum number of running workers. Cannot be used in conjunction with expected_num_workers.') parser.add_argument('--seconds-to-sleep', dest='seconds_to_sleep', type=int, default=5, help='The number of seconds to sleep before checking the queue size.') parser.add_argument('--num-retries', dest='num_retries', type=int, default=5, @@ -39,6 +42,7 @@ def handle(self, *args, **options): """Handle command logic.""" log.info('Checking rq workers') + self.minimum_num_workers = options['minimum_num_workers'] self.expected_num_workers = options['expected_num_workers'] self.seconds_to_sleep = options['seconds_to_sleep'] self.num_retries = options['num_retries'] @@ -50,12 +54,15 @@ def handle(self, *args, **options): # Check the number of workers is as expected and notify otherwise workers = Worker.all(connection=redis_conn) num_workers = len(workers) - - if num_workers != self.expected_num_workers: - subject = 'WARNING: RQ Workers maybe down!' + + if num_workers < self.minimum_num_workers: + message = 'The number of workers {} is less than the expected number {}. Workers may be down.'.format( + num_workers, self.minimum_num_workers) + self.notify(self.WORKERS_DOWN_SUBJECT, message) + elif num_workers != self.expected_num_workers: message = 'The number of workers {} does not equal the expected number {}. Workers maybe down.'.format( num_workers, self.expected_num_workers) - self.notify(subject, message) + self.notify(self.WORKERS_DOWN_SUBJECT, message) # Check the Queue size is changing and notify otherwise self.q = Queue(self.queue_name, connection=redis_conn) @@ -72,9 +79,8 @@ def handle(self, *args, **options): log.info('The Q size is not changing, will check again after {} seconds.'.format(self.seconds_to_sleep)) if not is_q_size_changing: - subject = 'WARNING: RQ Workers maybe down!' message = 'The Q size is not changing, this is bad. Workers maybe down.' - self.notify(subject, message) + self.notify(self.WORKERS_DOWN_SUBJECT, message) log.info('Finished checking rq workers') diff --git a/django_rq_pulse/urls.py b/django_rq_pulse/urls.py index f92af40..62eaa2e 100644 --- a/django_rq_pulse/urls.py +++ b/django_rq_pulse/urls.py @@ -4,6 +4,8 @@ from . import views +app_name = 'django_rq_pulse' + urlpatterns = [ url(r'', TemplateView.as_view(template_name="base.html")), ] diff --git a/setup.cfg b/setup.cfg index 4d4f2b9..be528ee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.4 +current_version = 0.1.5 commit = True tag = True diff --git a/setup.py b/setup.py index d675669..1e4f627 100755 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ setup( name='django-rq-pulse', - version='0.1.4', + version='0.1.5', description="""A Django package to check that rq workers are running and notify admins if they are not""", long_description=readme + '\n\n' + history, author='Medhat Gayed', @@ -35,6 +35,7 @@ 'Framework :: Django :: 1.8', 'Framework :: Django :: 1.9', 'Framework :: Django :: 1.11', + 'Framework :: Django :: 2.2', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Natural Language :: English', @@ -42,5 +43,6 @@ 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ], ) diff --git a/tests/test_commands.py b/tests/test_commands.py index bfe80ac..a029c64 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -36,10 +36,30 @@ def test_number_of_workers_is_expected( call_command('rq_pulse_check') self.assertFalse(mock_mail_admins.called) + def test_minimum_number_of_workers_is_not_expected( + self, mock_queue, mock_worker, mock_mail_admins, mock_log, mock_time): + mock_worker.all.return_value = [] + call_command('rq_pulse_check', minimum_num_workers=2) + mock_mail_admins.assert_called_with( + 'WARNING: RQ Workers maybe down!', + 'The number of workers 0 is less than the expected number 2. Workers may be down.') + + mock_worker.all.return_value = [mock.MagicMock()] + call_command('rq_pulse_check', minimum_num_workers=2) + mock_mail_admins.assert_called_with( + 'WARNING: RQ Workers maybe down!', + 'The number of workers 1 is less than the expected number 2. Workers may be down.') + + def test_minimum_number_of_workers_is_expected( + self, mock_queue, mock_worker, mock_mail_admins, mock_log, mock_time): + mock_worker.all.return_value = [mock.MagicMock(), mock.MagicMock()] + call_command('rq_pulse_check') + self.assertFalse(mock_mail_admins.called) + def test_queue_has_no_items( self, mock_queue, mock_worker, mock_mail_admins, mock_log, mock_time): mock_queue.return_value.__len__.return_value = 0 - call_command('rq_pulse_check') + call_command('rq_pulse_check', minimum_num_workers=2) self.assertFalse(mock_time.sleep.called) def test_queue_has_items_and_queue_size_not_changing( diff --git a/tests/urls.py b/tests/urls.py index 3c6dbdc..787301e 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -3,8 +3,6 @@ from django.conf.urls import url, include -from django_rq_pulse.urls import urlpatterns as django_rq_pulse_urls - urlpatterns = [ - url(r'^', include(django_rq_pulse_urls, namespace='django_rq_pulse')), + url(r'^', include('django_rq_pulse.urls', namespace='django_rq_pulse')), ] diff --git a/tox.ini b/tox.ini index deffb51..46680c1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,9 @@ [tox] envlist = - {py27,py35}-django-18 - {py27,py35}-django-19 - {py27,py35}-django-111 + {py27,py35,py36}-django-18 + {py27,py35,py36}-django-19 + {py27,py35,py36}-django-111 + {py35,py36}-django-22 [testenv] setenv = @@ -12,7 +13,9 @@ deps = django-18: Django>=1.8,<1.9 django-19: Django>=1.9,<1.10 django-111: Django>=1.11,<2.0 + django-22: Django>=2.2,<2.3 -r{toxinidir}/requirements_test.txt basepython = + py36: python3.6 py35: python3.5 py27: python2.7