mirror of
https://github.com/discourse/discourse.git
synced 2025-05-28 13:51:18 +08:00
PERF: Update Group#user_count
counter cache outside DB transaction (#19256)
While load testing our user creation code path in production, we identified that executing the DB statement to update the `Group#user_count` column within a transaction is creating a bottleneck for us. This is because the creation of a user and addition of the user to the relevant groups are done in a transaction. When we execute the DB statement to update `Group#user_count` for the relevant group, a row level lock is held until the transaction completes. This row level lock acts like a global lock when the server is creating users that will be added to the same group in quick succession. Instead of updating the counter cache within a transaction which the default ActiveRecord `counter_cache` option does, we simply update the counter cache outside of the committing transaction. Co-authored-by: Rafael dos Santos Silva <xfalcox@gmail.com> Co-authored-by: Rafael dos Santos Silva <xfalcox@gmail.com>
This commit is contained in:

committed by
GitHub

parent
9f022112e3
commit
7c321d3aad
@ -1,6 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe GroupUser do
|
||||
fab!(:group) { Fabricate(:group) }
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
describe 'callbacks' do
|
||||
it "increments and decrements `Group#user_count` when record is created and destroyed" do
|
||||
group_user = GroupUser.new(user: user, group: group)
|
||||
|
||||
expect do
|
||||
group_user.save!
|
||||
end.to change { group.reload.user_count }.from(0).to(1)
|
||||
|
||||
expect do
|
||||
group_user.destroy!
|
||||
end.to change { group.reload.user_count }.from(1).to(0)
|
||||
end
|
||||
end
|
||||
|
||||
it 'correctly sets notification level' do
|
||||
moderator = Fabricate(:moderator)
|
||||
|
Reference in New Issue
Block a user