Handle POST failure in Phoenix app

I’m still working through @pragdave’s course building a simple Hangman game. One of the tasks involves shutting down a game server after a timeout is reached. I cannot figure out how to correctly notify the Phoenix frontend (or is client the better word?) that the game has died or how to redirect if someone tries to interact with a dead game. Right now after a game times out the web app does nothing and if the user then tries to guess a letter for a dead game the Phoenix server returns

unhandled exit at POST /hangman
exited in: GenServer.call(#PID<0.1204.0>, {:make_move, “c”}, 5000) ** (EXIT) no process:
the process is not alive or there’s no process currently associated with the given name,
possibly because its application isn’t started

What are the best ways to approach this?

Process.alive?(pid) - Tells whether the given process is alive on the local node.

I am guessing you are making a post http call from the title and it is trying to make call on genserver.

You can add check something like case Process.alive?(<PID>) do and if it is not alive you return error message in response.

1 Like

This method only works if you are using channels in webpages.

GenServer.terminate(reason, state) is a callback which is invoked for any cleanup actions to executed. when server is about to exit

If you are using channels, you can broadcast that server is shutting down to all connected to a topic - Phoenix.Channel — Phoenix v1.6.6

Here topic is your game channel where all clients are connected.

MyAppWeb.Endpoint.broadcast!("game:" <> game_id, "shutdown", %{reason: reason})

On the webpage you can handle appropriately using javascript.

2 Likes

Thanks for your help!

I might have to look into Channels, I think. Right now I am sending a terminate_child/2 call from the “watchdog” process to the game server supervisor. Otherwise the supervisor just starts a new game in a new process automatically.

Two ways of doing same thing. One is checking when POST happens, other is push from server as broadcast when you are using channels. Channels are not needed to solve the problem.

I have not seen the course or code - so my advice is generic. Looks like your code is not using channels. So first one should work ? You can redirect to games page or new game page if the Process.alive? returns false.

Yes, I think the first approach would work, but it feels like a less consistent design pattern. The backend game server is responsible for all aspects of starting, playing, and ending a game. The frontend (Phoenix app) is basically responsible only for displaying the game state and providing the interface. So it feels like the responsibility for recognizing the game has been terminated should fall on the backend and the backend should notify the frontend of the change in game state, allowing it to display an appropriate interface.

Having the frontend check that the game is alive shifts that responsibility, although you’re right that it is probably the easier way to do it with the current way the app is structured.

1 Like