In order to upgrade to new version we need to create a appup file i.e. nine9s.appup.src which describes how to update from version number 0.1.0 to 0.2.0,

{"vsn in app.src",

[ {"upgrade from vsn", Instructions1}],

[ {"downgrade to vsn", Instructions2}]

}

The appup file is a tuple of three elements where the first element is the version as defined in the .app.src (current version). The second argument is a list of tuples where the first element in each of these tuples is the version number from which to upgrade and the second argument is a list of instructions of how to upgrade from that version. These tuples direct how to upgrade from a given version to current version. The third argument in appup file is a list of tuples where first argument of each of these tuples is version number to downgrade to and second argument is a list of instructions directing how to downgrade to this version.

Following is the appup file for nine9s.

{“0.2.0”,

[{“0.1.0”, [

{add_module, state_handler}

,{update, nine9s_sup, supervisor}

,{apply, {supervisor, restart_child, [nine9s_sup, state_handler]}}

,{load_module, default_handler}

,{add_module, count_handler}

,{load_module, nine9s_app}

,{apply, {nine9s_app, set_routes_new, [] }} ] }],

[{“0.1.0”, [

{load_module, default_handler}

,{apply, {supervisor, terminate_child, [nine9s_sup, state_handler]}}

,{apply, {supervisor, delete_child, [nine9s_sup, state_handler]}}

,{update, nine9s_sup, supervisor}

,{delete_module, state_handler}

,{apply, {nine9s_app, set_routes_old, [] }}

,{delete_module, count_handler}

,{load_module, nine9s_app}

]

}]}.

Now we will discuss the upgrading instructions here. NOTE that the instructions are executed in the order they a specified,

{add_module, state_handler} : directs to add the state_handler.erl file to the shell.

{update, nine9s_sup, supervisor} : this will update the supervisor changing its internal i.e. changing the restart strategy and maximum restart frequency properties, as well as changing the existing child specifications. This will add our state_handler child spec to the supervisor.

{apply, {supervisor, restart_child, [nine9s_sup, state_handler]}} : “apply” takes {M, F, A} as arguments and executes M:F(A1, … An). So we execute supervisor(nine9s_sup, state_handler) which will start the state_handler as a worker process under nine9s_sup supervisor. Notice the order of instructions here, we have added the state_handler first then changed the supervisor state and then spawned the state_handler process.

{load_module, default_handler} : this will reload the default_handler module which replace the old code.

{add_module, count_handler} : now we add the count_handler

{load_module, nine9s_app} we reload the nine9s_app module so that new function which we added are loaded.

{apply, {nine9s_app, set_routes_new, [] }} ] }] : since we have loaded the new functions we will now execute nine9s_app:set_routes_new() to add new routes to our server.

Next argument gives instruction on how to downgrade which works similarly as above but old modules are loaded in place of new modules.

{load_module, default_handler} : will load the old default_handler

{apply, {supervisor, terminate_child, [nine9s_sup, state_handler]}} : terminate state_handler process.

{apply, {supervisor, delete_child, [nine9s_sup, state_handler]}} : delete the child spec for state_handler from the nine9s_sup

{update, nine9s_sup, supervisor} : update internal state of the supervisor.

{delete_module, state_handler} : remove the state_handler module

{apply, {nine9s_app, set_routes_old, [] }} : set the routes to the older version.

{delete_module, count_handler} : remove the count_handler module.

{load_module, nine9s_app} : load the older nine9s_app module.

Since our appup file is complete, we are now ready to upgrade to latest code.

# Firstly we copy the appup file to nine9s src folder under lib

$ cp apps/nine9s/src/nine9s.appup.src _build/default/lib/nine9s/ebin/nine9s.appup # Next we compile and release the new code

$ rebar3 compile

$ rebar3 release # generate relup w.r.t to the previous release

$ rebar3 relup -n nine9s -v "0.2.0" -u "0.1.0" # genereate tar file of the new release

$ rebar3 tar -n nine9s -v "0.2.0" $ mv _build/default/rel/nine9s/nine9s-0.2.0.tar.gz _build/default/rel/nine9s/releases/0.2.0/nine9s.tar.gz # upgrade to the new release

$ _build/default/rel/nine9s/bin/nine9s-0.1.0 upgrade "0.2.0"

That's it ! If everything executed successfully then we have upgraded to version 0.2.0. You can check it by browsing to http://localhost:9090 and http://localhost:9090/count

The project source has two branches i.e. 0.1.0 and 0.2.0 . You can compile and run the code in 0.1.0 and then checkout 0.2.0 and use the python script upgrade.py to upgrade to version 0.2.0