mirror of
https://github.com/zulip/zulip.git
synced 2025-11-13 02:17:19 +00:00
message: Add a bulk_access_stream_messages_query method.
This applies access restrictions in SQL, so that individual messages
do not need to be walked one-by-one. It only functions for stream
messages.
Use of this method significantly speeds up checks if we moved "all
visible messages" in a topic, since we no longer need to walk every
remaining message in the old topic to determine that at least one was
visible to the user. Similarly, it significantly speeds up merging
into existing topics, since it no longer must walk every message in
the new topic to determine if the user could see at least one.
Finally, it unlocks the ability to bulk-update only messages the user
has access to, in a single query (see subsequent commit).
(cherry picked from commit 7dcc7540f9)
This commit is contained in:
committed by
Tim Abbott
parent
9ac6ca1545
commit
9a2a5b5910
@@ -21,7 +21,7 @@ import ahocorasick
|
||||
import orjson
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
from django.db.models import Max, QuerySet, Sum
|
||||
from django.db.models import Exists, Max, OuterRef, QuerySet, Sum
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.translation import gettext as _
|
||||
from django_stubs_ext import ValuesQuerySet
|
||||
@@ -996,6 +996,38 @@ def bulk_access_messages(
|
||||
return filtered_messages
|
||||
|
||||
|
||||
def bulk_access_stream_messages_query(
|
||||
user_profile: UserProfile, messages: QuerySet[Message], stream: Stream
|
||||
) -> QuerySet[Message]:
|
||||
"""This function mirrors bulk_access_messages, above, but applies the
|
||||
limits to a QuerySet and returns a new QuerySet which only
|
||||
contains messages in the given stream which the user can access.
|
||||
Note that this only works with streams. It may return an empty
|
||||
QuerySet if the user has access to no messages (for instance, for
|
||||
a private stream which the user is not subscribed to).
|
||||
|
||||
"""
|
||||
|
||||
messages = messages.filter(realm_id=user_profile.realm_id, recipient_id=stream.recipient_id)
|
||||
|
||||
if stream.is_public() and user_profile.can_access_public_streams():
|
||||
return messages
|
||||
|
||||
if not Subscription.objects.filter(
|
||||
user_profile=user_profile, active=True, recipient=stream.recipient
|
||||
).exists():
|
||||
return Message.objects.none()
|
||||
if not stream.is_history_public_to_subscribers():
|
||||
messages = messages.annotate(
|
||||
has_usermessage=Exists(
|
||||
UserMessage.objects.filter(
|
||||
user_profile_id=user_profile.id, message_id=OuterRef("id")
|
||||
)
|
||||
)
|
||||
).filter(has_usermessage=1)
|
||||
return messages
|
||||
|
||||
|
||||
def get_messages_with_usermessage_rows_for_user(
|
||||
user_profile_id: int, message_ids: Sequence[int]
|
||||
) -> ValuesQuerySet[UserMessage, int]:
|
||||
|
||||
Reference in New Issue
Block a user