Make chat faster

This commit is contained in:
cuom1999 2023-11-01 20:54:09 -05:00
parent 58f3807b8d
commit e5b2481345
10 changed files with 135 additions and 102 deletions

View file

@ -0,0 +1,33 @@
# Generated by Django 3.2.18 on 2023-11-02 01:41
from django.db import migrations, models
def migrate(apps, schema_editor):
Room = apps.get_model("chat_box", "Room")
Message = apps.get_model("chat_box", "Message")
for room in Room.objects.all():
messages = room.message_set
last_msg = messages.first()
if last_msg:
room.last_msg_time = last_msg.time
room.save()
class Migration(migrations.Migration):
dependencies = [
("chat_box", "0014_userroom_unread_count"),
]
operations = [
migrations.AddField(
model_name="room",
name="last_msg_time",
field=models.DateTimeField(
db_index=True, null=True, verbose_name="last seen"
),
),
migrations.RunPython(migrate, migrations.RunPython.noop, atomic=True),
]

View file

@ -1,6 +1,7 @@
from django.db import models
from django.db.models import CASCADE, Q
from django.utils.translation import gettext_lazy as _
from django.utils.functional import cached_property
from judge.models.profile import Profile
@ -17,25 +18,39 @@ class Room(models.Model):
user_two = models.ForeignKey(
Profile, related_name="user_two", verbose_name="user 2", on_delete=CASCADE
)
last_msg_time = models.DateTimeField(
verbose_name=_("last seen"), null=True, db_index=True
)
class Meta:
app_label = "chat_box"
@cache_wrapper(prefix="Rc")
def contain(self, profile):
return self.user_one == profile or self.user_two == profile
@cache_wrapper(prefix="Rinfo")
def _info(self):
return {
"user_ids": [self.user_one.id, self.user_two.id],
"last_message": self.message_set.first().body,
}
@cached_property
def _cached_info(self):
return self._info()
def contain(self, profile):
return profile.id in self._cached_info["user_ids"]
@cache_wrapper(prefix="Rou")
def other_user(self, profile):
return self.user_one if profile == self.user_two else self.user_two
@cache_wrapper(prefix="Rus")
def other_user_id(self, profile):
user_ids = self._cached_info["user_ids"]
return sum(user_ids) - profile.id
def users(self):
return [self.user_one, self.user_two]
@cache_wrapper(prefix="Rlmb")
def last_message_body(self):
return self.message_set.first().body
return self._cached_info["last_message"]
class Message(models.Model):

View file

@ -84,8 +84,8 @@ class ChatView(ListView):
self.room_id = request_room
self.messages = (
Message.objects.filter(hidden=False, room=self.room_id, id__lt=last_id)
.select_related("author", "author__user")
.defer("author__about", "author__user_script")[:page_size]
.select_related("author")
.only("body", "time", "author__rating", "author__display_rank")[:page_size]
)
if not only_messages:
return super().get(request, *args, **kwargs)
@ -204,7 +204,9 @@ def post_message(request):
},
)
else:
Room.last_message_body.dirty(room)
Room._info.dirty(room)
room.last_msg_time = new_message.time
room.save()
for user in room.users():
event.post(
@ -351,11 +353,11 @@ def get_online_status(profile, other_profile_ids, rooms=None):
room = Room.objects.get(id=i["room"])
other_profile = room.other_user(profile)
count[other_profile.id] = i["unread_count"]
rooms = Room.objects.filter(id__in=rooms)
for room in rooms:
room = Room.objects.get(id=room)
other_profile = room.other_user(profile)
last_msg[other_profile.id] = room.last_message_body()
room_of_user[other_profile.id] = room.id
other_profile_id = room.other_user_id(profile)
last_msg[other_profile_id] = room.last_message_body()
room_of_user[other_profile_id] = room.id
for other_profile in other_profiles:
is_online = False
@ -389,9 +391,6 @@ def get_status_context(profile, include_ignored=False):
recent_profile = (
Room.objects.filter(Q(user_one=profile) | Q(user_two=profile))
.annotate(
last_msg_time=Subquery(
Message.objects.filter(room=OuterRef("pk")).values("time")[:1]
),
other_user=Case(
When(user_one=profile, then="user_two"),
default="user_one",
@ -412,28 +411,15 @@ def get_status_context(profile, include_ignored=False):
.values_list("id", flat=True)
)
all_user_status = (
queryset.filter(last_access__gte=last_5_minutes)
.annotate(is_online=Case(default=True, output_field=BooleanField()))
.order_by("-rating")
.exclude(id__in=admin_list)
.exclude(id__in=recent_profile_ids)
.values_list("id", flat=True)[:30]
)
return [
{
"title": "Recent",
"title": _("Recent"),
"user_list": get_online_status(profile, recent_profile_ids, recent_rooms),
},
{
"title": "Admin",
"title": _("Admin"),
"user_list": get_online_status(profile, admin_list),
},
{
"title": "Other",
"user_list": get_online_status(profile, all_user_status),
},
]