I am building an app which can run in two modes. A sandbox mode and a production one.
In sandbox mode, i want to make many checks in my gen_server against the database : if table doesn't exist then create it ; if column doesn't exist then add it ; if column type doesn't allow the value i want to store then change it, etc.
In production mode, if a tables does not exist or a column does not match the type of the value, it will fail and that is ok.
So, in order to avoid cumbersome code like "case State#state.is_sandbox of true -> ... ", i would like to have two different modules for my gen_server, and i would like to change the current module either in handle_call or handle_info.
Actually, i just want to go from sandbox to production, but i think if it works this way, it could work backwards.
Thanks.
You can add module
, which is a name of a module, to the state in gen_server. Then you will need 2 modules - sandbox and production that both implement the same functions (you could create a behaviour for it).
The gen_server callbacks will call module:function
which will be a function either from sandbox or production module. The module
can be set in init
function of the gen_server, to change it, simply add a new function(s) to the gen_server:
use_production() ->
gen_server:cast(production).
....
handle_cast(production, State) ->
{noreply, State#state{module = production}).
The same for the sandbox module.
An example of a gen_server's callback with the module
:
handle_call(Msg, _From, #state{module = Module} = State) ->
Module:function(Msq),
{reply, ok, State}.
The function
must be implemented in both sandbox and production modules.