Browse Source

Fix error when trying to update counters for statuses that are gone (#8251)

Eugen Rochko 5 years ago
parent
commit
d010816ba8
3 changed files with 29 additions and 6 deletions
  1. 2 2
      app/models/favourite.rb
  2. 6 4
      app/models/status.rb
  3. 21 0
      spec/models/status_spec.rb

+ 2 - 2
app/models/favourite.rb

@@ -32,11 +32,11 @@ class Favourite < ApplicationRecord
   private
 
   def increment_cache_counters
-    status.increment_count!(:favourites_count)
+    status&.increment_count!(:favourites_count)
   end
 
   def decrement_cache_counters
     return if association(:status).loaded? && (status.marked_for_destruction? || status.marked_for_mass_destruction?)
-    status.decrement_count!(:favourites_count)
+    status&.decrement_count!(:favourites_count)
   end
 end

+ 6 - 4
app/models/status.rb

@@ -396,6 +396,8 @@ class Status < ApplicationRecord
   private
 
   def update_status_stat!(attrs)
+    return if marked_for_destruction? || destroyed?
+
     record = status_stat || build_status_stat
     record.update(attrs)
   end
@@ -456,8 +458,8 @@ class Status < ApplicationRecord
       Account.where(id: account_id).update_all('statuses_count = COALESCE(statuses_count, 0) + 1')
     end
 
-    reblog.increment_count!(:reblogs_count) if reblog?
-    thread.increment_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?)
+    reblog&.increment_count!(:reblogs_count) if reblog?
+    thread&.increment_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?)
   end
 
   def decrement_counter_caches
@@ -469,7 +471,7 @@ class Status < ApplicationRecord
       Account.where(id: account_id).update_all('statuses_count = GREATEST(COALESCE(statuses_count, 0) - 1, 0)')
     end
 
-    reblog.decrement_count!(:reblogs_count) if reblog?
-    thread.decrement_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?)
+    reblog&.decrement_count!(:reblogs_count) if reblog?
+    thread&.decrement_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?)
   end
 end

+ 21 - 0
spec/models/status_spec.rb

@@ -182,6 +182,27 @@ RSpec.describe Status, type: :model do
       reblog.destroy
       expect(subject.reblogs_count).to eq 0
     end
+
+    it 'does not fail when original is deleted before reblog' do
+      reblog = Fabricate(:status, account: bob, reblog: subject)
+      expect(subject.reblogs_count).to eq 1
+      expect { subject.destroy }.to_not raise_error
+      expect(Status.find_by(id: reblog.id)).to be_nil
+    end
+  end
+
+  describe '#replies_count' do
+    it 'is the number of replies' do
+      reply = Fabricate(:status, account: bob, thread: subject)
+      expect(subject.replies_count).to eq 1
+    end
+
+    it 'is decremented when reply is removed' do
+      reply = Fabricate(:status, account: bob, thread: subject)
+      expect(subject.replies_count).to eq 1
+      reply.destroy
+      expect(subject.replies_count).to eq 0
+    end
   end
 
   describe '#favourites_count' do