@Falco Salut, j’ai rencontré quelques problèmes reproductibles lors des tests de la version mise à jour de Resenha. Je partage mes observations ainsi que les correctifs que j’applique localement, au cas où ils seraient utiles pour le projet en amont.
1. L’interface admin ignore silencieusement room_type : les salles de type “stage” ne peuvent jamais conserver ce statut
app/controllers/resenha/admin_rooms_controller.rb:65 (room_params) omet :room_type de la liste des paramètres autorisés, et admin_room_serializer.rb ne le sérialise jamais.
Toute attribution de type “stage” effectuée via l’interface admin est ignorée ; les salles sont créées en mode “ouvert” et “repassent” en mode “ouvert” lors de toute modification ultérieure via l’admin. Confirmé via les logs de production ; le contrôleur côté utilisateur l’autorise, seul le chemin admin le perd.
# admin_rooms_controller.rb — ajouter :room_type à la liste des paramètres autorisés, puis :
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 — sérialiser room_type afin que le formulaire s'initialise correctement
2. Un room_type invalide bascule silencieusement sur “ouvert”
app/controllers/resenha/rooms_controller.rb:575 — ROOM_TYPES[...] || ROOM_TYPE_OPEN.
Tout room_type malformé ou obsolète dans une modification de salle par ailleurs valide transforme silencieusement une salle de type “stage” en salle “ouverte”. Renvoyer une erreur 400 permet de rendre visible l’appelant fautif plutôt que de corrompre la salle.
value = Resenha::Room::ROOM_TYPES[permitted[:room_type].to_s]
raise Discourse::InvalidParameters.new(:room_type) if value.nil?
permitted[:room_type] = value
3. Le heartbeat réanime un utilisateur qui vient de quitter (présence fantôme)
rooms_controller.rb:234 (heartbeat) réajoute la présence sans condition, donc si un heartbeat est en cours d’exécution lorsque leave (:220) est traité en second, il recrée l’utilisateur parti.
Le fantôme persiste jusqu’à la suppression par expiration du TTL, qui n’est pas diffusée — les clients l’affichent “dans la salle” pendant jusqu’à une minute.
Reproduit sur appareil ; le “kick” présente la même vulnérabilité.
# ParticipantTracker : marqueur de suppression de 15s
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. Un webhook participant_left obsolète “kick” une session fraîche
livekit_webhooks_controller.rb:37/57 — les départs sont appariés uniquement par l’identité de l’utilisateur.
En cas de déconnexion/reconnexion rapide, le participant_left de la session remplacée arrive en retard et expire la présence de la nouvelle session (l’utilisateur est “kické” ~3s après la reconnexion, puis revient ~15s plus tard).
Reproduit sur appareil ; l’heuristique gone_at ne peut pas distinguer les sessions lorsque la reconnexion précède la déconnexion de l’ancienne session.
# participant_joined → enregistrer le SID actif
Resenha::ParticipantTracker.set_livekit_sid(room.id, user_id, event.dig("participant", "sid"))
# expire_participant → ignorer le départ d'une session remplacée
known = Resenha::ParticipantTracker.livekit_sid(room.id, user_id)
return if sid.present? && known.present? && sid != known
5. DeleteRoom 404 après le dernier départ inonde les logs
lib/resenha/livekit/room_service_client.rb:84 avertit sur toute réponse non-200.
Le SFU ferme automatiquement une salle dès qu’elle est vide, donc le DeleteRoom du dernier départ entre souvent en concurrence avec cette fermeture — “la salle demandée n’existe pas” est l’état final attendu, et non une erreur.
Cela apparaît dans Logster à chaque dernier départ.
elsif method == "DeleteRoom" && response.status == 404
Rails.logger.debug("[resenha-livekit] DeleteRoom no-op pour la salle #{room.id} : déjà fermée")
true
Je peux envoyer une pull request si vous le souhaitez.
Comme je l’ai dit précédemment, je ne connais pas votre direction dans son intégralité, mais vous pouvez jeter un œil à la mienne, car j’ai publié un message ici → Discourse Desktop Mac App - #10 by nicolsdennis