Fix updating account counters when account_stat is not yet created (#15108)

master
Eugen Rochko 4 years ago committed by GitHub
parent 2b63c62c57
commit 337dc6e0ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      app/models/account_stat.rb
  2. 23
      spec/models/account_spec.rb

@ -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…
Cancel
Save