blob: 084619cbd93aa6ee496c8a33c8f1294487f5e047 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
# frozen_string_literal: true
class Scheduler::FollowRecommendationsScheduler
include Sidekiq::Worker
include Redisable
sidekiq_options retry: 0
# The maximum number of accounts that can be requested in one page from the
# API is 80, and the suggestions API does not allow pagination. This number
# leaves some room for accounts being filtered during live access
SET_SIZE = 100
def perform
# Maintaining a materialized view speeds-up subsequent queries significantly
AccountSummary.refresh
FollowRecommendation.refresh
fallback_recommendations = FollowRecommendation.order(rank: :desc).limit(SET_SIZE)
I18n.available_locales.map { |locale| locale.to_s.split(/[_-]/).first }.uniq.each do |locale|
recommendations = begin
if AccountSummary.safe.filtered.localized(locale).exists? # We can skip the work if no accounts with that language exist
FollowRecommendation.localized(locale).order(rank: :desc).limit(SET_SIZE).map { |recommendation| [recommendation.account_id, recommendation.rank] }
else
[]
end
end
# Use language-agnostic results if there are not enough language-specific ones
missing = SET_SIZE - recommendations.size
if missing.positive? && fallback_recommendations.size.positive?
max_fallback_rank = fallback_recommendations.first.rank || 0
# Language-specific results should be above language-agnostic ones,
# otherwise language-agnostic ones will always overshadow them
recommendations.map! { |(account_id, rank)| [account_id, rank + max_fallback_rank] }
added = 0
fallback_recommendations.each do |recommendation|
next if recommendations.any? { |(account_id, _)| account_id == recommendation.account_id }
recommendations << [recommendation.account_id, recommendation.rank]
added += 1
break if added >= missing
end
end
redis.pipelined do
redis.del(key(locale))
recommendations.each do |(account_id, rank)|
redis.zadd(key(locale), rank, account_id)
end
end
end
end
private
def key(locale)
"follow_recommendations:#{locale}"
end
end
|