diff --git a/deep/settings.py b/deep/settings.py index cc6b76b84..1ed8058e4 100644 --- a/deep/settings.py +++ b/deep/settings.py @@ -218,6 +218,14 @@ 'drf_yasg', # API Documentation 'graphene_django', 'graphene_graphiql_explorer', + # heath check + 'health_check', + 'health_check.db', # stock Django health checkers + 'health_check.cache', + 'health_check.storage', + 'health_check.contrib.migrations', + 'health_check.contrib.celery', # requires celery + 'health_check.contrib.celery_ping', # requires celery ] + [ '{}.{}.apps.{}Config'.format( APPS_DIR.split('/')[-1], diff --git a/deep/tests/test_case.py b/deep/tests/test_case.py index ba24b1cc7..20433c7af 100644 --- a/deep/tests/test_case.py +++ b/deep/tests/test_case.py @@ -7,13 +7,10 @@ ) import datetime -from django.urls import reverse from django.test import override_settings from django.utils import timezone from django.conf import settings -from unittest.mock import patch - from deep.middleware import _set_current_request as _set_middleware_current_request from user.models import User @@ -358,21 +355,3 @@ def get_aware_datetime(self, *args, **kwargs): def get_aware_datetime_str(self, *args, **kwargs): return self.get_datetime_str(self.get_aware_datetime(*args, **kwargs)) - - -class HealthCheckViewTests(test.APITestCase): - @patch('deep.views.current_app.control.ping') - def test_health_check_healthy(self, mock_ping): - mock_ping.return_value = [{'celery@worker1': {'ok': 'pong'}}] - - response = self.client.get(reverse('celery_health_check')) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data, {"status": "healthy"}) - - @patch('deep.views.current_app.control.ping') - def test_health_check_unhealthy(self, mock_ping): - mock_ping.return_value = [] - - response = self.client.get(reverse('celery_health_check')) - self.assertEqual(response.status_code, status.HTTP_503_SERVICE_UNAVAILABLE) - self.assertEqual(response.data, {"status": "unhealthy"}) diff --git a/deep/urls.py b/deep/urls.py index 61d4687b5..36e6a4c8a 100644 --- a/deep/urls.py +++ b/deep/urls.py @@ -174,7 +174,6 @@ PasswordChanged, get_frontend_url, graphql_docs, - HealthCheckView, ) from organization.views import ( OrganizationViewSet, @@ -620,6 +619,8 @@ def get_api_path(path): name="favicon"), re_path('ses-bounce/?$', ses_bounce_handler_view, name='ses_bounce'), + re_path(r'ht/', include('health_check.urls')), + ] + [ # graphql patterns re_path('^graphql/?$', csrf_exempt(CustomGraphQLView.as_view())), @@ -648,7 +649,6 @@ def get_api_path(path): re_path(r'^ec-email/$', EntryCommentEmail.as_view()), re_path(r'^erc-email/$', EntryReviewCommentEmail.as_view()), re_path(r'^render-debug/$', RenderChart.as_view()), - re_path(r'celery-health/$', HealthCheckView.as_view(), name='celery_health_check'), ] diff --git a/deep/views.py b/deep/views.py index 66acdcb38..34fe80e18 100644 --- a/deep/views.py +++ b/deep/views.py @@ -6,7 +6,6 @@ status, response, ) -from celery import current_app from django.core.exceptions import PermissionDenied as DjPermissionDenied from django.views.decorators.clickjacking import xframe_options_exempt @@ -279,11 +278,3 @@ def format_error(error): extensions['errorCode'] = str(status.HTTP_500_INTERNAL_SERVER_ERROR) formatted_error['extensions'] = extensions return formatted_error - - -class HealthCheckView(views.APIView): - def get(self, request): - active_worker = current_app.control.ping() - if active_worker: - return response.Response({"status": "healthy"}, status=200) - return response.Response({"status": "unhealthy"}, status=503) diff --git a/poetry.lock b/poetry.lock index a0c5dc5a3..b778e59fc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "amqp" @@ -895,6 +895,24 @@ Django = ">=2.2" django-debug-toolbar = ">=3.1" graphene-django = ">=2.0.0" +[[package]] +name = "django-health-check" +version = "3.18.3" +description = "Run checks on services like databases, queue servers, celery processes, etc." +optional = false +python-versions = ">=3.8" +files = [ + {file = "django_health_check-3.18.3-py2.py3-none-any.whl", hash = "sha256:f5f58762b80bdf7b12fad724761993d6e83540f97e2c95c42978f187e452fa07"}, + {file = "django_health_check-3.18.3.tar.gz", hash = "sha256:18b75daca4551c69a43f804f9e41e23f5f5fb9efd06cf6a313b3d5031bb87bd0"}, +] + +[package.dependencies] +django = ">=2.2" + +[package.extras] +docs = ["sphinx"] +test = ["boto3", "celery", "django-storages", "pytest", "pytest-cov", "pytest-django", "redis"] + [[package]] name = "django-js-asset" version = "2.0.0" @@ -2840,6 +2858,7 @@ optional = false python-versions = ">=3.6" files = [ {file = "pytest-icdiff-0.6.tar.gz", hash = "sha256:e8f1ef4550a893b4f0a0ea7e7a8299b12ded72c086101d7811ddec0d85fd1bad"}, + {file = "pytest_icdiff-0.6-py3-none-any.whl", hash = "sha256:93ba20b71e51db7abecf99abee8fd13abd9ba7934f8e6838d1c4f443b4fc56a7"}, ] [package.dependencies] @@ -3769,4 +3788,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "5d64834a45fec04c0b4ca9436b71b3f79d774a2225ac8ad9c84cd06843599a81" +content-hash = "567353d5821c4240db9d7cf24dcf8a4f30f96d0147c3180f445fc909f97ba646" diff --git a/pyproject.toml b/pyproject.toml index 3265e8cb8..70456883f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,6 +72,7 @@ django-environ = "^0.8.1" uwsgi = "*" django-admin-autocomplete-filter = "^0.7.1" aws-sns-message-validator = "0.0.5 " +django-health-check = "^3.18.3" # Thumbnail # Shapely = "==1.7.1"