From 90b693e550b848ef25f878e8e7ef5a4e00f641d9 Mon Sep 17 00:00:00 2001 From: Fire Demon Date: Mon, 21 Sep 2020 15:27:09 -0500 Subject: Precompute list feeds; include replies when computing home feeds --- app/lib/feed_manager.rb | 39 +++++++++++++++++++++++++++++---- app/services/precompute_feed_service.rb | 1 + 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index cfa7a4655..1edf6fb6e 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -238,6 +238,39 @@ class FeedManager end end + # Populate list feeds of account from scratch + # @param [Account] account + # @return [void] + def populate_lists(account) + limit = FeedManager::MAX_ITEMS / 2 + + account.owned_lists.includes(:accounts) do |list| + timeline_key = key(:list, list.id) + filter_options = filter_options_for(account.id) + + list.accounts.includes(:account_stat).find_each do |target_account| + if redis.zcard(timeline_key) >= limit + oldest_home_score = redis.zrange(timeline_key, 0, 0, with_scores: true).first.last.to_i + last_status_score = Mastodon::Snowflake.id_at(account.last_status_at) + + # If the feed is full and this account has not posted more recently + # than the last item on the feed, then we can skip the whole account + # because none of its statuses would stay on the feed anyway + next if last_status_score < oldest_home_score + end + + statuses = target_account.statuses.published.without_reblogs.where(visibility: [:public, :unlisted, :private]).includes(:mentions, :preloadable_poll).limit(limit) + crutches = build_crutches(account.id, statuses) + + statuses.each do |status| + add_to_feed(:list, list.id, status, false) unless filter_from_list?(status, account.id) || filter_from_home?(status, account.id, crutches, filter_options) + end + + trim(:list, list.id) + end + end + end + # Populate home feed of account from scratch # @param [Account] account # @return [void] @@ -261,14 +294,12 @@ class FeedManager next if last_status_score < oldest_home_score end - statuses = target_account.statuses.published.without_replies.where(visibility: [:public, :unlisted, :private]).includes(:preloadable_poll, reblog: :account).limit(limit) + statuses = target_account.statuses.published.where(visibility: [:public, :unlisted, :private]).includes(:mentions, :preloadable_poll, reblog: [:account, :mentions]).limit(limit) crutches = build_crutches(account.id, statuses) filter_options = filter_options_for(account.id) statuses.each do |status| - next if filter_from_home?(status, account.id, crutches, filter_options) - - add_to_feed(:home, account.id, status, aggregate) + add_to_feed(:home, account.id, status, aggregate) unless filter_from_home?(status, account.id, crutches, filter_options) end trim(:home, account.id) diff --git a/app/services/precompute_feed_service.rb b/app/services/precompute_feed_service.rb index b4fa70710..56d9d2f68 100644 --- a/app/services/precompute_feed_service.rb +++ b/app/services/precompute_feed_service.rb @@ -4,6 +4,7 @@ class PrecomputeFeedService < BaseService def call(account) FeedManager.instance.populate_home(account) FeedManager.instance.populate_direct_feed(account) + FeedManager.instance.populate_lists(account) ensure Redis.current.del("account:#{account.id}:regeneration") end -- cgit