Add type check for cache
This commit is contained in:
parent
f1ba0e79c1
commit
0ea822f7a0
10 changed files with 35 additions and 13 deletions
|
@ -5,6 +5,8 @@ from django.core.handlers.wsgi import WSGIRequest
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
|
from judge.logging import log_debug
|
||||||
|
|
||||||
MAX_NUM_CHAR = 50
|
MAX_NUM_CHAR = 50
|
||||||
NONE_RESULT = "__None__"
|
NONE_RESULT = "__None__"
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ def filter_args(args_list):
|
||||||
l0_cache = caches["l0"] if "l0" in caches else None
|
l0_cache = caches["l0"] if "l0" in caches else None
|
||||||
|
|
||||||
|
|
||||||
def cache_wrapper(prefix, timeout=None):
|
def cache_wrapper(prefix, timeout=None, expected_type=None):
|
||||||
def get_key(func, *args, **kwargs):
|
def get_key(func, *args, **kwargs):
|
||||||
args_list = list(args)
|
args_list = list(args)
|
||||||
signature_args = list(signature(func).parameters.keys())
|
signature_args = list(signature(func).parameters.keys())
|
||||||
|
@ -54,10 +56,23 @@ def cache_wrapper(prefix, timeout=None):
|
||||||
cache.set(key, value, timeout)
|
cache.set(key, value, timeout)
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
|
def _validate_type(cache_key, result):
|
||||||
|
if expected_type and not isinstance(result, expected_type):
|
||||||
|
data = {
|
||||||
|
"function": f"{func.__module__}.{func.__qualname__}",
|
||||||
|
"result": str(result)[:30],
|
||||||
|
"expected_type": expected_type,
|
||||||
|
"type": type(result),
|
||||||
|
"key": cache_key,
|
||||||
|
}
|
||||||
|
log_debug("invalid_key", data)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
cache_key = get_key(func, *args, **kwargs)
|
cache_key = get_key(func, *args, **kwargs)
|
||||||
result = _get(cache_key)
|
result = _get(cache_key)
|
||||||
if result is not None:
|
if result is not None and _validate_type(cache_key, result):
|
||||||
_set_l0(cache_key, result)
|
_set_l0(cache_key, result)
|
||||||
if type(result) == str and result == NONE_RESULT:
|
if type(result) == str and result == NONE_RESULT:
|
||||||
result = None
|
result = None
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
error_log = logging.getLogger("judge.errors")
|
error_log = logging.getLogger("judge.errors")
|
||||||
|
debug_log = logging.getLogger("judge.debug")
|
||||||
|
|
||||||
|
|
||||||
def log_exception(msg):
|
def log_exception(msg):
|
||||||
error_log.exception(msg)
|
error_log.exception(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def log_debug(category, data):
|
||||||
|
debug_log.info(f"{category}: {data}")
|
||||||
|
|
|
@ -23,7 +23,7 @@ class BookMark(models.Model):
|
||||||
linked_object = GenericForeignKey("content_type", "object_id")
|
linked_object = GenericForeignKey("content_type", "object_id")
|
||||||
|
|
||||||
@cache_wrapper(prefix="BMgb")
|
@cache_wrapper(prefix="BMgb")
|
||||||
def get_bookmark(self, user):
|
def is_bookmarked_by(self, user):
|
||||||
return MakeBookMark.objects.filter(bookmark=self, user=user).exists()
|
return MakeBookMark.objects.filter(bookmark=self, user=user).exists()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -53,7 +53,7 @@ class MakeBookMark(models.Model):
|
||||||
verbose_name_plural = _("make bookmarks")
|
verbose_name_plural = _("make bookmarks")
|
||||||
|
|
||||||
|
|
||||||
@cache_wrapper(prefix="gocb")
|
@cache_wrapper(prefix="gocb", expected_type=BookMark)
|
||||||
def _get_or_create_bookmark(content_type, object_id):
|
def _get_or_create_bookmark(content_type, object_id):
|
||||||
bookmark, created = BookMark.objects.get_or_create(
|
bookmark, created = BookMark.objects.get_or_create(
|
||||||
content_type=content_type,
|
content_type=content_type,
|
||||||
|
@ -70,5 +70,5 @@ class Bookmarkable:
|
||||||
|
|
||||||
|
|
||||||
def dirty_bookmark(bookmark, profile):
|
def dirty_bookmark(bookmark, profile):
|
||||||
bookmark.get_bookmark.dirty(bookmark, profile)
|
bookmark.is_bookmarked_by.dirty(bookmark, profile)
|
||||||
_get_or_create_bookmark.dirty(bookmark.content_type, bookmark.object_id)
|
_get_or_create_bookmark.dirty(bookmark.content_type, bookmark.object_id)
|
||||||
|
|
|
@ -133,7 +133,7 @@ class BlogPost(models.Model, PageVotable, Bookmarkable):
|
||||||
and self.authors.filter(id=user.profile.id).exists()
|
and self.authors.filter(id=user.profile.id).exists()
|
||||||
)
|
)
|
||||||
|
|
||||||
@cache_wrapper(prefix="BPga")
|
@cache_wrapper(prefix="BPga", expected_type=models.query.QuerySet)
|
||||||
def get_authors(self):
|
def get_authors(self):
|
||||||
return self.authors.only("id")
|
return self.authors.only("id")
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ class PageVoteVoter(models.Model):
|
||||||
verbose_name_plural = _("pagevote votes")
|
verbose_name_plural = _("pagevote votes")
|
||||||
|
|
||||||
|
|
||||||
@cache_wrapper(prefix="gocp")
|
@cache_wrapper(prefix="gocp", expected_type=PageVote)
|
||||||
def _get_or_create_pagevote(content_type, object_id):
|
def _get_or_create_pagevote(content_type, object_id):
|
||||||
pagevote, created = PageVote.objects.get_or_create(
|
pagevote, created = PageVote.objects.get_or_create(
|
||||||
content_type=content_type,
|
content_type=content_type,
|
||||||
|
|
|
@ -440,7 +440,7 @@ class Problem(models.Model, PageVotable, Bookmarkable):
|
||||||
"profile_id", flat=True
|
"profile_id", flat=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@cache_wrapper(prefix="Pga")
|
@cache_wrapper(prefix="Pga", expected_type=models.query.QuerySet)
|
||||||
def get_authors(self):
|
def get_authors(self):
|
||||||
return self.authors.only("id")
|
return self.authors.only("id")
|
||||||
|
|
||||||
|
|
|
@ -581,7 +581,7 @@ def on_user_save(sender, instance, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@cache_wrapper(prefix="Pgbi3")
|
@cache_wrapper(prefix="Pgbi3", expected_type=dict)
|
||||||
def _get_basic_info(profile_id):
|
def _get_basic_info(profile_id):
|
||||||
profile = (
|
profile = (
|
||||||
Profile.objects.select_related("user")
|
Profile.objects.select_related("user")
|
||||||
|
|
|
@ -7,6 +7,8 @@ from django.contrib.sites.shortcuts import get_current_site
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils.functional import SimpleLazyObject, new_method_proxy
|
from django.utils.functional import SimpleLazyObject, new_method_proxy
|
||||||
|
|
||||||
|
from mptt.querysets import TreeQuerySet
|
||||||
|
|
||||||
from .models import MiscConfig, NavigationBar, Profile
|
from .models import MiscConfig, NavigationBar, Profile
|
||||||
from judge.caching import cache_wrapper
|
from judge.caching import cache_wrapper
|
||||||
|
|
||||||
|
@ -52,7 +54,7 @@ def comet_location(request):
|
||||||
return {"EVENT_DAEMON_LOCATION": websocket, "EVENT_DAEMON_POLL_LOCATION": poll}
|
return {"EVENT_DAEMON_LOCATION": websocket, "EVENT_DAEMON_POLL_LOCATION": poll}
|
||||||
|
|
||||||
|
|
||||||
@cache_wrapper(prefix="nb")
|
@cache_wrapper(prefix="nb", expected_type=TreeQuerySet)
|
||||||
def _nav_bar():
|
def _nav_bar():
|
||||||
return NavigationBar.objects.all()
|
return NavigationBar.objects.all()
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ def editable_problems(user, profile=None):
|
||||||
return subquery
|
return subquery
|
||||||
|
|
||||||
|
|
||||||
@cache_wrapper(prefix="hp", timeout=900)
|
@cache_wrapper(prefix="hp", timeout=14400)
|
||||||
def hot_problems(duration, limit):
|
def hot_problems(duration, limit):
|
||||||
qs = Problem.get_public_problems().filter(
|
qs = Problem.get_public_problems().filter(
|
||||||
submission__date__gt=timezone.now() - duration
|
submission__date__gt=timezone.now() - duration
|
||||||
|
@ -224,7 +224,7 @@ def hot_problems(duration, limit):
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
@cache_wrapper(prefix="grp", timeout=26400)
|
@cache_wrapper(prefix="grp", timeout=14400)
|
||||||
def get_related_problems(profile, problem, limit=8):
|
def get_related_problems(profile, problem, limit=8):
|
||||||
if not profile or not settings.ML_OUTPUT_PATH:
|
if not profile or not settings.ML_OUTPUT_PATH:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="actionbar-block">
|
<span class="actionbar-block">
|
||||||
<span id="bookmark-button-{{bookmark.id}}"
|
<span id="bookmark-button-{{bookmark.id}}"
|
||||||
class="bookmark-button actionbar-button {% if bookmark.get_bookmark(request.profile) == True %} bookmarked {% endif %}"
|
class="bookmark-button actionbar-button {% if bookmark.is_bookmarked_by(request.profile) %} bookmarked {% endif %}"
|
||||||
onclick="javascript:bookmark({{ bookmark.id }}, event)">
|
onclick="javascript:bookmark({{ bookmark.id }}, event)">
|
||||||
<i class="fa fa-bookmark-o" style="font-size: large;"></i>
|
<i class="fa fa-bookmark-o" style="font-size: large;"></i>
|
||||||
<span class="actionbar-text">{{_("Bookmark")}}</span>
|
<span class="actionbar-text">{{_("Bookmark")}}</span>
|
||||||
|
|
Loading…
Reference in a new issue