bookwyrm/bookwyrm/views/admin/redis.py

64 lines
2.1 KiB
Python

""" redis cache status """
from django.contrib.auth.decorators import login_required, permission_required
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views import View
import redis
from bookwyrm import models, settings
r = redis.from_url(settings.REDIS_ACTIVITY_URL)
# pylint: disable= no-self-use
@method_decorator(login_required, name="dispatch")
@method_decorator(
permission_required("bookwyrm.edit_instance_settings", raise_exception=True),
name="dispatch",
)
class RedisStatus(View):
"""Are your tasks running? Well you'd better go catch them"""
def get(self, request):
"""See workers and active tasks"""
data = {"errors": []}
try:
data["info"] = r.info
# pylint: disable=broad-except
except Exception as err:
data["errors"].append(err)
return TemplateResponse(request, "settings/redis.html", data)
# pylint: disable=unused-argument
def post(self, request):
"""Erase invalid keys"""
dry_run = request.POST.get("dry_run")
patterns = [":*:*"] # this pattern is a django cache with no prefix
for user_id in models.User.objects.filter(
is_deleted=True, local=True
).values_list("id", flat=True):
patterns.append(f"{user_id}-*")
deleted_count = 0
for pattern in patterns:
deleted_count += erase_keys(pattern, dry_run=dry_run)
if dry_run:
return HttpResponse(f"{deleted_count} keys identified for deletion")
return HttpResponse(f"{deleted_count} keys deleted")
def erase_keys(pattern, count=1000, dry_run=False):
"""Delete all redis activity keys according to a provided regex pattern"""
pipeline = r.pipeline()
key_count = 0
for keys in r.scan_iter(match=pattern, count=count):
key_count += len(keys)
if not dry_run:
for key in keys:
pipeline.delete(key)
if not dry_run:
pipeline.execute()
return key_count