Broadcasting to channel on GenServer exit

Hi all,

I’m creating an application where at any given point there are a number of active “rooms”. These rooms must have state, so when someone creates a room the application spins up a GenServer to associate with it via a DynamicSupervisor, and it is tracked in a Registry. Rooms can be disbanded a few ways, notably manually by a host, by inactivity, or by error (this last one is where my confusions come in).

When a room terminates, any client still in that room must be notified, so I have to broadcast to the channel topic. This is easy to do with Endpoint.broadcast!, but I’m wondering where this call should be made. I’ve come up with a few options:

  1. The terminate/2 callback of the GenServer which is exiting. This seems to work well, but my understanding is terminate/2 is not always called (for example, running 1 / 0 in a callback did not call terminate/2). It feels weird not wanting to do something because a runtime exception might cause strange behavior (lol), but also this is Elixir, if there’s a runtime exception I want people to be gracefully kicked out of the room and send back to the lobby so they can create a new room if they like. It also feels a little weird having channel event logic in the GenServer, but not sure if that’s actually something I should be worried about.
  2. The supervisor monitoring/trapping exits. I’ve actually had trouble getting this to work, but if this would be better in theory I would figure it out.
  3. A different process being in charge of monitoring room GenServers and broadcasting messages on their exit. I kinda like this because it separates concerns of the room servers and room supervisor a bit, but not sure if there’s actually a reason to do this. Plus it would rely on the :trap_exit flag and/or Process.monitor, and I’m not sure if using those from a separate process is the best way to do this when terminate/2 and all children are supervised by an existing process already.

Any thoughts and/or resources I should read? I feel like the problem of associating a GenServer with an active topic can’t be a new one but I haven’t come across any resources that describe good patterns for this in-depth. Thank you!

1 Like

Instead of broadcasting, each client could instead Process.monitor the GenServer for the room. Then it will get a guaranteed :DOWN message from the VM instead of relying on the terminating GenServer to broadcast.

1 Like

What do you mean by this exactly? By client, I mean person viewing the room in the browser. Is there some way the Channel could be monitoring processes as they get spun up by the supervisor? Maybe I could send a message to the channel process with the new room server PID and in a handle_info on the Channel it could run Process.monitor? That seems a bit hacky though…unless it isn’t :thinking:

Yes, I assume it is a registered GenServer with a well known name, such as the module name. Any process can monitor any process via Process.monitor/1

When a client channel process “joins” a room today how does that work? How does it communicate with the room process?