I have a piece of erlang code which should read some values from a db and should support a couple of dbs. I wanted my code to be somehow not dependent from the db, so I implemented two different gen_servers that register both with the same atom (db_handler). I decide which version should be started reading the .app file.
The two gen_servers expose a common handle_call, so I can use in other parts of my application something like:
gen_server:call(db_handler, {do_something, "value1", "value2"})
This works, but still it is strongly coupled to the fact that each and any future implementation for a new db should be a gen_server.
I was thinking of using the ! operator and handle the command in the handle_info, but still I think that a better solution is possible (maybe passing through another module?).
Can somebody give me some insight on the better way to handle something like this in erlang?
For each db server add a common interface to abstract the call:
-module(db_server1).
...
do_something([Value1,Value2]) -> gen_server:call(db_handler, {do_something, "value1", "value2"}).
...
another one not using gen server
-module(db_server2).
...
do_something([Value1,Value2]) -> something_else({do_something, "value1", "value2"}).
...
create a new process (a gen_server :o) which receive as init parameter the param which is used to select the db server and store it in its state (for example db_server2),
for each do_something function, implement a function like:
do_something(Value1,Value2) -> gen_server:call(db_handler, {do_something, ["value1", "value2"]}).
...
handle_call({Func, Args}, _From, DB_server) ->
R = DB_server:F(Args),
{reply, R, DB_server}.
same thing for non blocking interfaces, using cast or equivalent
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With