0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 06:24:48 +08:00
discourse/app/services/group_action_logger.rb
Bannon Tanner 0acfe07701
PERF: Add Users to Group Improvements Pt. 2 (#38901)
Pt. 2 of the performance update to group add/remove users, building on
#38737

This PR moves the bulk_add/remove logic from the `Group` model into
`GroupManager`, making `GroupManager` the single owner of membership
mutation logic. `Group#bulk_add` and `Group#bulk_remove` become thin
delegators.

The controller's per-user `add_user_to_group` loop is replaced with a
single bulk `add_users_to_group` call. `GroupActionLogger` gets
`bulk_log_add_users_to_group` / `bulk_log_remove_users_from_group`
backed by `insert_all`. `DiscourseConnect` routes through `GroupManager`
instead of raw `GroupUser.create!/destroy_all`

Also moves notifications for adding users to a group to a background
job, as that was running synchronously and causing performance issues
when `notify_users: true`

There will be a Pt. 3 (#39091) that updates all callers using some
variation of `GroupUser.create` and removes callbacks from `GroupUser`
2026-04-06 09:31:50 -05:00

96 lines
2.4 KiB
Ruby
Vendored

# frozen_string_literal: true
class GroupActionLogger
def initialize(acting_user, group)
@acting_user = acting_user
@group = group
end
def log_make_user_group_owner(target_user)
GroupHistory.create!(
default_params.merge(
action: GroupHistory.actions[:make_user_group_owner],
target_user: target_user,
),
)
end
def log_remove_user_as_group_owner(target_user)
GroupHistory.create!(
default_params.merge(
action: GroupHistory.actions[:remove_user_as_group_owner],
target_user: target_user,
),
)
end
def log_add_user_to_group(target_user, subject = nil)
bulk_log_add_users_to_group([target_user.id], subject)
end
def log_remove_user_from_group(target_user, subject = nil)
bulk_log_remove_users_from_group([target_user.id], subject)
end
def bulk_log_add_users_to_group(target_user_ids, subject = nil)
bulk_log(target_user_ids, :add_user_to_group, subject)
end
def bulk_log_remove_users_from_group(target_user_ids, subject = nil)
bulk_log(target_user_ids, :remove_user_from_group, subject)
end
def log_change_group_settings
@group
.previous_changes
.except(*excluded_attributes)
.each do |attribute_name, value|
next if value[0].blank? && value[1].blank?
GroupHistory.create!(
default_params.merge(
action: GroupHistory.actions[:change_group_setting],
subject: attribute_name,
prev_value: value[0],
new_value: value[1],
),
)
end
end
def log_group_creation
@group.group_users.each do |group_user|
log_make_user_group_owner(group_user.user) if group_user.owner?
log_add_user_to_group(group_user.user)
end
end
private
def excluded_attributes
%i[bio_cooked updated_at created_at user_count]
end
def default_params
{ group: @group, acting_user: @acting_user }
end
def bulk_log(target_user_ids, action, subject = nil)
return if target_user_ids.blank?
now = Time.now
GroupHistory.insert_all!(
target_user_ids.map do |user_id|
{
group_id: @group.id,
acting_user_id: @acting_user.id,
target_user_id: user_id,
action: GroupHistory.actions[action],
created_at: now,
updated_at: now,
subject: subject,
}
end,
)
end
end