PERF: cook message in background (#24227)

This commit starts from a simple observation: cooking messages on the hot path can be slow. Especially with a lot of mentions.

To move cooking from the hot path, this commit has made the following changes:

- updating cooked, inserting mentions and notifying user of new mentions has been moved inside the `process_message` job. It happens right after the `Chat::MessageProcessor` run, which is where the cooking happens.
- the similar existing code in `rebake!` has also been moved to rely on the `process_message`job only
- refactored `create_mentions` and `update_mentions` into one single `upsert_mentions` which can be called invariably
- allows services to decide if their job is ran inline or later. It avoids to need to know you have to use `Jobs.run_immediately!` in this case, in tests it will be inline per default
- made various frontend changes to make the chat-channel component lifecycle clearer. we had to handle `did-update @channel` which was super awkward and creating bugs with listeners which the changes of the PR made clear in failing specs
- adds a new `-processed` (and `-not-processed`) class on the chat message, this is made to have a good lifecyle hook in system specs
This commit is contained in:
Joffrey JAFFEUX
2023-11-06 15:45:30 +01:00
committed by GitHub
parent 4425e99bf9
commit 90efdd7f9d
46 changed files with 388 additions and 394 deletions

View File

@ -12,8 +12,8 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
chat_system_bootstrap
end
def create_message(text: "this is fine", channel:, creator: Fabricate(:user))
Fabricate(:chat_message_with_service, chat_channel: channel, message: text, user: creator)
def create_message(channel, text: "this is fine", user: Fabricate(:user))
Fabricate(:chat_message_with_service, chat_channel: channel, message: text, user: user)
end
context "as a user" do
@ -30,13 +30,9 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
context "when not member of the channel" do
context "when a message is created" do
it "doesn't show anything" do
Jobs.run_immediately!
visit("/chat")
using_session(:user_1) do |session|
create_message(channel: channel_1, creator: user_1)
session.quit
end
create_message(channel_1, user: user_1)
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
expect(page).to have_no_css(channel_index_page.channel_row_selector(channel_1))
@ -58,13 +54,9 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
end
it "doesn’t show indicator in header" do
Jobs.run_immediately!
visit("/chat")
using_session(:user_1) do |session|
create_message(channel: channel_1, creator: user_1)
session.quit
end
create_message(channel_1, user: user_1)
expect(page).to have_css(".do-not-disturb-background")
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
@ -76,13 +68,9 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
context "when a message is created" do
it "doesn't show anything" do
Jobs.run_immediately!
visit("/chat")
using_session(:user_1) do |session|
create_message(channel: channel_1, creator: user_1)
session.quit
end
create_message(channel_1, user: user_1)
expect(page).to have_no_css(".chat-header-icon .chat-channel-unread-indicator")
expect(channel_index_page).to have_no_unread_channel(channel_1)
@ -92,13 +80,9 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
context "when a message is created" do
it "correctly renders notifications" do
Jobs.run_immediately!
visit("/chat")
using_session(:user_1) do |session|
create_message(channel: channel_1, creator: user_1)
session.quit
end
create_message(channel_1, user: user_1)
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
expect(channel_index_page).to have_unread_channel(channel_1)
@ -110,13 +94,12 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
Jobs.run_immediately!
visit("/chat")
using_session(:user_1) do
create_message(
channel: channel_1,
creator: user_1,
text: "hello @#{current_user.username} what's up?",
)
end
create_message(
channel_1,
user: user_1,
text: "hello @#{current_user.username} what's up?",
)
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator")
expect(channel_index_page).to have_unread_channel(channel_1, count: 1)
@ -135,13 +118,9 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
context "when a message is created" do
it "correctly renders notifications" do
Jobs.run_immediately!
visit("/chat")
using_session(:user_1) do |session|
create_message(channel: dm_channel_1, creator: user_1)
session.quit
end
create_message(dm_channel_1, user: user_1)
expect(page).to have_css(
".chat-header-icon .chat-channel-unread-indicator",
@ -150,10 +129,7 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
)
expect(channel_index_page).to have_unread_channel(dm_channel_1, wait: 25)
using_session(:user_1) do |session|
create_message(channel: dm_channel_1, creator: user_1)
session.quit
end
create_message(dm_channel_1, user: user_1)
expect(page).to have_css(
".chat-header-icon .chat-channel-unread-indicator",
@ -163,8 +139,6 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
end
it "reorders channels" do
Jobs.run_immediately!
visit("/chat")
expect(page).to have_css(
@ -174,10 +148,7 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
".chat-channel-row:nth-child(2)[data-chat-channel-id=\"#{dm_channel_2.id}\"]",
)
using_session(:user_1) do |session|
create_message(channel: dm_channel_2, creator: user_2)
session.quit
end
create_message(dm_channel_2, user: user_2)
expect(page).to have_css(
".chat-channel-row:nth-child(1)[data-chat-channel-id=\"#{dm_channel_2.id}\"]",
@ -202,21 +173,14 @@ RSpec.describe "Message notifications - mobile", type: :system, mobile: true do
context "when messages are created" do
it "correctly renders notifications" do
Jobs.run_immediately!
visit("/chat")
using_session(:user_1) do |session|
create_message(channel: channel_1, creator: user_1)
session.quit
end
create_message(channel_1, user: user_1)
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "")
expect(channel_index_page).to have_unread_channel(channel_1)
using_session(:user_1) do |session|
create_message(channel: dm_channel_1, creator: user_1)
session.quit
end
create_message(dm_channel_1, user: user_1)
expect(channel_index_page).to have_unread_channel(dm_channel_1)
expect(page).to have_css(".chat-header-icon .chat-channel-unread-indicator", text: "1")