You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
1.8 KiB

  1. # frozen_string_literal: true
  2. class Scheduler::FollowRecommendationsScheduler
  3. include Sidekiq::Worker
  4. include Redisable
  5. sidekiq_options retry: 0
  6. # The maximum number of accounts that can be requested in one page from the
  7. # API is 80, and the suggestions API does not allow pagination. This number
  8. # leaves some room for accounts being filtered during live access
  9. SET_SIZE = 100
  10. def perform
  11. # Maintaining a materialized view speeds-up subsequent queries significantly
  12. AccountSummary.refresh
  13. FollowRecommendation.refresh
  14. fallback_recommendations = FollowRecommendation.limit(SET_SIZE).index_by(&:account_id)
  15. I18n.available_locales.each do |locale|
  16. recommendations = begin
  17. if AccountSummary.safe.filtered.localized(locale).exists? # We can skip the work if no accounts with that language exist
  18. FollowRecommendation.localized(locale).limit(SET_SIZE).index_by(&:account_id)
  19. else
  20. {}
  21. end
  22. end
  23. # Use language-agnostic results if there are not enough language-specific ones
  24. missing = SET_SIZE - recommendations.keys.size
  25. if missing.positive?
  26. added = 0
  27. # Avoid duplicate results
  28. fallback_recommendations.each_value do |recommendation|
  29. next if recommendations.key?(recommendation.account_id)
  30. recommendations[recommendation.account_id] = recommendation
  31. added += 1
  32. break if added >= missing
  33. end
  34. end
  35. redis.pipelined do
  36. redis.del(key(locale))
  37. recommendations.each_value do |recommendation|
  38. redis.zadd(key(locale), recommendation.rank, recommendation.account_id)
  39. end
  40. end
  41. end
  42. end
  43. private
  44. def key(locale)
  45. "follow_recommendations:#{locale}"
  46. end
  47. end