From f5a3be750c99f3ba89126c61dda51df0571dbe4e Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Tue, 19 Dec 2017 21:42:29 -0500 Subject: [PATCH] PERF: add option to limit how many categories are processed in one call to CategoryFeaturedTopic.feature_topics (#5446) --- app/jobs/scheduled/periodical_updates.rb | 2 +- app/models/category_featured_topic.rb | 26 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/app/jobs/scheduled/periodical_updates.rb b/app/jobs/scheduled/periodical_updates.rb index a1223434825..ca54bf3b181 100644 --- a/app/jobs/scheduled/periodical_updates.rb +++ b/app/jobs/scheduled/periodical_updates.rb @@ -17,7 +17,7 @@ module Jobs def execute(args) # Feature topics in categories - CategoryFeaturedTopic.feature_topics + CategoryFeaturedTopic.feature_topics(batched: true) # Update the scores of posts args = { min_topic_age: 1.day.ago } diff --git a/app/models/category_featured_topic.rb b/app/models/category_featured_topic.rb index 4b1f92628de..f5496cd7896 100644 --- a/app/models/category_featured_topic.rb +++ b/app/models/category_featured_topic.rb @@ -2,13 +2,33 @@ class CategoryFeaturedTopic < ActiveRecord::Base belongs_to :category belongs_to :topic - # Populates the category featured topics - def self.feature_topics + NEXT_CATEGORY_ID_KEY = 'category-featured-topic:next-category-id'.freeze + BATCH_SIZE = 100 + + # Populates the category featured topics. + def self.feature_topics(batched: false) current = {} CategoryFeaturedTopic.select(:topic_id, :category_id).order(:rank).each do |f| (current[f.category_id] ||= []) << f.topic_id end - Category.select(:id, :topic_id, :num_featured_topics).find_each do |c| + + next_category_id = batched ? ($redis.get(NEXT_CATEGORY_ID_KEY) || 0) : 0 + + categories = Category.select(:id, :topic_id, :num_featured_topics) + .where('id >= ?', next_category_id) + .order('id ASC') + .limit(BATCH_SIZE) + + if batched + if categories.count == BATCH_SIZE + next_id = Category.where('id > ?', categories.last.id).order('id asc').limit(1).pluck(:id)[0] + next_id ? $redis.setex(NEXT_CATEGORY_ID_KEY, 1.day, next_id) : $redis.del(NEXT_CATEGORY_ID_KEY) + else + $redis.del(NEXT_CATEGORY_ID_KEY) + end + end + + categories.find_each do |c| CategoryFeaturedTopic.feature_topics_for(c, current[c.id] || []) end end