Skip to content

Commit 12743c4

Browse files
committed
Updated the RefreshUser job to use the ID. Added recurring RefreshStaleUsers worker to update user facts. Updated logging and structure of facts to ensure all the facts are refreshed even if another fact fails.
1 parent aa18369 commit 12743c4

File tree

9 files changed

+118
-40
lines changed

9 files changed

+118
-40
lines changed

app/clock.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
ActivatePendingUsersWorker.perform_async
1212
end
1313

14-
every(1.day, 'award:fresh:stale', at: '00:00') {}
14+
every(1.day, 'award:refresh:stale', at: '00:00') do
15+
RefreshStaleUsersWorker.perform_async
16+
end
17+
1518
every(1.day, 'cleanup:protips:associate_zombie_upvotes', at: '00:00') {}
1619
every(1.day, 'clear_expired_sessions', at: '00:00') {}
1720
every(1.day, 'facts:system', at: '00:00') {}

app/controllers/application_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def show_achievement
124124
def record_visit
125125
if viewing_user
126126
if viewing_user == current_user && (viewing_user.try(:last_request_at) || 1.week.ago) < 1.day.ago && viewing_user.active? && viewing_user.last_refresh_at < 2.days.ago
127-
RefreshUserJob.perform_async(current_user.username)
127+
RefreshUserJob.perform_async(current_user.id)
128128
end
129129
viewing_user.visited!
130130
Usage.page_view(viewing_user.id) unless viewing_user.admin?

app/controllers/redemptions_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def show
66
if current_user.pending?
77
current_user.activate
88
NotifierMailer.welcome_email(current_user.username).deliver
9-
RefreshUserJob.perform_async(current_user.username)
9+
RefreshUserJob.perform_async(current_user.id)
1010
end
1111
redirect_to(destination_url)
1212
else

app/controllers/users_controller.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,9 @@ def autocomplete
143143
end
144144

145145
def refresh
146-
147146
refresh_params = params.permit(:username)
148-
149-
RefreshUserJob.perform_async(refresh_params[:username], true)
147+
user = User.with_username(refresh_params[:username])
148+
RefreshUserJob.perform_async(user.id, true)
150149
flash[:notice] = "Queued #{refresh_params[:username]} for a refresh"
151150
redirect_to :back
152151
end

app/jobs/refresh_user_job.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
class RefreshUserJob
22
include Sidekiq::Worker
3+
sidekiq_options queue: :low
34

4-
def perform(username, full=false)
5+
def perform(user_id, full=false)
56
return if Rails.env.test?
6-
user = User.find_by_username(username)
7+
8+
user = User.find(user_id)
79

810
if user.github_id
911
user.destroy_github_cache
@@ -17,7 +19,6 @@ def perform(username, full=false)
1719
user.add_skills_for_unbadgified_facts
1820

1921
user.calculate_score!
20-
2122
ensure
2223
user.touch(:last_refresh_at)
2324
user.destroy_github_cache

app/models/concerns/user_facts.rb

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
module UserFacts
22
extend ActiveSupport::Concern
3+
34
included do
45
def build_facts(all)
56
since = (all ? Time.at(0) : self.last_refresh_at)
7+
68
build_github_facts(since)
79
build_lanyrd_facts
810
build_linkedin_facts
@@ -12,32 +14,89 @@ def build_facts(all)
1214
end
1315

1416
def build_speakerdeck_facts
15-
Speakerdeck.new(speakerdeck).facts if speakerdeck_identity
17+
Rails.logger.info("[FACTS] Building SpeakerDeck facts for #{username}")
18+
begin
19+
if speakerdeck_identity
20+
Speakerdeck.new(speakerdeck).facts
21+
Rails.logger.info("[FACTS] Processed SpeakerDeck facts for #{username}")
22+
else
23+
Rails.logger.info("[FACTS] Skipped SpeakerDeck facts for #{username}")
24+
end
25+
rescue => ex
26+
Rails.logger.error("[FACTS] Unable to build SpeakerDeck facts due to '#{ex}' >>\n#{ex.backtrace.join("\n ")}")
27+
end
1628
end
1729

1830
def build_slideshare_facts
19-
Slideshare.new(slideshare).facts if slideshare_identity
31+
Rails.logger.info("[FACTS] Building SlideShare facts for #{username}")
32+
begin
33+
if slideshare_identity
34+
Slideshare.new(slideshare).facts
35+
Rails.logger.info("[FACTS] Processed Slideshare facts for #{username}")
36+
else
37+
Rails.logger.info("[FACTS] Skipped SlideShare facts for #{username}")
38+
end
39+
rescue => ex
40+
Rails.logger.error("[FACTS] Unable to build SlideShare facts due to '#{ex}' >>\n#{ex.backtrace.join("\n ")}")
41+
end
2042
end
2143

2244
def build_lanyrd_facts
23-
Lanyrd.new(twitter).facts if lanyrd_identity
45+
Rails.logger.info("[FACTS] Building Lanyrd facts for #{username}")
46+
begin
47+
if lanyrd_identity
48+
Lanyrd.new(twitter).facts
49+
Rails.logger.info("[FACTS] Processed Lanyrd facts for #{username}")
50+
else
51+
Rails.logger.info("[FACTS] Skipped Lanyrd facts for #{username}")
52+
end
53+
rescue => ex
54+
Rails.logger.error("[FACTS] Unable to build Lanyrd facts due to '#{ex}' >>\n#{ex.backtrace.join("\n ")}")
55+
end
2456
end
2557

2658
def build_bitbucket_facts
27-
Bitbucket::V1.new(bitbucket).update_facts! unless bitbucket.blank?
59+
Rails.logger.info("[FACTS] Building Bitbucket facts for #{username}")
60+
begin
61+
unless bitbucket.blank?
62+
Bitbucket::V1.new(bitbucket).update_facts!
63+
Rails.logger.info("[FACTS] Processed Bitbucket facts for #{username}")
64+
else
65+
Rails.logger.info("[FACTS] Skipped Bitbucket facts for #{username}")
66+
end
67+
rescue => ex
68+
Rails.logger.error("[FACTS] Unable to build Bitbucket facts due to '#{ex}' >>\n#{ex.backtrace.join("\n ")}")
69+
end
2870
end
2971

3072
def build_github_facts(since=Time.at(0))
31-
GithubProfile.for_username(github, since).facts if github_identity and github_failures == 0
73+
Rails.logger.info("[FACTS] Building GitHub facts for #{username}")
74+
begin
75+
if github_identity && github_failures == 0
76+
GithubProfile.for_username(github, since).facts
77+
Rails.logger.info("[FACTS] Processed GitHub facts for #{username}")
78+
else
79+
Rails.logger.info("[FACTS] Skipped GitHub facts for #{username}")
80+
end
81+
rescue => ex
82+
Rails.logger.error("[FACTS] Unable to build GitHub facts due to '#{ex}' >>\n#{ex.backtrace.join("\n ")}")
83+
end
3284
end
3385

3486
def build_linkedin_facts
35-
LinkedInStream.new(linkedin_token + '::' + linkedin_secret).facts if linkedin_identity
36-
rescue => e
37-
logger.error(e.message + "\n " + e.backtrace.join("\n "))
87+
Rails.logger.info("[FACTS] Building LinkedIn facts for #{username}")
88+
begin
89+
if linkedin_identity
90+
LinkedInStream.new(linkedin_token + '::' + linkedin_secret).facts
91+
Rails.logger.info("[FACTS] Processed LinkedIn facts for #{username}")
92+
else
93+
Rails.logger.info("[FACTS] Skipped LinkedIn facts for #{username}")
94+
end
95+
rescue => ex
96+
Rails.logger.error("[FACTS] Unable to build LinkedIn facts due to '#{ex}' >>\n#{ex.backtrace.join("\n ")}")
97+
end
3898
end
3999

40-
41100
def repo_facts
42101
self.facts.select { |fact| fact.tagged?('personal', 'repo', 'original') }
43102
end
@@ -58,6 +117,5 @@ def speakerdeck_identity
58117
def slideshare_identity
59118
"slideshare:#{slideshare}" if slideshare
60119
end
61-
62120
end
63-
end
121+
end

app/models/user.rb

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,17 @@ def near
115115
def self.with_username(username, provider = :username)
116116
return nil if username.nil?
117117
sql_injection_safe_where_clause = case provider.to_s
118-
when 'username', ''
119-
'username'
120-
when 'linkedin'
121-
'linkedin'
122-
when 'twitter'
123-
'twitter'
124-
when 'github'
125-
'github'
126-
else
127-
#A user could malicously pass in a provider, thats why we do the string matching above
128-
raise "Unkown provider type specified, unable to find user by username"
118+
when 'username', ''
119+
'username'
120+
when 'linkedin'
121+
'linkedin'
122+
when 'twitter'
123+
'twitter'
124+
when 'github'
125+
'github'
126+
else
127+
#A user could malicously pass in a provider, thats why we do the string matching above
128+
raise "Unkown provider type specified, unable to find user by username"
129129
end
130130
where(["UPPER(#{sql_injection_safe_where_clause}) = UPPER(?)", username]).first
131131
end
@@ -328,7 +328,7 @@ def clear_facts!
328328
skills.each { |skill| skill.apply_facts && skill.save }
329329
self.github_failures = 0
330330
save!
331-
RefreshUserJob.perform_async(username, true)
331+
RefreshUserJob.perform_async(id, true)
332332
end
333333

334334

@@ -344,11 +344,6 @@ def num_linked_accounts
344344
LINKABLE_PROVIDERS.map { |provider| self.send("#{provider}_identity") }.compact.count
345345
end
346346

347-
348-
349-
350-
351-
352347
def check_achievements!(badge_list = Badges.all)
353348
BadgeBase.award!(self, badge_list)
354349
touch(:achievements_checked_at)
@@ -476,8 +471,8 @@ def calculate_score!
476471
score = ((endorsers.count / 6.0) + (achievement_score) + (times_spoken / 1.50) + (times_attended / 4.0)) * activitiy_multipler
477472
self.score_cache = [score - penalty, 0.0].max
478473
save!
479-
rescue
480-
Rails.logger.error "Failed cacluating score for #{username}" if ENV['DEBUG']
474+
rescue => ex
475+
Rails.logger.error("Failed cacluating score for #{username} due to '#{ex}' >>\n#{ex.backtrace.join("\n ")}")
481476
end
482477

483478
def like_value
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class RefreshStaleUsersWorker
2+
include Sidekiq::Worker
3+
sidekiq_options queue: :critical
4+
5+
def perform
6+
user_records.find_each(batch_size: 1000) do |user|
7+
RefreshUserJob.perform_in(minutes, user.id)
8+
end
9+
end
10+
11+
def minutes
12+
# spread the execution of the spawned jobs across the next 24 hours
13+
Random.rand(0..1439).minutes
14+
end
15+
16+
def user_records
17+
User.
18+
active.
19+
where('last_refresh_at < ?', 5.days.ago).
20+
order('last_refresh_at ASC').
21+
select(:id)
22+
end
23+
end

spec/controllers/emails_controller_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,4 @@
3232
expect(user.notify_on_award).to eq(true)
3333
expect(user.receive_newsletter).to eq(false)
3434
end
35-
3635
end

0 commit comments

Comments
 (0)