PERF: avoid N+1 on category load

PERF: avoid N+1 on category load

after_find is a very risky callback cause it can impact how read perf works. In this case it was loading a custom field on category which triggered an N+1 on a fresh load of a site.

This amends it so we do the repair before save

diff --git a/plugin.rb b/plugin.rb
index f4df820..cb402b2 100755
--- a/plugin.rb
+++ b/plugin.rb
@@ -115,21 +115,16 @@ after_initialize do
     end
 
     after_save :reset_voting_cache
-    after_find :track_voting_enabled
-    after_save :reclaim_release_votes
+    before_save :reclaim_release_votes
 
     protected
     def reset_voting_cache
       ::Category.reset_voting_cache
     end
 
-    def track_voting_enabled
-      return unless SiteSetting.voting_enabled
-      @old_enable_voting = custom_fields[::DiscourseVoting::VOTING_ENABLED]
-    end
-
     def reclaim_release_votes
-      return unless SiteSetting.voting_enabled
+      return if self.new_record?
+      return if !SiteSetting.voting_enabled
 
       aliases = {
         votes: DiscourseVoting::VOTES,
@@ -137,7 +132,13 @@ after_initialize do
         category_id: id
       }
 
-      was_enabled = @old_enable_voting
+      was_enabled = CategoryCustomField.where(
+        "name = :name AND value similar to :value AND category_id = :id",
+        id: id,
+        name: ::DiscourseVoting::VOTING_ENABLED,
+        value: '(t|T|1)%'
+      ).exists?
+
       is_enabled = custom_fields[::DiscourseVoting::VOTING_ENABLED]
 
       if !was_enabled && is_enabled
diff --git a/spec/ensure_consistency_spec.rb b/spec/ensure_consistency_spec.rb
index df2c2e8..78d3d6e 100644
--- a/spec/ensure_consistency_spec.rb
+++ b/spec/ensure_consistency_spec.rb
@@ -32,7 +32,7 @@ describe "Voting Consistency" do
     Jobs::VotingEnsureConsistency.new.execute_onceoff(nil)
 
     no_vote_topic.reload
-    expect(no_vote_topic.custom_fields).to eq("random1" => "random")
+    expect(no_vote_topic.custom_fields["random1"]).to eq("random")
 
     user.reload
     expect(user.custom_fields).to eq("votes" => [one_vote_topic.id, two_vote_topic.id])
@@ -41,10 +41,12 @@ describe "Voting Consistency" do
     expect(user2.custom_fields).to eq("votes" => [two_vote_topic.id])
 
     one_vote_topic.reload
-    expect(one_vote_topic.custom_fields).to eq("vote_count" => 1, "random2" => "random")
+    expect(one_vote_topic.custom_fields["vote_count"]).to eq(1)
+    expect(one_vote_topic.custom_fields["random2"]).to eq("random")
 
     two_vote_topic.reload
-    expect(two_vote_topic.custom_fields).to eq("vote_count" => 2, "random3" => "random")
+    expect(two_vote_topic.custom_fields["vote_count"]).to eq(2)
+    expect(two_vote_topic.custom_fields["random3"]).to eq("random")
 
   end
 end

GitHub sha: 9b4f233b

1 Like