FEATURE: Better thread reply counter cache (#21108)

This commit introduces a redis cache over the top of the thread
replies_count DB cache, so that we can quickly and accurately
increment/decrement the reply count for all users and not have
to constantly update the database-level count. This is done so
the UI can have a count that is displayed to the users on each
thread indicator, that appears to live update on each chat
message create/trash/recover inside the thread.

This commit also introduces the `Chat::RestoreMessage` service
and moves the restore endpoint into the `Api::ChannelMessages`
controller as part of incremental migrations to move things out
of ChatController.

Finally, this commit refactors `Chat::Publisher` to be less repetitive
with its `MessageBus` sending code.
This commit is contained in:
Martin Brennan
2023-04-18 14:01:01 +10:00
committed by GitHub
parent b8583f274d
commit 180e3e11d1
22 changed files with 601 additions and 231 deletions

View File

@ -559,82 +559,6 @@ RSpec.describe Chat::ChatController do
end
end
RSpec.shared_examples "chat_message_restoration" do
it "doesn't allow a user to restore another user's message" do
sign_in(other_user)
put "/chat/#{chat_channel.id}/restore/#{Chat::Message.unscoped.last.id}.json"
expect(response.status).to eq(403)
end
it "allows a user to restore their own posts" do
sign_in(user)
deleted_message = Chat::Message.unscoped.last
put "/chat/#{chat_channel.id}/restore/#{deleted_message.id}.json"
expect(response.status).to eq(200)
expect(deleted_message.reload.deleted_at).to be_nil
end
it "allows admin to restore others' posts" do
sign_in(admin)
deleted_message = Chat::Message.unscoped.last
put "/chat/#{chat_channel.id}/restore/#{deleted_message.id}.json"
expect(response.status).to eq(200)
expect(deleted_message.reload.deleted_at).to be_nil
end
it "does not allow message restore when chat channel is read_only" do
sign_in(Chat::Message.last.user)
chat_channel.update!(status: :read_only)
deleted_message = Chat::Message.unscoped.last
put "/chat/#{chat_channel.id}/restore/#{deleted_message.id}.json"
expect(response.status).to eq(403)
expect(deleted_message.reload.deleted_at).not_to be_nil
sign_in(admin)
put "/chat/#{chat_channel.id}/restore/#{deleted_message.id}.json"
expect(response.status).to eq(403)
end
it "only allows admin to restore when chat channel is closed" do
sign_in(admin)
chat_channel.update!(status: :read_only)
deleted_message = Chat::Message.unscoped.last
put "/chat/#{chat_channel.id}/restore/#{deleted_message.id}.json"
expect(response.status).to eq(403)
expect(deleted_message.reload.deleted_at).not_to be_nil
chat_channel.update!(status: :closed)
put "/chat/#{chat_channel.id}/restore/#{deleted_message.id}.json"
expect(response.status).to eq(200)
expect(deleted_message.reload.deleted_at).to be_nil
end
end
describe "#restore" do
fab!(:second_user) { Fabricate(:user) }
before do
message =
Chat::Message.create(user: user, message: "this is a message", chat_channel: chat_channel)
message.trash!
end
describe "for category" do
fab!(:chat_channel) { Fabricate(:category_channel, chatable: category) }
it_behaves_like "chat_message_restoration" do
let(:other_user) { second_user }
end
end
end
describe "react" do
fab!(:chat_channel) { Fabricate(:category_channel) }
fab!(:chat_message) { Fabricate(:chat_message, chat_channel: chat_channel, user: user) }