1

I have written a gen_server module (data_cahe.erl) that will save the data in ETS.

My code is as follows:

-export([start_link/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
 terminate/2, code_change/3]).

-define(SERVER, ?MODULE).
-define(TABLE_ID, ?MODULE).
-record(state, {user_id, my_reading, my_status}).

start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

init([]) ->
{ok, ?TABLE_ID} = new_cache(?TABLE_ID),
{ok, #state{user_id=undefined, my_reading=undefined, my_status=undefined}}.

The handle_call:

handle_call({save, UserId, Readings}, _From, _Status) ->
io:format("Inside handle_call_save: ~n~p~n",[]);
%Check if email is present
case my_reading(UserId) of
{error, not_found} -> %%Email not present
    io:format("Inside handle_call_save Just before save: ~n~p~n",[]),
    Result = save_my_readings(UserId, Readings),
    {reply, ok, #state{user_id=UserId, my_reading=Readings, my_status=Result}};
{ok, Reading} ->
    io:format("Inside handle_call_save Just before delete and save: ~n~p~n",[]),
    delete_my_reading(UserId), %%delete last reading
    Result = save_my_readings(UserId, Readings), %%Save this new Reading
    {reply, ok, #state{user_id=UserId, my_reading=Readings, my_status=Result}}
end;

I'm trying using this handel_call (that has access to Email and AccessToken) to save the data in ETS from the worker module:

case my_app_interface:get_data_summary(binary_to_list(AccessToken)) of
    {error, _Reason1} ->
    %%Start a new Timer Cycle
    ..
    ..
    Readings1 ->
        gen_server:call(data_cahe, {save, Email, Readings1}), %%HERE IT CRASHES
        io:format("Get Data Summary : ~n~p~n",[Readings1]) %%This is printed when the line above is commented
 end,

However the gen_server:call(...) crashes. When I comment out this line the Readings are printed in usual sequence.

I've even commeneted out all the lines except the print statement in handle_call method - but nothing is printed. It seems the gen_server:call(...) is not at all going through. Would be extremely grateful if someone throws some light what is going wrong.

4

2 回答 2

3

As general rule, you do not want to expose users of your server to gen_server API. Or to be more specific, you don't want them to call gen_server:call( ModuleName, {SomeAtom, And, DifferentArguments}) since it creates space for many errors (misspellings and missing "arguments" in message tuple). And it makes it hard to find out how you could interact with this server (one would have to look into handle_call's and handle_cast's, which is not easiest approach).

To go around this, all such interactions (all possible calls and casts) should be wrapped in function call. And those functions will be exposed (exported) as module interface. And in the end, the client won't have to even know that it is implemented with gen_server

So if your module is called data_cache, and you have functionality of saving some data, just implement save function.

save( Email, Readings) ->
   gen_server:call(?SERVER, {save, Email, Readings1}).

We even used ?SERVER macro (to help a little with possible misspelings), and you can leave handle_call as it was. Now the client call could be changed to

    Readings1 ->
        data_cache:save(Email, Readings1),
        io:format("Get Data Summary : ~n~p~n",[Readings1]) %%This is printed when the line above is commented
 end,

which is much easier to read, and harder to break.

于 2014-10-28T23:03:08.510 回答
3

也许你拼错了?data_cahe而不是 d data_cache..

于 2014-10-28T22:49:10.077 回答