mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
PERF: Cache user badge count in user_stats table (#8610)
This means that we no longer need to run a `count()` on the user_badges table when serializing a user
This commit is contained in:
@@ -114,6 +114,7 @@ class Badge < ActiveRecord::Base
|
||||
|
||||
after_commit do
|
||||
SvgSprite.expire_cache
|
||||
UserStat.update_distinct_badge_count if saved_change_to_enabled?
|
||||
end
|
||||
|
||||
# fields that can not be edited on system badges
|
||||
|
||||
@@ -945,7 +945,7 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def badge_count
|
||||
user_badges.select('distinct badge_id').count
|
||||
user_stat&.distinct_badge_count
|
||||
end
|
||||
|
||||
def featured_user_badges(limit = 3)
|
||||
|
||||
@@ -18,11 +18,13 @@ class UserBadge < ActiveRecord::Base
|
||||
|
||||
after_create do
|
||||
Badge.increment_counter 'grant_count', self.badge_id
|
||||
UserStat.update_distinct_badge_count self.user_id
|
||||
DiscourseEvent.trigger(:user_badge_granted, self.badge_id, self.user_id)
|
||||
end
|
||||
|
||||
after_destroy do
|
||||
Badge.decrement_counter 'grant_count', self.badge_id
|
||||
UserStat.update_distinct_badge_count self.user_id
|
||||
DiscourseEvent.trigger(:user_badge_removed, self.badge_id, self.user_id)
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ class UserStat < ActiveRecord::Base
|
||||
|
||||
def self.ensure_consistency!(last_seen = 1.hour.ago)
|
||||
reset_bounce_scores
|
||||
update_distinct_badge_count
|
||||
update_view_counts(last_seen)
|
||||
update_first_unread(last_seen)
|
||||
end
|
||||
@@ -126,6 +127,29 @@ class UserStat < ActiveRecord::Base
|
||||
SQL
|
||||
end
|
||||
|
||||
def self.update_distinct_badge_count(user_id = nil)
|
||||
sql = <<~SQL
|
||||
UPDATE user_stats
|
||||
SET distinct_badge_count = x.distinct_badge_count
|
||||
FROM (
|
||||
SELECT users.id user_id, COUNT(distinct user_badges.badge_id) distinct_badge_count
|
||||
FROM users
|
||||
LEFT JOIN user_badges ON user_badges.user_id = users.id
|
||||
AND (user_badges.badge_id IN (SELECT id FROM badges WHERE enabled))
|
||||
GROUP BY users.id
|
||||
) x
|
||||
WHERE user_stats.user_id = x.user_id AND user_stats.distinct_badge_count <> x.distinct_badge_count
|
||||
SQL
|
||||
|
||||
sql = sql + " AND user_stats.user_id = #{user_id.to_i}" if user_id
|
||||
|
||||
DB.exec sql
|
||||
end
|
||||
|
||||
def update_distinct_badge_count
|
||||
self.class.update_distinct_badge_count(self.user_id)
|
||||
end
|
||||
|
||||
# topic_reply_count is a count of posts in other users' topics
|
||||
def update_topic_reply_count
|
||||
self.topic_reply_count = Topic
|
||||
|
||||
Reference in New Issue
Block a user