THRIFT-2708 add support for oneway (async) function calls in erlang client Client: Erlang Patch: Alisdair Sullivan modified by Nobuaki Sukegawa
Modification: Fix invalid send_call return type. This closes #231 Project: http://git-wip-us.apache.org/repos/asf/thrift/repo Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/7bdba5c0 Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/7bdba5c0 Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/7bdba5c0 Branch: refs/heads/master Commit: 7bdba5c06a7aa40cf83352c214270a2f1f4dd572 Parents: 149ecc1 Author: alisdair sullivan <[email protected]> Authored: Tue Sep 30 22:03:34 2014 -0700 Committer: Nobuaki Sukegawa <[email protected]> Committed: Sun Nov 1 18:07:15 2015 +0900 ---------------------------------------------------------------------- lib/erl/src/thrift_client.erl | 71 ++++++++++++++++++-------------- test/erl/src/test_client.erl | 4 +- test/erl/src/test_thrift_server.erl | 1 + 3 files changed, 43 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/thrift/blob/7bdba5c0/lib/erl/src/thrift_client.erl ---------------------------------------------------------------------- diff --git a/lib/erl/src/thrift_client.erl b/lib/erl/src/thrift_client.erl index ff5c3dc..209bd4c 100644 --- a/lib/erl/src/thrift_client.erl +++ b/lib/erl/src/thrift_client.erl @@ -36,13 +36,11 @@ new(Protocol, Service) -spec call(#tclient{}, atom(), list()) -> {#tclient{}, {ok, any()} | {error, any()}}. call(Client = #tclient{}, Function, Args) - when is_atom(Function), is_list(Args) -> - case send_function_call(Client, Function, Args) of - {Client1, ok} -> - receive_function_result(Client1, Function); - Else -> - Else - end. +when is_atom(Function), is_list(Args) -> + case send_function_call(Client, Function, Args) of + {ok, Client1} -> receive_function_result(Client1, Function); + Else -> Else + end. %% Sends a function call but does not read the result. This is useful @@ -51,7 +49,10 @@ call(Client = #tclient{}, Function, Args) -spec send_call(#tclient{}, atom(), list()) -> {#tclient{}, ok}. send_call(Client = #tclient{}, Function, Args) when is_atom(Function), is_list(Args) -> - send_function_call(Client, Function, Args). + case send_function_call(Client, Function, Args) of + {ok, Client1} -> {Client1, ok}; + Else -> Else + end. -spec close(#tclient{}) -> ok. close(#tclient{protocol=Protocol}) -> @@ -61,30 +62,36 @@ close(#tclient{protocol=Protocol}) -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- --spec send_function_call(#tclient{}, atom(), list()) -> {#tclient{}, ok | {error, any()}}. -send_function_call(Client = #tclient{protocol = Proto0, - service = Service, - seqid = SeqId}, - Function, - Args) -> - Params = try Service:function_info(Function, params_type) - catch error:function_clause -> no_function - end, - case Params of - no_function -> - {Client, {error, {no_function, Function}}}; - {struct, PList} when length(PList) =/= length(Args) -> - {Client, {error, {bad_args, Function, Args}}}; - {struct, _PList} -> - Begin = #protocol_message_begin{name = atom_to_list(Function), - type = ?tMessageType_CALL, - seqid = SeqId}, - {Proto1, ok} = thrift_protocol:write(Proto0, Begin), - {Proto2, ok} = thrift_protocol:write(Proto1, {Params, list_to_tuple([Function | Args])}), - {Proto3, ok} = thrift_protocol:write(Proto2, message_end), - {Proto4, ok} = thrift_protocol:flush_transport(Proto3), - {Client#tclient{protocol = Proto4}, ok} - end. +-spec send_function_call(#tclient{}, atom(), list()) -> {sync | async | {error, any()}, #tclient{}}. +send_function_call(Client = #tclient{service = Service}, Function, Args) -> + {Params, Reply} = try + {Service:function_info(Function, params_type), Service:function_info(Function, reply_type)} + catch error:function_clause -> no_function + end, + MsgType = case Reply of + oneway_void -> ?tMessageType_ONEWAY; + _ -> ?tMessageType_CALL + end, + case Params of + no_function -> + {{error, {no_function, Function}}, Client}; + {struct, PList} when length(PList) =/= length(Args) -> + {{error, {bad_args, Function, Args}}, Client}; + {struct, _PList} -> write_message(Client, Function, Args, Params, MsgType) + end. + +-spec write_message(#tclient{}, atom(), list(), {struct, list()}, integer()) -> + {ok, #tclient{}}. +write_message(Client = #tclient{protocol = P0, seqid = Seq}, Function, Args, Params, MsgType) -> + {P1, ok} = thrift_protocol:write(P0, #protocol_message_begin{ + name = atom_to_list(Function), + type = MsgType, + seqid = Seq + }), + {P2, ok} = thrift_protocol:write(P1, {Params, list_to_tuple([Function|Args])}), + {P3, ok} = thrift_protocol:write(P2, message_end), + {P4, ok} = thrift_protocol:flush_transport(P3), + {ok, Client#tclient{protocol = P4}}. -spec receive_function_result(#tclient{}, atom()) -> {#tclient{}, {ok, any()} | {error, any()}}. receive_function_result(Client = #tclient{service = Service}, Function) -> http://git-wip-us.apache.org/repos/asf/thrift/blob/7bdba5c0/test/erl/src/test_client.erl ---------------------------------------------------------------------- diff --git a/test/erl/src/test_client.erl b/test/erl/src/test_client.erl index fad0988..7dd5cbc 100644 --- a/test/erl/src/test_client.erl +++ b/test/erl/src/test_client.erl @@ -136,4 +136,6 @@ start(Args) -> ClientS4 end, - thrift_client:close(Client19). + {Client20, {ok, ok}} = thrift_client:call(Client19, testOneway, [1]), + + thrift_client:close(Client20). http://git-wip-us.apache.org/repos/asf/thrift/blob/7bdba5c0/test/erl/src/test_thrift_server.erl ---------------------------------------------------------------------- diff --git a/test/erl/src/test_thrift_server.erl b/test/erl/src/test_thrift_server.erl index 6969465..51457f5 100644 --- a/test/erl/src/test_thrift_server.erl +++ b/test/erl/src/test_thrift_server.erl @@ -219,5 +219,6 @@ handle_function(testMultiException, {Arg0, Arg1}) -> end; handle_function(testOneway, {Seconds}) -> + io:format("testOneway: ~p~n", [Seconds]), timer:sleep(1000 * Seconds), ok.
