When to write GenServer state to database

Hi everyone,

I’ve built a multiplayer game with Phoenix LiveView (couldn’t believe how easy it was BTW).

I use a GenServer for storing game state (one GenServer per game). I’m not using hot upgrades (I don’t want to deal with state migrations), so all GenServers die when I deploy a new version of the app. Since I want players to be able to continue playing after a deployment, I write the state of the game to PostgreSQL and the game GenServer reads this state when starting up in a handle_continue/2 callback.

My question is: When should I be writing the state to the database? Right now I save it when some actions happen (player scores a point, makes a move etc.), but I was wondering if using the terminate/2 callback could work as well, or if there’s any idiomatic way of doing this (I would imagine that it’s a pretty common use case)?

2 Likes

I think storing it after every action is fine, until you notice it adds too much load to the DB.
Really, just keep it this way, as long as everything runs fine.

Generally, strictly relying on the terminate callback is not good. If I remember correctly, there are situations where it is not guaranteed that it will be called (e.g. total app crash). However, if everything is set up correctly and the app does a proper shutdown, it should be called. You can also run a timer inside the Genserver to write it all x seconds, which would give you at least some state to recover from in case of e.g. an app crash.

2 Likes

That’s what I thought. I don’t anticipate a lot of users anyway, so I’m sure PostgreSQL will take it without breaking a sweat. I just wanted to know if I missed some BEAM mechanics I wasn’t aware of.

Thanks for the quick feedback!

2 Likes