Cache prefetch
This commit is contained in:
parent
c2f6dba462
commit
2831a24b90
6 changed files with 70 additions and 34 deletions
|
@ -25,26 +25,18 @@ class Room(models.Model):
|
|||
class Meta:
|
||||
app_label = "chat_box"
|
||||
|
||||
@cache_wrapper(prefix="Rinfo")
|
||||
def _info(self):
|
||||
last_msg = self.message_set.filter(hidden=False).first()
|
||||
return {
|
||||
"user_ids": [self.user_one.id, self.user_two.id],
|
||||
"last_message": last_msg.body if last_msg else None,
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def _cached_info(self):
|
||||
return self._info()
|
||||
return get_room_info(self.id)
|
||||
|
||||
def contain(self, profile):
|
||||
return profile.id in self._cached_info["user_ids"]
|
||||
return profile.id in [self.user_one_id, self.user_two_id]
|
||||
|
||||
def other_user(self, profile):
|
||||
return self.user_one if profile == self.user_two else self.user_two
|
||||
|
||||
def other_user_id(self, profile):
|
||||
user_ids = self._cached_info["user_ids"]
|
||||
user_ids = [self.user_one_id, self.user_two_id]
|
||||
return sum(user_ids) - profile.id
|
||||
|
||||
def users(self):
|
||||
|
@ -53,6 +45,10 @@ class Room(models.Model):
|
|||
def last_message_body(self):
|
||||
return self._cached_info["last_message"]
|
||||
|
||||
@classmethod
|
||||
def prefetch_room_cache(self, room_ids):
|
||||
get_room_info.prefetch_multi([(i,) for i in room_ids])
|
||||
|
||||
|
||||
class Message(models.Model):
|
||||
author = models.ForeignKey(Profile, verbose_name=_("user"), on_delete=CASCADE)
|
||||
|
@ -147,3 +143,11 @@ class Ignore(models.Model):
|
|||
self.remove_ignore(current_user, friend)
|
||||
else:
|
||||
self.add_ignore(current_user, friend)
|
||||
|
||||
|
||||
@cache_wrapper(prefix="Rinfo")
|
||||
def get_room_info(room_id):
|
||||
last_msg = Message.objects.filter(room_id=room_id).first()
|
||||
return {
|
||||
"last_message": last_msg.body if last_msg else None,
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ from judge import event_poster as event
|
|||
from judge.jinja2.gravatar import gravatar
|
||||
from judge.models import Friend
|
||||
|
||||
from chat_box.models import Message, Profile, Room, UserRoom, Ignore
|
||||
from chat_box.models import Message, Profile, Room, UserRoom, Ignore, get_room_info
|
||||
from chat_box.utils import encrypt_url, decrypt_url, encrypt_channel, get_unread_boxes
|
||||
|
||||
|
||||
|
@ -231,7 +231,7 @@ def post_message(request):
|
|||
},
|
||||
)
|
||||
else:
|
||||
Room._info.dirty(room)
|
||||
get_room_info.dirty(room.id)
|
||||
room.last_msg_time = new_message.time
|
||||
room.save()
|
||||
|
||||
|
@ -363,6 +363,8 @@ def user_online_status_ajax(request):
|
|||
def get_online_status(profile, other_profile_ids, rooms=None):
|
||||
if not other_profile_ids:
|
||||
return None
|
||||
Profile.prefetch_profile_cache(other_profile_ids)
|
||||
|
||||
joined_ids = ",".join([str(id) for id in other_profile_ids])
|
||||
other_profiles = Profile.objects.raw(
|
||||
f"SELECT * from judge_profile where id in ({joined_ids}) order by field(id,{joined_ids})"
|
||||
|
@ -429,6 +431,7 @@ def get_status_context(profile, include_ignored=False):
|
|||
|
||||
recent_profile_ids = [str(i["other_user"]) for i in recent_profile]
|
||||
recent_rooms = [int(i["id"]) for i in recent_profile]
|
||||
Room.prefetch_room_cache(recent_rooms)
|
||||
|
||||
admin_list = (
|
||||
queryset.filter(display_rank="admin")
|
||||
|
|
|
@ -74,7 +74,17 @@ def cache_wrapper(prefix, timeout=None):
|
|||
if l0_cache:
|
||||
l0_cache.delete(cache_key)
|
||||
|
||||
def prefetch_multi(args_list):
|
||||
keys = []
|
||||
for args in args_list:
|
||||
keys.append(get_key(func, *args))
|
||||
results = cache.get_many(keys)
|
||||
for key, result in results.items():
|
||||
if result is not None:
|
||||
_set_l0(key, result)
|
||||
|
||||
wrapper.dirty = dirty
|
||||
wrapper.prefetch_multi = prefetch_multi
|
||||
|
||||
return wrapper
|
||||
|
||||
|
|
|
@ -253,24 +253,9 @@ class Profile(models.Model):
|
|||
max_length=300,
|
||||
)
|
||||
|
||||
@cache_wrapper(prefix="Pgbi2")
|
||||
def _get_basic_info(self):
|
||||
res = {
|
||||
"email": self.user.email,
|
||||
"username": self.user.username,
|
||||
"mute": self.mute,
|
||||
}
|
||||
if self.user.first_name:
|
||||
res["first_name"] = self.user.first_name
|
||||
if self.user.last_name:
|
||||
res["last_name"] = self.user.last_name
|
||||
if self.profile_image:
|
||||
res["profile_image_url"] = self.profile_image.url
|
||||
return res
|
||||
|
||||
@cached_property
|
||||
def _cached_info(self):
|
||||
return self._get_basic_info()
|
||||
return _get_basic_info(self.id)
|
||||
|
||||
@cached_property
|
||||
def organization(self):
|
||||
|
@ -412,6 +397,10 @@ class Profile(models.Model):
|
|||
or self.user.is_superuser
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def prefetch_profile_cache(self, profile_ids):
|
||||
_get_basic_info.prefetch_multi([(pid,) for pid in profile_ids])
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
models.Index(fields=["is_unlisted", "performance_points"]),
|
||||
|
@ -540,7 +529,7 @@ class OrganizationProfile(models.Model):
|
|||
def on_user_save(sender, instance, **kwargs):
|
||||
try:
|
||||
profile = instance.profile
|
||||
profile._get_basic_info.dirty(profile)
|
||||
_get_basic_info.dirty(profile.id)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -551,4 +540,34 @@ def on_profile_save(sender, instance, **kwargs):
|
|||
return
|
||||
prev = sender.objects.get(id=instance.id)
|
||||
if prev.mute != instance.mute or prev.profile_image != instance.profile_image:
|
||||
instance._get_basic_info.dirty(instance)
|
||||
_get_basic_info.dirty(instance.id)
|
||||
|
||||
|
||||
@cache_wrapper(prefix="Pgbi2")
|
||||
def _get_basic_info(profile_id):
|
||||
profile = (
|
||||
Profile.objects.select_related("user")
|
||||
.only(
|
||||
"id",
|
||||
"mute",
|
||||
"profile_image",
|
||||
"user__username",
|
||||
"user__email",
|
||||
"user__first_name",
|
||||
"user__last_name",
|
||||
)
|
||||
.get(id=profile_id)
|
||||
)
|
||||
user = profile.user
|
||||
res = {
|
||||
"email": user.email,
|
||||
"username": user.username,
|
||||
"mute": profile.mute,
|
||||
"first_name": user.first_name or None,
|
||||
"last_name": user.last_name or None,
|
||||
"profile_image_url": profile.profile_image.url
|
||||
if profile.profile_image
|
||||
else None,
|
||||
}
|
||||
res = {k: v for k, v in res.items() if v is not None}
|
||||
return res
|
||||
|
|
|
@ -470,6 +470,7 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
|
|||
if context["in_hidden_subtasks_contest"]:
|
||||
for submission in context["submissions"]:
|
||||
self.modify_attrs(submission)
|
||||
|
||||
return context
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
|
|
@ -457,14 +457,13 @@ class UserList(QueryStringSortMixin, InfinitePaginationMixin, TitleMixin, ListVi
|
|||
queryset = (
|
||||
Profile.objects.filter(is_unlisted=False)
|
||||
.order_by(self.order, "id")
|
||||
.select_related("user")
|
||||
.only(
|
||||
"display_rank",
|
||||
"user__username",
|
||||
"points",
|
||||
"rating",
|
||||
"performance_points",
|
||||
"problem_count",
|
||||
"about",
|
||||
)
|
||||
)
|
||||
if self.request.organization:
|
||||
|
@ -472,11 +471,11 @@ class UserList(QueryStringSortMixin, InfinitePaginationMixin, TitleMixin, ListVi
|
|||
if (self.request.GET.get("friend") == "true") and self.request.profile:
|
||||
queryset = self.filter_friend_queryset(queryset)
|
||||
self.filter_friend = True
|
||||
|
||||
return queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UserList, self).get_context_data(**kwargs)
|
||||
Profile.prefetch_profile_cache([u.id for u in context["users"]])
|
||||
context["users"] = ranker(
|
||||
context["users"], rank=self.paginate_by * (context["page_obj"].number - 1)
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue