discourse/plugins/chat/spec/jobs/scheduled/auto_join_users_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

74 lines
2.5 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
describe Jobs::Chat::AutoJoinUsers do
subject(:job) { described_class.new }
fab!(:channel) { Fabricate(:category_channel, auto_join_users: true) }
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
fab!(:user) { Fabricate(:user, last_seen_at: 1.minute.ago, trust_level: 1) }
fab!(:group)
fab!(:user_without_chat) do
user = Fabricate(:user)
user.user_option.update!(chat_enabled: false)
user
end
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
fab!(:staged_user) { Fabricate(:user, staged: true) }
fab!(:suspended_user) { Fabricate(:user, suspended_till: 1.day.from_now) }
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
fab!(:silenced_user) { Fabricate(:user, silenced_till: 2.day.from_now) }
fab!(:inactive_user) { Fabricate(:user, active: false) }
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
fab!(:anonymous_user) do
# When using the `anonymous` fabricator, the `::Chat::AutoJoinChannels` is called in the
# `on(:user_added_to_group)` hook **before** the `anonymous_user` record is created in the `after_create` hook
anon = Fabricate(:user)
AnonymousUser.create!(user: anon, master_user: anon, active: true)
anon
end
before { Jobs.run_immediately! }
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
it "does not auto join users without permissions" do
channel.category.read_restricted = true
channel.category.set_permissions(group => :full)
channel.category.save!
job.execute({})
membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
expect(membership).to be_nil
GroupUser.create!(group: group, user: user)
job.execute({})
membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
expect(membership).to_not be_nil
end
it "works for simple workflows" do
# this is just to avoid test fragility, we should always have negative users
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
_bot = Fabricate(:user, id: [User.minimum(:id), 0].min - 1)
job.execute({})
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
# excludes bot / chat disabled / inactive / staged / suspended / silenced / anonymous users
expect(
Chat::UserChatChannelMembership.where(chat_channel: channel).pluck(:user_id),
PERF: auto join & leave chat channels (#29193) Chat channels that are linked to a category can be set to automatically join users. This is handled by subscribing to the following events - group_destroyed - user_seen - user_confirmed_email - user_added_to_group - user_removed_from_group - category_updated - site_setting_changed (for `chat_allowed_groups`) As well as a - hourly background job (`AutoJoinUsers`) - `CreateCategoryChannel` service - `UpdateChannel` service There was however two issues with the current implementation 1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system 2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel. Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened. In the making of these classes, a few bugs were encountered and fixed, notably - A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting - A category that has no associated "category groups" is only accessible to staff members (and not "Everyone") - A silenced user should not be able to automatically join channels - We should not attempt to automatically join users to deleted chat channels - There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users Internal - t/135259 & t/70607 * DEV: add specs for auto join/leave channels services * DEV: less hacky specs * DEV: no instance variables in specs
2024-11-11 23:00:59 -05:00
).to contain_exactly(user.id)
membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
expect(membership.following).to eq(true)
membership.update!(following: false)
job.execute({})
membership.reload
expect(membership.following).to eq(false)
channel = Fabricate(:category_channel, auto_join_users: false)
job.execute({})
membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
expect(membership).to be_nil
end
end