mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 13:33:24 +00:00
perf: Extract get_subscribed_stream_ids_for_user.
This new method prevents us from getting fat
objects from the database.
Instead, now we just get ids from the database
to build our subqueries.
Note that we could also technically eliminate
the `set(...)` wrappers in this code to have
Django make a subquery and save a round trip.
I am postponing that for another commit (since
it's still somewhat coupled to some other
complexity in `do_get_streams` that I am trying
to cut through, plus it's not the main point
of this commit.)
BEFORE:
# old, still in use for other codepaths
def get_stream_subscriptions_for_user(user_profile: UserProfile) -> QuerySet:
# TODO: Change return type to QuerySet[Subscription]
return Subscription.objects.filter(
user_profile=user_profile,
recipient__type=Recipient.STREAM,
)
user_subs = get_stream_subscriptions_for_user(user_profile).filter(
active=True,
).select_related('recipient')
recipient_check = Q(id__in=[sub.recipient.type_id for sub in user_subs])
AFTER:
# newly added
def get_subscribed_stream_ids_for_user(user_profile: UserProfile) -> QuerySet:
return Subscription.objects.filter(
user_profile_id=user_profile,
recipient__type=Recipient.STREAM,
active=True,
).values_list('recipient__type_id', flat=True)
subscribed_stream_ids = get_subscribed_stream_ids_for_user(user_profile)
recipient_check = Q(id__in=set(subscribed_stream_ids))
This commit is contained in:
@@ -61,6 +61,7 @@ from zerver.lib.stream_subscription import (
|
||||
get_bulk_stream_subscriber_info,
|
||||
get_stream_subscriptions_for_user,
|
||||
get_stream_subscriptions_for_users,
|
||||
get_subscribed_stream_ids_for_user,
|
||||
num_subscribers_for_stream_id,
|
||||
)
|
||||
from zerver.lib.stream_topic import StreamTopicTarget
|
||||
@@ -5436,10 +5437,6 @@ def do_get_streams(
|
||||
query = get_occupied_streams(user_profile.realm)
|
||||
|
||||
if not include_all_active:
|
||||
user_subs = get_stream_subscriptions_for_user(user_profile).filter(
|
||||
active=True,
|
||||
).select_related('recipient')
|
||||
|
||||
# We construct a query as the or (|) of the various sources
|
||||
# this user requested streams from.
|
||||
query_filter = None # type: Optional[Q]
|
||||
@@ -5452,17 +5449,17 @@ def do_get_streams(
|
||||
query_filter |= option
|
||||
|
||||
if include_subscribed:
|
||||
recipient_check = Q(id__in=[sub.recipient.type_id for sub in user_subs])
|
||||
subscribed_stream_ids = get_subscribed_stream_ids_for_user(user_profile)
|
||||
recipient_check = Q(id__in=set(subscribed_stream_ids))
|
||||
add_filter_option(recipient_check)
|
||||
if include_public:
|
||||
invite_only_check = Q(invite_only=False)
|
||||
add_filter_option(invite_only_check)
|
||||
if include_owner_subscribed and user_profile.is_bot:
|
||||
assert user_profile.bot_owner is not None
|
||||
owner_subs = get_stream_subscriptions_for_user(user_profile.bot_owner).filter(
|
||||
active=True,
|
||||
).select_related('recipient')
|
||||
owner_subscribed_check = Q(id__in=[sub.recipient.type_id for sub in owner_subs])
|
||||
bot_owner = user_profile.bot_owner
|
||||
assert bot_owner is not None
|
||||
owner_stream_ids = get_subscribed_stream_ids_for_user(bot_owner)
|
||||
owner_subscribed_check = Q(id__in=set(owner_stream_ids))
|
||||
add_filter_option(owner_subscribed_check)
|
||||
|
||||
if query_filter is not None:
|
||||
|
||||
@@ -24,6 +24,13 @@ def get_active_subscriptions_for_stream_ids(stream_ids: List[int]) -> QuerySet:
|
||||
active=True
|
||||
)
|
||||
|
||||
def get_subscribed_stream_ids_for_user(user_profile: UserProfile) -> QuerySet:
|
||||
return Subscription.objects.filter(
|
||||
user_profile_id=user_profile,
|
||||
recipient__type=Recipient.STREAM,
|
||||
active=True,
|
||||
).values_list('recipient__type_id', flat=True)
|
||||
|
||||
def get_stream_subscriptions_for_user(user_profile: UserProfile) -> QuerySet:
|
||||
# TODO: Change return type to QuerySet[Subscription]
|
||||
return Subscription.objects.filter(
|
||||
|
||||
Reference in New Issue
Block a user