Hi everyone,
I’m building a game using Nakama for the backend, and I’ve implemented a voice room feature similar to Clubhouse, where users can join a room and talk.
To track who is currently talking or holding the microphone, I’m using Nakama chat channels. I edit the channel message regularly to update the list of speakers or users requesting the mic.
When a user leaves the room, I remove them from the mic list (By editing message).
To handle this, I’m currently using the ChannelLeave
hook, and it works fine most of the time.
However, I’ve noticed that in many cases—especially when a user force-closes the app or their internet disconnects suddenly—the ChannelLeave
hook doesn’t seem to fire. As a result, the user is not removed from the speaker list, which leads to inconsistencies.
It seems that ChannelLeave
is not always triggered reliably in those abrupt disconnection scenarios.
What’s the best way to handle this properly and efficiently?
I’d really appreciate any advice or best practices for ensuring users are removed from the mic list even when they leave unexpectedly.
Thanks a lot in advance!
Hello @Ahmadrezadl,
Can you clarify what ChannelLeave
hook you’re using?
Hello @sesposito , thank you for you respone
This is my code
init:
initializer.registerRtAfter("ChannelLeave", afterChannelLeave);
function afterChannelLeave(ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, output: nkruntime.EnvelopeChannelLeave | null, input: nkruntime.EnvelopeChannelLeave) {
logger.info("user " + ctx.userId + " left chat " + input.channelLeave.channelId);
let channelId = input.channelLeave.channelId;
if (channelId.indexOf("Mic_") != -1) {
userLeaveFromMic(nk, ctx.userId, undefined, channelId);
}
}
My problem not solved yet 
@Ahmadrezadl that hook will take care of any client that gracefully leaves the channel. To pick up on forceful disconnects, you’d need to add a hook on built in events: Events - Heroic Labs Documentation .
Hope this helps.
Where Should i call my event? I didn’t understand
How can I notified about player forcefully disconnected?
The SessionEnd event is created when the socket connection for a session is closed. The socket could have closed for a number of reasons but can be observed to react on.
You need to register your custom code as part of the hook:
func eventSessionEnd(ctx context.Context, logger runtime.Logger, evt *api.Event) {
logger.Debug("process event session end: %+v", evt)
}
// initializer runtime.Initializer
if err := initializer.RegisterEventSessionEnd(eventSessionEnd); err != nil {
return err
}
The event is generated automatically when a disconnect is detected by the server. This may overlap with the graceful disconnect, you may only need the former.
Thank you again for your response @sesposito
but there is no RegisterEventSessionEnd
function on initializer on typescript server runtime 
I’m on the latest version btw
Edit: I read the document again and i see this:
Code snippet for this language TypeScript has not been found. Please choose another language to show equivalent examples.
So we don’t have this on typescript
Any plan to adding it?
Hi @Ahmadrezadl, sorry I forgot to mention that this API is Go only. JS support for the event pipeline is not part of the roadmap for now, but you can use Go just for this piece of code, which should be fairly straightforward, and keep using JS for the rest.