revsys / django-health-check

a pluggable app that runs a full check on the deployment, using a number of plugins to check e.g. database, queue server, celery processes, etc.

Home Page:https://readthedocs.org/projects/django-health-check/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CacheBackend: Redis Exceptions are not catched

Flauschbaellchen opened this issue · comments

commented

While using the cache backend health check, I've found that the check itself sometimes raises exceptions which are not catched.

from health_check.cache.backends import CacheBackend
health_cache.run_check()
if not health_cache.status:
  # do something

If the redis server itself was not initialized or not reachable, it resulted in the following exception:

File "/usr/local/lib/python3.10/site-packages/health_check/backends.py", line 30, in run_check
  self.check_status()
File "/usr/local/lib/python3.10/site-packages/health_check/cache/backends.py", line 19, in check_status
  cache.set("djangohealtcheck_test", "itworks")
File "/usr/local/lib/python3.10/site-packages/django_redis/cache.py", line 38, in _decorator
  raise e.__cause__
File "/usr/local/lib/python3.10/site-packages/django_redis/client/default.py", line 175, in set
  return bool(client.set(nkey, nvalue, nx=nx, px=timeout, xx=xx))
File "/usr/local/lib/python3.10/site-packages/redis/commands/core.py", line 2220, in set
  return self.execute_command("SET", *pieces, **options)
File "/usr/local/lib/python3.10/site-packages/redis/client.py", line 1235, in execute_command
  conn = self.connection or pool.get_connection(command_name, **options)
File "/usr/local/lib/python3.10/site-packages/redis/connection.py", line 1387, in get_connection
  connection.connect()
File "/usr/local/lib/python3.10/site-packages/redis/connection.py", line 617, in connect
  raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error 111 connecting to redis:6379. Connection refused.

This is because redis.exceptions.ConnectionError does not subclasses builtin ConnectionError which would be catched within the health-check:
https://github.com/redis/redis-py/blob/master/redis/exceptions.py

The health-check should be extended to catch this kind of errors.

Pull-Request: #340

commented

@jefftriplett @frankwiles Sorry to bump this issue 🙇 , but could you take a look at it and the referenced PR?

commented

Oww, I just saw that @violuke mentioned it in his own issue #354. The already existing (and closed as wont-fix) issue #240 somehow slipped by search.
However, not catching this error results in an error which is further raised to the top.

This might be not a problem (even if not a really "nice" solution) when used in live/ready/startup probes of K8s - but in my case I also use it in some other parts of the main application to check if certain actions can take place (background migrations etc).
Not catching this error would result in a broken application.

I would expect that the health-check would gracefully handle this, as this exception is a sign of "backend not working".
A health-check which itself raises an exception is not really useful.

Thus, I would like to start the discussion again, if the RedisError could be catched.
I've proposed my solution in the referenced PR, maybe this also resolved the discussion about "what to do if Redis is not used"? - because the PR would handle this case gracefully, too.

I'll see if I can carve out some time this week. I'm new to the project and trying not to overstep. I think it might be helpful to stage a test so we can address as many concerns as possible. This should be doable with redis.

I have same problem with Redis CacheBackend
redis raise redis.exceptions.ConnectionError, but django-health-check catches default python ConnectionError.