mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-08 07:40:08 +09:00
506c2771fe
Now that the unread fanout runs in a job, it can run after a member has already opened the room and moved on to another one. Their sidebar would then mark the room unread for a message they have seen. The job now notifies only members who still have the room unread or are in it now. Room#receive marks members who aren't in the room unread, and opening the room clears it, so a member who caught up in the meantime is skipped. When the job runs right away this is the same set of people as before, except members who have hidden the room, whose sidebar doesn't list it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JVFo3Lt9T8M5NR7KxVvsZ2
30 lines
1.1 KiB
Ruby
30 lines
1.1 KiB
Ruby
module Message::Broadcasts
|
|
def broadcast_create
|
|
broadcast_append_to room, :messages, target: [ room, :messages ]
|
|
broadcast_unread_room_later
|
|
end
|
|
|
|
def broadcast_remove
|
|
broadcast_remove_to room, :messages
|
|
end
|
|
|
|
# Fanned out to the room's members rather than published on one global stream, so
|
|
# that the timing of activity in a room only reaches people who are in it. Of those,
|
|
# only the ones who still have it unread or are in it now: by the time this runs,
|
|
# someone may have opened the room and moved on, and would see it marked unread again.
|
|
def broadcast_unread_room
|
|
payload = ActiveSupport::JSON.encode(roomId: room.id)
|
|
|
|
room.memberships.unread.or(room.memberships.connected).pluck(:user_id).each do |user_id|
|
|
ActionCable.server.broadcast UnreadRoomsChannel.stream_name_for(user_id), payload, coder: nil
|
|
end
|
|
end
|
|
|
|
private
|
|
# The fanout is one publish per member, which in a big room takes far longer than the
|
|
# rest of posting a message, so it runs in a job rather than while the poster waits.
|
|
def broadcast_unread_room_later
|
|
Message::BroadcastUnreadRoomJob.perform_later(self)
|
|
end
|
|
end
|