mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-09 00:00:12 +09:00
33c4b726e7
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
26 lines
872 B
Ruby
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
|