Fix updating account counters when account_stat is not yet created (#15108)
This commit is contained in:
		
							parent
							
								
									c01d043260
								
							
						
					
					
						commit
						f9dfbaf6b2
					
				
					 2 changed files with 38 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -21,26 +21,26 @@ class AccountStat < ApplicationRecord
 | 
			
		|||
 | 
			
		||||
  def increment_count!(key)
 | 
			
		||||
    update(attributes_for_increment(key))
 | 
			
		||||
  rescue ActiveRecord::StaleObjectError
 | 
			
		||||
  rescue ActiveRecord::StaleObjectError, ActiveRecord::RecordNotUnique
 | 
			
		||||
    begin
 | 
			
		||||
      reload_with_id
 | 
			
		||||
    rescue ActiveRecord::RecordNotFound
 | 
			
		||||
      # Nothing to do
 | 
			
		||||
    else
 | 
			
		||||
      retry
 | 
			
		||||
      return
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    retry
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def decrement_count!(key)
 | 
			
		||||
    update(key => [public_send(key) - 1, 0].max)
 | 
			
		||||
  rescue ActiveRecord::StaleObjectError
 | 
			
		||||
    update(attributes_for_decrement(key))
 | 
			
		||||
  rescue ActiveRecord::StaleObjectError, ActiveRecord::RecordNotUnique
 | 
			
		||||
    begin
 | 
			
		||||
      reload_with_id
 | 
			
		||||
    rescue ActiveRecord::RecordNotFound
 | 
			
		||||
      # Nothing to do
 | 
			
		||||
    else
 | 
			
		||||
      retry
 | 
			
		||||
      return
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    retry
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +51,13 @@ class AccountStat < ApplicationRecord
 | 
			
		|||
    attrs
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def attributes_for_decrement(key)
 | 
			
		||||
    attrs = { key => [public_send(key) - 1, 0].max }
 | 
			
		||||
    attrs
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def reload_with_id
 | 
			
		||||
    self.id = find_by!(account: account).id if new_record?
 | 
			
		||||
    self.id = self.class.find_by!(account: account).id if new_record?
 | 
			
		||||
    reload
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -817,4 +817,27 @@ RSpec.describe Account, type: :model do
 | 
			
		|||
 | 
			
		||||
  include_examples 'AccountAvatar', :account
 | 
			
		||||
  include_examples 'AccountHeader', :account
 | 
			
		||||
 | 
			
		||||
  describe '#increment_count!' do
 | 
			
		||||
    subject { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
    it 'increments the count in multi-threaded an environment when account_stat is not yet initialized' do
 | 
			
		||||
      subject
 | 
			
		||||
 | 
			
		||||
      increment_by   = 15
 | 
			
		||||
      wait_for_start = true
 | 
			
		||||
 | 
			
		||||
      threads = Array.new(increment_by) do
 | 
			
		||||
        Thread.new do
 | 
			
		||||
          true while wait_for_start
 | 
			
		||||
          Account.find(subject.id).increment_count!(:followers_count)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      wait_for_start = false
 | 
			
		||||
      threads.each(&:join)
 | 
			
		||||
 | 
			
		||||
      expect(subject.reload.followers_count).to eq 15
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue