Would something like that be reasonable:
a() ->
case gen_server:call(..., a) of
{ok, Value} -> Value;
{error, Error} -> throw({error, Error})
end
and
handle_call(a, ...) ->
case ... of
{ok, Value} -> {reply, {ok, Value} , State};
{error, Error} -> {reply, {error, Error} , State}
end
Regards,
Anton
________________________________________________________________
erlang-questions mailing list. See http://www.erlang.org/faq.html
erlang-questions (at) erlang.org
I usually do the following:
foo(Params) ->
case gen_server:call(?MODULE, {foo, Params}) of
{error, Reason} ->
erlang:error({Reason, Params}); % I return params to
understand what's going on...
{ok, Value} ->
Value
end.
handle_call({create, Name, Opts}, _From, State) ->
...
Regards,
Roberto Aloi
Erlang Training and Consulting Ltd.
http://www.erlang-consulting.com
a() ->
{ok, Value} = gen_server:call(..., a),
Value.
Your handle_call looks OK to me.
Cheers,
David
-Vance
--------------------------------------------------------------------------
-module(foo_client).
-export([do_local/2, do_remote/2]).
do_local(Pid, Request) ->
case gen_server:call(Pid, Request) of
{ok, Value} ->
Value;
{error, Error} ->
exit(Error)
end.
do_remote(Pid, Request) ->
gen_server:call(Pid, Request).
--------------------------------------------------------------------------
-module(foo_server).
-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
init(Arg) ->
{ok, Arg}.
handle_call(foo_local, _From, State) ->
{reply, {ok, 42}, State};
handle_call(foo_remote, _From, State) ->
{reply, 42, State};
handle_call(bar_local, _From, State) ->
{reply, {error, badarg}, State};
handle_call(bar_remote, {Pid, _Tag}, State) ->
exit(Pid, badarg),
{noreply, State}.
handle_cast(_Request, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
--------------------------------------------------------------------------
1> application:start(sasl).
ok
2> {ok, S} = gen_server:start(foo_server, [], []).
{ok,<0.45.0>}
3> foo_client:do_local(S, foo_local).
42
4> foo_client:do_local(S, bar_local).
** exception exit: badarg
in function foo_client:do_local/2
5> foo_client:do_remote(S, foo_remote).
42
6> foo_client:do_remote(S, bar_remote).
** exception exit: badarg
7>
On Fri, Nov 06, 2009 at 03:57:24PM +0000, Anton Krasovsky wrote:
} What would be the standard way of returning/throwing an exception in a
} result to a gen_server:call?
}
} Would something like that be reasonable:
}
} a() ->
} case gen_server:call(..., a) of
} {ok, Value} -> Value;
} {error, Error} -> throw({error, Error})
} end
}
} and
}
} handle_call(a, ...) ->
} case ... of
} {ok, Value} -> {reply, {ok, Value} , State};
} {error, Error} -> {reply, {error, Error} , State}
} end
________________________________________________________________
Regards,
anton
Anton
I do use this method to handle unknown calls in servers where I'd
rather the server kept running than have it fail and expose a
programming error in another process.
handle_call(Request, From, State) ->
...
{reply, Reply, State};
handle_call(_Request, {Pid, _Tag}, State) ->
exit(Pid, badarg),
{noreply, State}.
This way if some process attempts gen_server:call(S, foo), where
foo is not a supported API call, they get the appropriate response.
--
-Vance
Anton
- First off: do you want the error to crash the server or not? If so is
links and exit signals a good enough way for you to see the error?
- If the server is to live, how should your app see the error? Two valid
suggestions which have been given here are:
1. Signal the error using exit/2. This "simulates" the exit signals as if
the server had crashed.
2. Return an error value which either: returns an error value to the caller;
or generates an error using erlang:error/1. Which is best for you depends on
your app.
All these solutions are easy to program so the main problem is for you to
decide which is best for your app.
One thing I would *NOT* do is use throw/1 to signal error! Throw is for
non-local returns not errors. Using it for errors will just lead to
confusion and maybe errors if other parts of app assume it is a non-local
return. As try can differentiate between throw, exit and error it is
important that they are used for the right thing.
Robert
P.S. I would LOVE to change catch now so it only catches throws, but I don't
think it would be possible. :-(
2009/11/6 Anton Krasovsky <anton.k...@gmail.com>
Regards,
Anton