mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 04:53:36 +00:00
This endpoint verifies that the services that Zulip needs to function are running, and Django can talk to them. It is designed to be used as a readiness probe[^1] for Zulip, either by Kubernetes, or some other reverse-proxy load-balancer in front of Zulip. Because of this, it limits access to only localhost and the IP addresses of configured reverse proxies. Tests are limited because we cannot stop running services (which would impact other concurrent tests) and there would be extremely limited utility to mocking the very specific methods we're calling to raising the exceptions that we're looking for. [^1]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
from django.db.migrations.recorder import MigrationRecorder
|
|
from django.http import HttpRequest, HttpResponse
|
|
from django.utils.crypto import get_random_string
|
|
from django.utils.translation import gettext as _
|
|
from pika import BlockingConnection
|
|
|
|
from zerver.lib.cache import cache_delete, cache_get, cache_set
|
|
from zerver.lib.exceptions import ServerNotReadyError
|
|
from zerver.lib.queue import get_queue_client
|
|
from zerver.lib.redis_utils import get_redis_client
|
|
from zerver.lib.response import json_success
|
|
|
|
|
|
def check_database() -> None:
|
|
try:
|
|
if not MigrationRecorder.Migration.objects.exists():
|
|
raise ServerNotReadyError(_("Database is empty")) # nocoverage
|
|
except ServerNotReadyError: # nocoverage
|
|
raise
|
|
except Exception: # nocoverage
|
|
raise ServerNotReadyError(_("Cannot query postgresql"))
|
|
|
|
|
|
def check_rabbitmq() -> None: # nocoverage
|
|
try:
|
|
conn = get_queue_client().connection
|
|
if conn is None:
|
|
raise ServerNotReadyError(_("Cannot connect to rabbitmq"))
|
|
assert isinstance(conn, BlockingConnection)
|
|
conn.process_data_events()
|
|
except ServerNotReadyError:
|
|
raise
|
|
except Exception:
|
|
raise ServerNotReadyError(_("Cannot query rabbitmq"))
|
|
|
|
|
|
def check_redis() -> None:
|
|
try:
|
|
get_redis_client().ping()
|
|
except Exception: # nocoverage
|
|
raise ServerNotReadyError(_("Cannot query redis"))
|
|
|
|
|
|
def check_memcached() -> None:
|
|
try:
|
|
roundtrip_key = "health_check_" + get_random_string(32)
|
|
roundtrip_value = get_random_string(32)
|
|
cache_set(roundtrip_key, roundtrip_value)
|
|
got_value = cache_get(roundtrip_key)[0]
|
|
if got_value != roundtrip_value:
|
|
raise ServerNotReadyError(_("Cannot write to memcached")) # nocoverage
|
|
cache_delete(roundtrip_key)
|
|
except ServerNotReadyError: # nocoverage
|
|
raise
|
|
except Exception: # nocoverage
|
|
raise ServerNotReadyError(_("Cannot query memcached"))
|
|
|
|
|
|
def health(request: HttpRequest) -> HttpResponse:
|
|
check_database()
|
|
check_rabbitmq()
|
|
check_redis()
|
|
check_memcached()
|
|
|
|
return json_success(request)
|