# مراجعة - أضف غرف فيديو وصوت واستدعاءات بأسلوب ديسكورد إلى مجتمعك 🎙

**URL:** https://meta.discourse.org/t/resenha-add-discord-style-video-and-voice-rooms-and-calls-to-your-community/389056
**Category:** Plugin
**Created:** [19 نوفمبر 2025، 4:34م UTC](https://meta.discourse.org/t/resenha-add-discord-style-video-and-voice-rooms-and-calls-to-your-community/389056 "2025-11-19T16:34:26Z")
**Posts on this page:** 1
**Showing post:** 72

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [30 يوليو 2026، 7:09م UTC](https://meta.discourse.org/t/resenha-add-discord-style-video-and-voice-rooms-and-calls-to-your-community/389056/72 "2026-07-30T19:09:37Z")

</div>

شكراً لك على التقرير المفصل، لقد قمت بدمج طلب السحب (PR) الخاص بذلك:

> <https://github.com/discourse/resenha/pull/72>
>
> This addresses five user-reported bugs around presence tracking, room types, and… LiveKit reconciliation. One commit per fix.
> 
> \## 1. Racing heartbeats resurrected departed users (ghost presence)
> 
> A heartbeat already in flight when a \`leave\` or \`kick\` was processed landed second and unconditionally re-added the departed user's presence. Because the TTL reap never broadcasts, the ghost stayed visible to other clients until the next republish sweep — up to a minute.
> 
> Leave and kick now write a short-lived Redis tombstone (15s — one heartbeat interval plus latency) that \`heartbeat\` checks before re-adding presence. \`join\` and the reconnect ladder's \`livekit\_token\` endpoint clear it, since both are explicit statements that the user is (re-)entering the call.
> 
> \## 2. \`room\_type\` could not be set through the admin UI, and unknown values silently became "open"
> 
> The admin controller never permitted \`room\_type\` and the admin serializer never returned it, so the admin form always displayed (and submitted) "open" — stage assignments made there were silently dropped. Both halves land together deliberately: permitting the param while the form still prefills "open" from the missing serializer field would flip existing stage rooms back to open on any admin edit.
> 
> The user-facing controller also mapped unknown \`room\_type\` values to open as a silent fallback. Both controllers now share a strict model-level lookup that rejects unknown names with a 400 — the column is an integer, so an unmapped name would otherwise cast to \`0\` (open) and corrupt the room.
> 
> \## 3. A superseded LiveKit session's late departure webhook dropped a fresh session
> 
> Departure webhooks were matched by user identity alone. On a quick disconnect/rejoin, the old session's \`participant\_left\` routinely arrives after the new session is connected, and the \`gone\_at\` heuristic can't tell them apart (the rejoin's presence timestamp predates the old session's disconnect), so the new session's presence was expired and the user vanished from the roster until their next heartbeat.
> 
> \`participant\_joined\` events now record the session SID per user, and a departure whose SID differs from the recorded one is skipped as superseded. Departures without SID context on either side still expire presence, keeping the webhook's reconcile-only backstop role intact. Webhook delivery is unordered, so this narrows the race window rather than sealing it — the next heartbeat still recovers the residual case.
> 
> \## 4. The last leave's \`DeleteRoom\` race logged as a failure
> 
> The SFU tears an emptied room down on its own, so the \`DeleteRoom\` issued by the last participant's leave routinely finds the room already gone and 404s. That's the desired end state, not a fault, yet it landed in Logster on every last-leave (and again from the emptied-room sweep). \`DeleteRoom\` now treats 404 as success at debug level; every other call and status keeps warning.

---

_[View the full topic](https://meta.discourse.org/t/resenha-add-discord-style-video-and-voice-rooms-and-calls-to-your-community/389056)._
