I am looking to make use of Erlang's hot code swapping feature on a gen_server, so that I don't have to restart it. How should I do that? When I searched, all I could find was one article which mentioned that I need to make use of gen_server:code_change
callback.
However, I could not really find any documentation/examples on how to use this. Any help or links to resources greatly appreciated!
As I already mentioned the normal way of upgrading is creating the proper .appup and .relup files, and let release_handler do what needs to be done. However you can manually execute the steps involved, as described here. Sorry for the long answer.
The following dummy gen_server implements a counter. The old version ("0") simply stores an integer as state, while the new version ("1") stores {tschak, Int} as state. As I said, this is a dummy example.
z.erl (old):
z.erl (new):
Start the shell, and compile the old code. Notice the gen_server is started with debug trace.
Works as expected: returns the Int, and new state is Int+1.
Now replace z.erl with the new one, and execute the following steps.
What you just did: 5: compiled the new code. 6: suspended the server. 7: purged older code (just in case). 8: loaded the new code. 9: invoked code change in process 'z' for module 'z' from version "0" with [] passed as "Extra" to code_change. 10: resumed the server.
Now if you run some more tests, you can see, that the server works with the new state format:
You don't need to use that callback in the
gen_server
behaviour. It is there if you change the internal representation of the state across a code upgrade.You only need to load the new module and the
gen_server
running the old version will upgrade, since it calls the new module. It is just that you dont have a chance to change the representation if that is necessary.If you're on rebar3, some of this manual processing has been automated away (ie. appup and relup generation), you can find more info here: http://lrascao.github.io/automatic-release-upgrades-in-erlang/
The simplest way to do it is replace the
.beam
file and runl(my_server_module).
in the shell. This bypasses thecode_change
function, and therefore requires that the representation of state hasn't changed.As mentioned already, the proper way to do it is to create a new release with appup and relup scripts. This new release is then installed with release_handler.
If you want to do it the right way, which is highly recommended, then you need to read up on the use of OTP Supervisors and Applications.
You could do worse than to read the OTP Design Principles User's Guide here :
http://www.erlang.org/doc/design_principles/users_guide.html