Files
once-campfire/app/models/rooms/direct.rb
T
Marcello Costagliola 33c4b726e7 Find a direct room with one query instead of checking every one
Opening a direct room looked for an existing one by loading every direct
room on the account and comparing its member ids in Ruby, two queries per
room, on each click. The cost grows with the account: about 0.3 s at 1,000
direct rooms and 3 s at 10,000. Asking SQL for the room among the first
user's memberships whose member set is exactly the given users finds the
same room in one query, however many direct rooms there are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JVFo3Lt9T8M5NR7KxVvsZ2
2026-10-05 04:06:17 +02:00

26 lines
872 B
Ruby

# Rooms for direct message chats between users. These act as a singleton, so a single set of users will
# always refer to the same direct room.
class Rooms::Direct < Room
class << self
def find_or_create_for(users)
find_for(users) || create_for({}, users: users)
end
private
# Among the first user's rooms, the one whose members are exactly these users: as many
# memberships as users, and all of them theirs.
def find_for(users)
user_ids = users.pluck(:id).uniq
where(id: Membership.where(user_id: user_ids.first).select(:room_id))
.joins(:memberships).group(:id)
.having("COUNT(*) = :size AND COUNT(CASE WHEN memberships.user_id IN (:user_ids) THEN 1 END) = :size", size: user_ids.size, user_ids: user_ids)
.first
end
end
def default_involvement
"everything"
end
end