PERF: speed up spec suite, avoid featuring topics

PERF: speed up spec suite, avoid featuring topics

Before: 6:05 After: 5:42

Featuring topics for list/categories is a very expensive operation that happened each time we created a topic. This introduces a test only bypass

diff --git a/app/models/topic.rb b/app/models/topic.rb
index 02fe6dd..8b38756 100644
--- a/app/models/topic.rb
+++ b/app/models/topic.rb
@@ -671,6 +671,8 @@ class Topic < ActiveRecord::Base
     SQL
   end
 
+  cattr_accessor :update_featured_topics
+
   def changed_to_category(new_category)
     return true if new_category.blank? || Category.exists?(topic_id: id)
     return false if new_category.id == SiteSetting.uncategorized_category_id && !SiteSetting.allow_uncategorized_topics
@@ -701,8 +703,11 @@ class Topic < ActiveRecord::Base
       end
 
       Category.where(id: new_category.id).update_all("topic_count = topic_count + 1")
-      CategoryFeaturedTopic.feature_topics_for(old_category) unless @import_mode
-      CategoryFeaturedTopic.feature_topics_for(new_category) unless @import_mode || old_category.try(:id) == new_category.id
+
+      if Topic.update_featured_topics != false
+        CategoryFeaturedTopic.feature_topics_for(old_category) unless @import_mode
+        CategoryFeaturedTopic.feature_topics_for(new_category) unless @import_mode || old_category.try(:id) == new_category.id
+      end
     end
 
     true
diff --git a/spec/models/category_list_spec.rb b/spec/models/category_list_spec.rb
index a3b5bf3..93bee27 100644
--- a/spec/models/category_list_spec.rb
+++ b/spec/models/category_list_spec.rb
@@ -4,6 +4,10 @@ require 'rails_helper'
 require 'category_list'
 
 describe CategoryList do
+  before do
+    # we need automatic updating here cause we are testing this
+    Topic.update_featured_topics = true
+  end
 
   fab!(:user) { Fabricate(:user) }
   fab!(:admin) { Fabricate(:admin) }
@@ -66,7 +70,7 @@ describe CategoryList do
     fab!(:topic_category) { Fabricate(:category, num_featured_topics: 2) }
 
     context "with a topic in a category" do
-      fab!(:topic) { Fabricate(:topic, category: topic_category) }
+      let(:topic) { Fabricate(:topic, category: topic_category) }
       let(:category) { category_list.categories.find { |c| c.id == topic_category.id } }
 
       it "should return the category" do
@@ -77,19 +81,22 @@ describe CategoryList do
     end
 
     context "with pinned topics in a category" do
-      fab!(:topic1) { Fabricate(:topic, category: topic_category, bumped_at: 8.minutes.ago) }
-      fab!(:topic2) { Fabricate(:topic, category: topic_category, bumped_at: 5.minutes.ago) }
-      fab!(:topic3) { Fabricate(:topic, category: topic_category, bumped_at: 2.minutes.ago) }
-      fab!(:pinned) { Fabricate(:topic, category: topic_category, pinned_at: 10.minutes.ago, bumped_at: 10.minutes.ago) }
-      let(:category) { category_list.categories.find { |c| c.id == topic_category.id } }
+      let!(:topic1) { Fabricate(:topic, category: topic_category, bumped_at: 8.minutes.ago) }
+      let!(:topic2) { Fabricate(:topic, category: topic_category, bumped_at: 5.minutes.ago) }
+      let!(:topic3) { Fabricate(:topic, category: topic_category, bumped_at: 2.minutes.ago) }
+      let!(:pinned) { Fabricate(:topic, category: topic_category, pinned_at: 10.minutes.ago, bumped_at: 10.minutes.ago) }
+
+      def displayable_topics
+        category_list = CategoryList.new(Guardian.new(user), include_topics: true)
+        category_list.categories.find { |c| c.id == topic_category.id }.displayable_topics.map(&:id)
+      end
 
       it "returns pinned topic first" do
-        expect(category.displayable_topics.map(&:id)).to eq([pinned.id, topic3.id])
-      end
+        expect(displayable_topics).to eq([pinned.id, topic3.id])
+
+        TopicUser.change(user.id, pinned.id, cleared_pinned_at: pinned.pinned_at + 10)
 
-      it "returns topics in bumped_at order if pinned was unpinned" do
-        PinnedCheck.stubs(:unpinned?).returns(true)
-        expect(category.displayable_topics.map(&:id)).to eq([topic3.id, topic2.id])
+        expect(displayable_topics).to eq([topic3.id, topic2.id])
       end
     end
 
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 47c267a..3d5a92d 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -117,6 +117,9 @@ module TestSetup
       $test_cleanup_callbacks = nil
     end
 
+    # in test this is very expensive, we explicitly enable when needed
+    Topic.update_featured_topics = false
+
     # Running jobs are expensive and most of our tests are not concern with
     # code that runs inside jobs. run_later! means they are put on the redis
     # queue and never processed.

GitHub sha: 0ab6c6e2

1 Like