account_suggestions.rb 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. # frozen_string_literal: true
  2. class AccountSuggestions
  3. include DatabaseHelper
  4. SOURCES = [
  5. AccountSuggestions::SettingSource,
  6. AccountSuggestions::FriendsOfFriendsSource,
  7. AccountSuggestions::SimilarProfilesSource,
  8. AccountSuggestions::GlobalSource,
  9. ].freeze
  10. BATCH_SIZE = 40
  11. def initialize(account)
  12. @account = account
  13. end
  14. def get(limit, offset = 0)
  15. with_read_replica do
  16. account_ids_with_sources = Rails.cache.fetch("follow_recommendations/#{@account.id}", expires_in: 15.minutes) do
  17. SOURCES.flat_map { |klass| klass.new.get(@account, limit: BATCH_SIZE) }.each_with_object({}) do |(account_id, source), h|
  18. (h[account_id] ||= []).concat(Array(source).map(&:to_sym))
  19. end.to_a.shuffle
  20. end
  21. # The sources deliver accounts that haven't yet been followed, are not blocked,
  22. # and so on. Since we reset the cache on follows, blocks, and so on, we don't need
  23. # a complicated query on this end.
  24. account_ids = account_ids_with_sources[offset, limit]
  25. accounts_map = Account.where(id: account_ids.map(&:first)).includes(:account_stat).index_by(&:id)
  26. account_ids.filter_map do |(account_id, source)|
  27. next unless accounts_map.key?(account_id)
  28. AccountSuggestions::Suggestion.new(
  29. account: accounts_map[account_id],
  30. source: source
  31. )
  32. end
  33. end
  34. end
  35. def remove(target_account_id)
  36. FollowRecommendationMute.create(account_id: @account.id, target_account_id: target_account_id)
  37. end
  38. end