PERF: stop mucking with user stats every 15 minutes

(pushed to twice daily)
This commit is contained in:
Sam 2014-08-07 14:20:42 +10:00
parent b5045a005f
commit cd22b6158c
7 changed files with 26 additions and 22 deletions

View File

@ -10,6 +10,8 @@ module Jobs
Notification.ensure_consistency!
UserAction.ensure_consistency!
UserBadge.ensure_consistency!
# ensure consistent
UserStat.update_view_counts(13.hours.ago)
end
end
end

View File

@ -12,9 +12,6 @@ module Jobs
# Feature topics in categories
CategoryFeaturedTopic.feature_topics
# Update view counts for users
UserStat.update_view_counts
# Update the scores of posts
ScoreCalculator.new.calculate(1.day.ago)

View File

@ -39,7 +39,7 @@ class PostTiming < ActiveRecord::Base
args)
if rows == 0
Post.where(['topic_id = :topic_id and post_number = :post_number', args]).update_all 'reads = reads + 1'
exec_sql("INSERT INTO post_timings (topic_id, user_id, post_number, msecs)
SELECT :topic_id, :user_id, :post_number, :msecs
WHERE NOT EXISTS(SELECT 1 FROM post_timings
@ -48,6 +48,8 @@ class PostTiming < ActiveRecord::Base
AND post_number = :post_number)",
args)
Post.where(['topic_id = :topic_id and post_number = :post_number', args]).update_all 'reads = reads + 1'
UserStat.where(user_id: args[:user_id]).update_all 'posts_read_count = posts_read_count + 1'
end
end

View File

@ -42,6 +42,7 @@ class TopicViewItem < ActiveRecord::Base
if result.cmd_tuples > 0
Topic.where(id: topic_id).update_all 'views = views + 1'
UserStat.where(user_id: user_id).update_all 'topics_entered = topics_entered + 1' if user_id
end
# Update the views count in the parent, if it exists.

View File

@ -4,7 +4,7 @@ class UserStat < ActiveRecord::Base
after_save :trigger_badges
# Updates the denormalized view counts for all users
def self.update_view_counts
def self.update_view_counts(last_seen = 1.hour.ago)
# NOTE: we only update the counts for users we have seen in the last hour
# this avoids a very expensive query that may run on the entire user base
@ -22,7 +22,7 @@ class UserStat < ActiveRecord::Base
WHERE
X.user_id = user_stats.user_id AND
X.c <> topics_entered
", seen_at: 1.hour.ago
", seen_at: last_seen
# Update denormalzied posts_read_count
exec_sql "UPDATE user_stats SET posts_read_count = X.c
@ -35,7 +35,7 @@ class UserStat < ActiveRecord::Base
GROUP BY pt.user_id) AS X
WHERE X.user_id = user_stats.user_id AND
X.c <> posts_read_count
", seen_at: 1.hour.ago
", seen_at: last_seen
end
def update_topic_reply_count

View File

@ -93,12 +93,6 @@ describe PostTiming do
@timing_attrs = {msecs: 1234, topic_id: @post.topic_id, user_id: @coding_horror.id, post_number: @post.post_number}
end
it 'creates a post timing record' do
lambda {
PostTiming.record_timing(@timing_attrs)
}.should change(PostTiming, :count).by(1)
end
it 'adds a view to the post' do
lambda {
PostTiming.record_timing(@timing_attrs)
@ -107,19 +101,17 @@ describe PostTiming do
end
describe 'multiple calls' do
before do
it 'correctly works' do
PostTiming.record_timing(@timing_attrs)
PostTiming.record_timing(@timing_attrs)
@timing = PostTiming.find_by(topic_id: @post.topic_id, user_id: @coding_horror.id, post_number: @post.post_number)
timing = PostTiming.find_by(topic_id: @post.topic_id, user_id: @coding_horror.id, post_number: @post.post_number)
timing.should be_present
timing.msecs.should == 2468
@coding_horror.user_stat.posts_read_count.should == 1
end
it 'creates a timing record' do
@timing.should be_present
end
it 'sums the msecs together' do
@timing.msecs.should == 2468
end
end
describe 'avg times' do

View File

@ -17,4 +17,14 @@ describe TopicViewItem do
TopicViewItem.count.should == 3
end
it "increases a users view count" do
user = Fabricate(:user)
add(1, "1.1.1.1", user.id)
add(1, "1.1.1.1", user.id)
user.user_stat.reload
user.user_stat.topics_entered.should == 1
end
end