Repository: boxine/django-huey-monitor (language: python)

Issue:
v0.7.0 gives error with django_huey's multi-queues
The version 0.7.0 gives a ConnectionError when using this library with `django_huey`'s multi-queues.

Error seems to be here:

```python
@register.simple_tag
def huey_counts_info():
    context = dict(
        huey_pending_count=HUEY.pending_count(),
        huey_scheduled_count=HUEY.scheduled_count(),
        huey_result_count=HUEY.result_count(),
    )
```

It tries to connect to a non-existing queue


Discussion / hints:
Oh, that's sad. So you use https://github.com/gaiacoop/django-huey ?
Can you provide a Trackback here? So we just catch the error. Because i didn't think it's a good idea to support "django-huey", yet.
I'm using django_huey in order to be able to run multiple queues.

The error is coming from that template tag that I posted above, as it is trying to fetch Huey's queue directly, which is not configured, and hence connecting to a non-existant redis.

Here is the full stack trace

```
OSError: [Errno 99] Cannot assign requested address
  File "redis/connection.py", line 707, in connect
    sock = self.retry.call_with_retry(
  File "redis/retry.py", line 46, in call_with_retry
    return do()
  File "redis/connection.py", line 708, in <lambda>
    lambda: self._connect(), lambda error: self.disconnect(error)
  File "redis/connection.py", line 1006, in _connect
    raise err
  File "redis/connection.py", line 994, in _connect
    sock.connect(socket_address)

ConnectionError: Error 99 connecting to localhost:6379. Cannot assign requested address.
  File "django/core/handlers/exception.py", line 38, in inner
    response = await get_response(request)
  File "django/core/handlers/base.py", line 263, in _get_response_async
    response = await sync_to_async(response.render, thread_sensitive=True)()
  File "django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "django/template/response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "django/template/base.py", line 170, in render
    return self._render(context)
  File "django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "django/template/library.py", line 192, in render
    output = self.func(*resolved_args, **resolved_kwargs)
  File "huey_monitor/templatetags/huey_monitor.py", line 12, in huey_counts_info
    huey_pending_count=HUEY.pending_count(),
  File "huey/api.py", line 594, in pending_count
    return self.storage.queue_size()
  File "huey/storage.py", line 432, in queue_size
    return self.conn.llen(self.queue_key)
  File "redis/commands/core.py", line 2694, in llen
    return self.execute_command("LLEN", name)
  File "redis/client.py", line 1266, in execute_command
    conn = self.connection or pool.get_connection(command_name, **options)
  File "redis/connection.py", line 1461, in get_connection
    connection.connect()
  File "redis/connection.py", line 713, in connect
    raise ConnectionError(self._error_message(e))
```

Thanks. Think i will catch `OSError`, so it's no problem if `redis` not used ;)

Fix patch:
diff --git a/huey_monitor/__init__.py b/huey_monitor/__init__.py
index c6cc3f4..d2598a6 100644
--- a/huey_monitor/__init__.py
+++ b/huey_monitor/__init__.py
@@ -4,5 +4,5 @@
     Django based tool for monitoring huey task queue: https://github.com/coleifer/huey
 """
 
-__version__ = '0.7.0'
+__version__ = '0.7.1'
 __author__ = 'Jens Diemer <django-huey-monitor@jensdiemer.de>'
diff --git a/huey_monitor/templatetags/huey_monitor.py b/huey_monitor/templatetags/huey_monitor.py
index d0fd613..6e565fa 100644
--- a/huey_monitor/templatetags/huey_monitor.py
+++ b/huey_monitor/templatetags/huey_monitor.py
@@ -1,16 +1,26 @@
+import logging
+
 from django import template
 from django.template.loader import render_to_string
 from huey.contrib.djhuey import HUEY
 
 
+logger = logging.getLogger(__name__)
 register = template.Library()
 
 
 @register.simple_tag
 def huey_counts_info():
-    context = dict(
-        huey_pending_count=HUEY.pending_count(),
-        huey_scheduled_count=HUEY.scheduled_count(),
-        huey_result_count=HUEY.result_count(),
-    )
-    return render_to_string('admin/huey_monitor/huey_counts_info.html', context)
+    try:
+        context = dict(
+            huey_pending_count=HUEY.pending_count(),
+            huey_scheduled_count=HUEY.scheduled_count(),
+            huey_result_count=HUEY.result_count(),
+        )
+    except OSError as err:
+        # e.g.: Redis down or other setup used see #127
+        logger.exception('Failed to get counts from HUEY: %s', err)
+
+        return f'<p>Huey counts: ({type(err).__name__}: {err})</p>'
+    else:
+        return render_to_string('admin/huey_monitor/huey_counts_info.html', context)


Test patch:
diff --git a/huey_monitor_project/tests/test_templatetags.py b/huey_monitor_project/tests/test_templatetags.py
index 974c18d..fa12dc7 100644
--- a/huey_monitor_project/tests/test_templatetags.py
+++ b/huey_monitor_project/tests/test_templatetags.py
@@ -11,3 +11,18 @@ def test_huey_counts_info(self):
         with patch('huey_monitor.templatetags.huey_monitor.HUEY', MemoryHuey()):
             html = huey_counts_info()
         self.assertHTMLEqual(html, '<p>Huey counts: Pending: 0, Scheduled: 0, Result: 0</p>')
+
+    def test_huey_counts_info_redis_down(self):
+        class HueyError:
+            def __getattribute__(self, item):
+                raise OSError('Redis down!')
+
+        with patch('huey_monitor.templatetags.huey_monitor.HUEY', HueyError()), self.assertLogs(
+            'huey_monitor'
+        ) as logs:
+            html = huey_counts_info()
+
+        self.assertHTMLEqual(html, '<p>Huey counts: (OSError: Redis down!)</p>')
+        log_message = logs.output[0]
+        self.assertIn('Traceback', log_message)
+        self.assertIn('raise OSError', log_message)