mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-26 19:41:11 +00:00
Optimize get_audience
This avoids filtering for the user that made the post in the same query as we use for other things, which should allow for better use of indices in all cases. Previously, #2723 did some work on this that only worked for some cases in HomeStream, but this code should work for all cases. Related: #2720
This commit is contained in:
parent
77264493eb
commit
07b50a1453
1 changed files with 25 additions and 19 deletions
|
@ -107,7 +107,7 @@ class ActivityStream(RedisStore):
|
||||||
|
|
||||||
@tracer.start_as_current_span("ActivityStream._get_audience")
|
@tracer.start_as_current_span("ActivityStream._get_audience")
|
||||||
def _get_audience(self, status): # pylint: disable=no-self-use
|
def _get_audience(self, status): # pylint: disable=no-self-use
|
||||||
"""given a status, what users should see it"""
|
"""given a status, what users should see it, excluding the author"""
|
||||||
trace.get_current_span().set_attribute("status_type", status.status_type)
|
trace.get_current_span().set_attribute("status_type", status.status_type)
|
||||||
trace.get_current_span().set_attribute("status_privacy", status.privacy)
|
trace.get_current_span().set_attribute("status_privacy", status.privacy)
|
||||||
trace.get_current_span().set_attribute(
|
trace.get_current_span().set_attribute(
|
||||||
|
@ -129,15 +129,13 @@ class ActivityStream(RedisStore):
|
||||||
# only visible to the poster and mentioned users
|
# only visible to the poster and mentioned users
|
||||||
if status.privacy == "direct":
|
if status.privacy == "direct":
|
||||||
audience = audience.filter(
|
audience = audience.filter(
|
||||||
Q(id=status.user.id) # if the user is the post's author
|
Q(id__in=status.mention_users.all()) # if the user is mentioned
|
||||||
| Q(id__in=status.mention_users.all()) # if the user is mentioned
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# don't show replies to statuses the user can't see
|
# don't show replies to statuses the user can't see
|
||||||
elif status.reply_parent and status.reply_parent.privacy == "followers":
|
elif status.reply_parent and status.reply_parent.privacy == "followers":
|
||||||
audience = audience.filter(
|
audience = audience.filter(
|
||||||
Q(id=status.user.id) # if the user is the post's author
|
Q(id=status.reply_parent.user.id) # if the user is the OG author
|
||||||
| Q(id=status.reply_parent.user.id) # if the user is the OG author
|
|
||||||
| (
|
| (
|
||||||
Q(following=status.user) & Q(following=status.reply_parent.user)
|
Q(following=status.user) & Q(following=status.reply_parent.user)
|
||||||
) # if the user is following both authors
|
) # if the user is following both authors
|
||||||
|
@ -146,8 +144,7 @@ class ActivityStream(RedisStore):
|
||||||
# only visible to the poster's followers and tagged users
|
# only visible to the poster's followers and tagged users
|
||||||
elif status.privacy == "followers":
|
elif status.privacy == "followers":
|
||||||
audience = audience.filter(
|
audience = audience.filter(
|
||||||
Q(id=status.user.id) # if the user is the post's author
|
Q(following=status.user) # if the user is following the author
|
||||||
| Q(following=status.user) # if the user is following the author
|
|
||||||
)
|
)
|
||||||
return audience.distinct()
|
return audience.distinct()
|
||||||
|
|
||||||
|
@ -155,7 +152,11 @@ class ActivityStream(RedisStore):
|
||||||
def get_audience(self, status):
|
def get_audience(self, status):
|
||||||
"""given a status, what users should see it"""
|
"""given a status, what users should see it"""
|
||||||
trace.get_current_span().set_attribute("stream_id", self.key)
|
trace.get_current_span().set_attribute("stream_id", self.key)
|
||||||
return [user.id for user in self._get_audience(status)]
|
audience = self._get_audience(status)
|
||||||
|
status_author = models.User.objects.filter(
|
||||||
|
is_active=True, local=True, id=status.user.id
|
||||||
|
)
|
||||||
|
return list({user.id for user in list(audience) + list(status_author)})
|
||||||
|
|
||||||
def get_stores_for_users(self, user_ids):
|
def get_stores_for_users(self, user_ids):
|
||||||
"""convert a list of user ids into redis store ids"""
|
"""convert a list of user ids into redis store ids"""
|
||||||
|
@ -184,11 +185,13 @@ class HomeStream(ActivityStream):
|
||||||
audience = super()._get_audience(status)
|
audience = super()._get_audience(status)
|
||||||
if not audience:
|
if not audience:
|
||||||
return []
|
return []
|
||||||
# if the user is the post's author
|
|
||||||
ids_self = [user.id for user in audience.filter(Q(id=status.user.id))]
|
|
||||||
# if the user is following the author
|
# if the user is following the author
|
||||||
ids_following = [user.id for user in audience.filter(Q(following=status.user))]
|
audience = audience.filter(following=status.user)
|
||||||
return ids_self + ids_following
|
# if the user is the post's author
|
||||||
|
status_author = models.User.objects.filter(
|
||||||
|
is_active=True, local=True, id=status.user.id
|
||||||
|
)
|
||||||
|
return list({user.id for user in list(audience) + list(status_author)})
|
||||||
|
|
||||||
def get_statuses_for_user(self, user):
|
def get_statuses_for_user(self, user):
|
||||||
return models.Status.privacy_filter(
|
return models.Status.privacy_filter(
|
||||||
|
@ -229,13 +232,6 @@ class BooksStream(ActivityStream):
|
||||||
|
|
||||||
def _get_audience(self, status):
|
def _get_audience(self, status):
|
||||||
"""anyone with the mentioned book on their shelves"""
|
"""anyone with the mentioned book on their shelves"""
|
||||||
# only show public statuses on the books feed,
|
|
||||||
# and only statuses that mention books
|
|
||||||
if status.privacy != "public" or not (
|
|
||||||
status.mention_books.exists() or hasattr(status, "book")
|
|
||||||
):
|
|
||||||
return []
|
|
||||||
|
|
||||||
work = (
|
work = (
|
||||||
status.book.parent_work
|
status.book.parent_work
|
||||||
if hasattr(status, "book")
|
if hasattr(status, "book")
|
||||||
|
@ -247,6 +243,16 @@ class BooksStream(ActivityStream):
|
||||||
return []
|
return []
|
||||||
return audience.filter(shelfbook__book__parent_work=work).distinct()
|
return audience.filter(shelfbook__book__parent_work=work).distinct()
|
||||||
|
|
||||||
|
def get_audience(self, status):
|
||||||
|
# only show public statuses on the books feed,
|
||||||
|
# and only statuses that mention books
|
||||||
|
if status.privacy != "public" or not (
|
||||||
|
status.mention_books.exists() or hasattr(status, "book")
|
||||||
|
):
|
||||||
|
return []
|
||||||
|
|
||||||
|
return super().get_audience(status)
|
||||||
|
|
||||||
def get_statuses_for_user(self, user):
|
def get_statuses_for_user(self, user):
|
||||||
"""any public status that mentions the user's books"""
|
"""any public status that mentions the user's books"""
|
||||||
books = user.shelfbook_set.values_list(
|
books = user.shelfbook_set.values_list(
|
||||||
|
|
Loading…
Reference in a new issue