Is there a way to trigger a GenServer restart when phoenix_live_reload fires?

Hi. I am using a GenServer to store a number of global constants on ETS. These constants combine data from a variable set of Elixir modules. The constants are derived after compilation, with :application.get_key(:my_app, :modules) supplying the module names (from which the data is extracted). Prior to compilation, get_key/2 seems to return nil.

This approach might work in production; in development, however, I must remember to restart the server manually, every time a change is made to the data-containing modules. I was therefore wondering whether there might be a way of triggering a GenServer restart, every time phoenix_live_reload fires following the detection of a change in my Elixir code.

Phoenix.CodeReloader is what you need to look at. It looks like you could decorate the reload callback used by the plug.

1 Like

Thanks for the pointer. I was hoping for a “fix and forget” type of solution, that there might be an obvious mechanism that I had somehow missed. If I decorate the reload callback, presumably I will have to repeat this every time CodeReloader is updated. If my understanding is correct, I would rather opt for a runtime calculation of each constant during development – and accept the risk of a discrepancy with the production environment.

Best wishes for 2020!

Why not just call this every time it’s needed? It’s very cheap and you can change the values at runtime with ease.

Indeed, :application.get_key(:my_app, :modules) does the job perfectly, but I was hoping for a built-in way to trigger it. The problem with its returning nil prior to compilation was not the cost of the runtime operation, it was that I could not use the re-compilation to reset my (runtime) constants. So, unless dev and prod logic is kept separate, I can be left with a GenServer preserving stale “constants” on ETS, while phoenix_live_reload is giving me the false impression that my changes are taking effect.

Clearly, this is not a huge issue, I just wanted to make sure that I am not missing an obvious solution.