리뷰 - 커뮤니티에 Discord 스타일 비디오 및 음성 룸과 통화를 추가하세요 🎙

@Falco 안녕하세요, 업데이트된 resenha를 테스트하는 과정에서 재현 가능한 몇 가지 문제를 발견했습니다. 유용할 수 있기를 바라며, 조사 결과와 로컬에서 실행 중인 패치를 공유합니다.

1. 관리자 UI가 room_type을 조용히 무시하여 stage 룸이 영원히 유지되지 않음
app/controllers/resenha/admin_rooms_controller.rb:65 (room_params)에서 허용 목록에 :room_type이 빠져 있고, admin_room_serializer.rb에서는 이를 직렬화하지 않습니다.

관리자 UI를 통해 수행한 모든 stage 할당이 삭제되며, 룸은 open 상태로 생성되고 이후 관리자 편집 시 open 상태로 "복원"됩니다. 프로덕션 로그를 통해 확인했습니다. 사용자용 컨트롤러에서는 허용되고 있으며, 관리자 경로에서만 누락되었습니다.

# admin_rooms_controller.rb — 허용 목록에 :room_type을 추가한 다음:
if permitted.key?(:room_type)
  value = Resenha::Room::ROOM_TYPES[permitted[:room_type].to_s]
  raise Discourse::InvalidParameters.new(:room_type) if value.nil?
  permitted[:room_type] = value
end
# admin_room_serializer.rb — room_type을 직렬화하여 양식이 올바르게 초기화되도록 함

2. 잘못된 room_type이 조용히 open으로 폴백됨
app/controllers/resenha/rooms_controller.rb:575ROOM_TYPES[...] || ROOM_TYPE_OPEN.

그 외 유효한 룸 편집에서 잘못된/오래된 room_type은 stage 룸을 open으로 조용히 전환시킵니다. 400 오류를 반환하면 룸이 손상되는 대신 잘못된 동작을 하는 호출자를 확인할 수 있습니다.

value = Resenha::Room::ROOM_TYPES[permitted[:room_type].to_s]
raise Discourse::InvalidParameters.new(:room_type) if value.nil?
permitted[:room_type] = value

3. 하트비트가 방금 떠난 사용자를 부활시킴 (고유 존재감)
rooms_controller.rb:234 (heartbeat)는 무조건적으로 존재감을 다시 추가하므로, leave(:220)가 처리되는 시점에 전송 중인 하트비트가 두 번째로 도착하여 떠난 사용자를 다시 생성합니다.
이 고유의 존재감은 TTL 수거(reap)까지 지속되며, 이는 브로드캐스트되지 않습니다 — 클라이언트는 최대 1분 동안 해당 사용자가 "룸에 있음"으로 표시합니다.

기기에서 재현했습니다. kick도 동일한 취약점이 있습니다.

# ParticipantTracker: 15초 톰스톤(tombstone)
def mark_left(room_id, user_id)  = redis.setex(left_key(room_id, user_id), 15, "1")
def recently_left?(room_id, user_id) = redis.exists?(left_key(room_id, user_id))
# leave/kick → mark_left; join/livekit_token → clear_left; heartbeat:
return head :no_content if Resenha::ParticipantTracker.recently_left?(@room.id, current_user.id)

4. 오래된 participant_left 웹훅이 새로운 세션을 유령처럼 강퇴함
livekit_webhooks_controller.rb:37/57 — 이탈은 사용자 신원만으로 매칭됩니다.
빠른 연결 해제/재연결 시, 대체된 세션의 participant_left가 늦게 도착하여 새로운 세션의 존재감을 만료시킵니다(사용자가 재연결 후 약 3초后被 "강퇴"되고, 약 15초 후에 다시 나타남). 기기에서 재현했습니다. 재연결이 이전 세션의 연결 해제보다 먼저 발생한 경우, gone_at 휴리스틱은 세션을 구별할 수 없습니다.

# participant_joined → 활성 SID 기록
Resenha::ParticipantTracker.set_livekit_sid(room.id, user_id, event.dig("participant", "sid"))
# expire_participant → 대체된 세션의 이탈 무시
known = Resenha::ParticipantTracker.livekit_sid(room.id, user_id)
return if sid.present? && known.present? && sid != known

5. 마지막 이탈 후 DeleteRoom 404가 로그를 범람시킴
lib/resenha/livekit/room_service_client.rb:84는 200이 아닌 모든 응답에 대해 경고를 기록합니다.
SFU는 룸이 비어지는 순간 자동으로 룸을 닫으므로, 마지막 이탈의 DeleteRoom은 이를 정기적으로 경쟁(race)합니다 — "요청한 룸이 존재하지 않습니다"는 결함이 아니라 원하시는 최종 상태입니다.
이는 마지막 이탈 시마다 Logster에 기록됩니다.

elsif method == "DeleteRoom" && response.status == 404
  Rails.logger.debug("[resenha-livekit] DeleteRoom no-op for room #{room.id}: already gone")
  true

원하시면 풀 리퀘스트를 보내겠습니다.

이전에 말했듯이, 님의 전체 방향성을 정확히 알지는 못하지만, 제가 여기에 게시물을 올렸으므로 제 것을 참고해 보실 수 있습니다 → https://meta.discourse.org/t/discourse-desktop-mac-app/406912/10?u=nicolsdennis

2개의 좋아요