mirror of
https://github.com/discourse/discourse.git
synced 2025-05-28 23:27:46 +08:00
DEV: Introduce bulk channel tracking publisher (#20838)
This commit introduces a Chat::Publisher and MessageBus endpoint that allows for updating a user's channel tracking state in bulk for multiple channels, rather than having to do it for one channel at a time. This also required an improvement to ChannelUnreadsQuery -- now multiple channel IDs can be passed to this to get the unread counts and mention counts for those channels for a user, also increasing efficiency rather than having to do a query for every individual channel. Followup to #20802
This commit is contained in:
@ -13,39 +13,91 @@ describe Chat::ChannelUnreadsQuery do
|
||||
end
|
||||
|
||||
context "with unread message" do
|
||||
it "returns a correct unread count" do
|
||||
Fabricate(:chat_message, chat_channel: channel_1)
|
||||
before { Fabricate(:chat_message, chat_channel: channel_1) }
|
||||
|
||||
expect(described_class.call(channel_id: channel_1.id, user_id: current_user.id)).to eq(
|
||||
{ mention_count: 0, unread_count: 1 },
|
||||
)
|
||||
it "returns a correct unread count" do
|
||||
expect(
|
||||
described_class.call(channel_ids: [channel_1.id], user_id: current_user.id).first.to_h,
|
||||
).to eq({ mention_count: 0, unread_count: 1, channel_id: channel_1.id })
|
||||
end
|
||||
|
||||
context "for multiple channels" do
|
||||
fab!(:channel_2) { Fabricate(:category_channel) }
|
||||
|
||||
it "returns accurate counts" do
|
||||
channel_2.add(current_user)
|
||||
Fabricate(:chat_message, chat_channel: channel_2)
|
||||
Fabricate(:chat_message, chat_channel: channel_2)
|
||||
|
||||
expect(
|
||||
described_class.call(
|
||||
channel_ids: [channel_1.id, channel_2.id],
|
||||
user_id: current_user.id,
|
||||
).map(&:to_h),
|
||||
).to match_array(
|
||||
[
|
||||
{ mention_count: 0, unread_count: 1, channel_id: channel_1.id },
|
||||
{ mention_count: 0, unread_count: 2, channel_id: channel_2.id },
|
||||
],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with unread mentions" do
|
||||
before { Jobs.run_immediately! }
|
||||
|
||||
it "returns a correct unread mention" do
|
||||
message = Fabricate(:chat_message)
|
||||
def create_mention(message, channel)
|
||||
notification =
|
||||
Notification.create!(
|
||||
notification_type: Notification.types[:chat_mention],
|
||||
user_id: current_user.id,
|
||||
data: { chat_message_id: message.id, chat_channel_id: channel_1.id }.to_json,
|
||||
data: { chat_message_id: message.id, chat_channel_id: channel.id }.to_json,
|
||||
)
|
||||
Chat::Mention.create!(notification: notification, user: current_user, chat_message: message)
|
||||
end
|
||||
|
||||
expect(described_class.call(channel_id: channel_1.id, user_id: current_user.id)).to eq(
|
||||
{ mention_count: 1, unread_count: 0 },
|
||||
)
|
||||
it "returns a correct unread mention" do
|
||||
message = Fabricate(:chat_message, chat_channel: channel_1)
|
||||
create_mention(message, channel_1)
|
||||
|
||||
expect(
|
||||
described_class.call(channel_ids: [channel_1.id], user_id: current_user.id).first.to_h,
|
||||
).to eq({ mention_count: 1, unread_count: 1, channel_id: channel_1.id })
|
||||
end
|
||||
|
||||
context "for multiple channels" do
|
||||
fab!(:channel_2) { Fabricate(:category_channel) }
|
||||
|
||||
it "returns accurate counts" do
|
||||
message = Fabricate(:chat_message, chat_channel: channel_1)
|
||||
create_mention(message, channel_1)
|
||||
|
||||
channel_2.add(current_user)
|
||||
Fabricate(:chat_message, chat_channel: channel_2)
|
||||
message_2 = Fabricate(:chat_message, chat_channel: channel_2)
|
||||
create_mention(message_2, channel_2)
|
||||
|
||||
expect(
|
||||
described_class.call(
|
||||
channel_ids: [channel_1.id, channel_2.id],
|
||||
user_id: current_user.id,
|
||||
).map(&:to_h),
|
||||
).to match_array(
|
||||
[
|
||||
{ mention_count: 1, unread_count: 1, channel_id: channel_1.id },
|
||||
{ mention_count: 1, unread_count: 2, channel_id: channel_2.id },
|
||||
],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with nothing unread" do
|
||||
it "returns a correct state" do
|
||||
expect(described_class.call(channel_id: channel_1.id, user_id: current_user.id)).to eq(
|
||||
{ mention_count: 0, unread_count: 0 },
|
||||
)
|
||||
expect(
|
||||
described_class.call(channel_ids: [channel_1.id], user_id: current_user.id).first.to_h,
|
||||
).to eq({ mention_count: 0, unread_count: 0, channel_id: channel_1.id })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -129,11 +129,30 @@ RSpec.describe Chat::MarkAllUserChannelsRead do
|
||||
}.by(-2)
|
||||
end
|
||||
|
||||
it "publishes tracking state for all affected channels" do
|
||||
messages = MessageBus.track_publish { result }
|
||||
expect(
|
||||
messages.select { |m| m.channel == "/chat/user-tracking-state/#{current_user.id}" }.count,
|
||||
).to eq(3)
|
||||
it "publishes tracking state in bulk for affected channels" do
|
||||
message =
|
||||
messages.find { |m| m.channel == "/chat/bulk-user-tracking-state/#{current_user.id}" }
|
||||
|
||||
expect(message.data).to eq(
|
||||
channel_1.id.to_s => {
|
||||
"last_read_message_id" => message_2.id,
|
||||
"membership_id" => membership_1.id,
|
||||
"mention_count" => 0,
|
||||
"unread_count" => 0,
|
||||
},
|
||||
channel_2.id.to_s => {
|
||||
"last_read_message_id" => message_4.id,
|
||||
"membership_id" => membership_2.id,
|
||||
"mention_count" => 0,
|
||||
"unread_count" => 0,
|
||||
},
|
||||
channel_3.id.to_s => {
|
||||
"last_read_message_id" => message_6.id,
|
||||
"membership_id" => membership_3.id,
|
||||
"mention_count" => 0,
|
||||
"unread_count" => 0,
|
||||
},
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user