Files
zulip/zerver/lib/default_streams.py
Steve Howell d6ef94f63f page load: Improve default_streams performance.
At least as measured by test_events.py, which has over 1000
calls to fetch initial data for page loads, this should
be about a 10% improvement in how much time the server
spends fetching data.

We mostly avoid a select_related() query that did this nastiness:

    INNER JOIN "zerver_realm" ON ("zerver_stream"."realm_id" = "zerver_realm"."id")
    INNER JOIN "zerver_usergroup" ON ("zerver_stream"."can_remove_subscribers_group_id" = "zerver_usergroup"."id")
    INNER JOIN "zerver_realm" T4 ON ("zerver_usergroup"."realm_id" = T4."id")
    INNER JOIN "zerver_usergroup" T5 ON ("zerver_usergroup"."can_mention_group_id" = T5."id")
    INNER JOIN "zerver_realm" T6 ON (T5."realm_id" = T6."id")
    INNER JOIN "zerver_usergroup" T7 ON (T5."can_mention_group_id" = T7."id")
    INNER JOIN "zerver_realm" T8 ON (T7."realm_id" = T8."id")
    INNER JOIN "zerver_usergroup" T9 ON (T7."can_mention_group_id" = T9."id")
    INNER JOIN "zerver_realm" T10 ON (T9."realm_id" = T10."id")
    INNER JOIN "zerver_usergroup" T11 ON (T9."can_mention_group_id" = T11."id")
    WHERE "zerver_stream"."id" IN (SELECT U0."stream_id" FROM "zerver_defaultstream" U0 WHERE U0."realm_id" = 2

Future commits will address the codepath for creating users.
2023-07-10 13:41:28 -07:00

34 lines
1.4 KiB
Python

from typing import List, Set
from zerver.lib.types import APIStreamDict
from zerver.models import DefaultStream, Stream
def get_default_streams_for_realm(realm_id: int) -> List[Stream]:
# TODO: Deprecate this extremely expensive query. We can't immediately
# just improve it by removing select_related(), because then you
# may get the opposite problem of multiple round trips.
return [
default.stream
for default in DefaultStream.objects.select_related().filter(realm_id=realm_id)
]
def get_default_stream_ids_for_realm(realm_id: int) -> Set[int]:
return set(DefaultStream.objects.filter(realm_id=realm_id).values_list("stream_id", flat=True))
def get_default_streams_for_realm_as_dicts(realm_id: int) -> List[APIStreamDict]:
"""
Return all the default streams for a realm using a list of dictionaries sorted
by stream name.
"""
# This slightly convoluted construction makes it so that the Django ORM gets
# all the data it needs to serialize default streams as a list of dictionaries
# using a single query without using select_related().
# This is enforced by test_query_count in test_subs.py.
stream_ids = DefaultStream.objects.filter(realm_id=realm_id).values_list("stream_id")
streams = Stream.objects.filter(id__in=stream_ids)
return sorted((stream.to_dict() for stream in streams), key=lambda elt: elt["name"])