[erlang-questions] Troubleshooting using YAWS + SOAP
David Mercer
dmercer@REDACTED
Thu Jul 19 18:10:32 CEST 2007
This kind of email is excellent, describing the problem and explaining the
solution. Thanks for sharing it with us.
Cheers,
David
-----Original Message-----
From: erlang-questions-bounces@REDACTED
[mailto:erlang-questions-bounces@REDACTED] On Behalf Of Laura M. Castro
Souto
Sent: Thursday, July 19, 2007 10:19
To: Willem de Jong
Cc: Lista de Erlang
Subject: Re: [erlang-questions] Troubleshooting using YAWS + SOAP
Hello all,
It seems that we finally found the source of the problem. In the
end, it has
something to do with yaws_soap_srv module, which is the genserver that was
dying with the timeout error. And the reason was in front of our eyes all
the
time, as happens so many times. Let me explain it here for the record.
Remember the "minimal" server that Willem posted in his mail?
> -module(my_soap).
> -export([handler/4]).
>
> -record('p:CodigoVO', {anyAttribs, 'etiqueta', 'valor'}).
> -record('p:setParte', {anyAttribs, 'param0', 'param1', 'param2', 'param3',
> 'param4', 'param5', 'param6'}).
> -record('p:setParteResponse', {anyAttribs, 'return'}).
>
> handler(_Header,
> [#'p:setParte'{'param0' = P0}],
> _Action,
> _SessionValue) ->
> {ok, undefined, setParte(P0)}.
>
> setParte(P0) ->
> CodigoVO = #'p:CodigoVO'{'etiqueta' = P0, 'valor' = 1},
> #'p:setParteResponse'{'return' = CodigoVO}.
As Willem said, this server works out perfectly well, but this is
just
because is *that minimal*. The issue is that the operation being invoked
through the web service (setParte) might not be *that simple*, meaning that
it could potentially be a function that consumes some time to get its
result.
If "some time" is less than 5000 milliseconds, everything is fine.
But what
happens if it's not? Well, the yaws_soap_srv genserver dies. As simple as
that. Why? Because whenever the gen_server:call function is used inside that
module, its third optional parameter (Timeout) is never specified, thus
assuming a default value (guess what: 5000 milliseconds). Check out the
source code:
handler(Args, Id, Payload, SessionValue) ->
(...)
case gen_server:call(?SERVER, {request, Id, Payload,
SessionValue,
SoapAction})
of
{ok, XmlDoc, ResCode, undefined} ->
{false, XmlDoc, ResCode};
{ok, XmlDoc, ResCode, SessVal} ->
{true, 0, SessVal, XmlDoc, ResCode};
{error, _, _} = Error ->
Error;
false ->
false
end.
So what we did is to add the third parameter to the gen_server:call
function
and now everything is working!
handler(Args, Id, Payload, SessionValue) ->
(...)
case gen_server:call(?SERVER, {request, Id, Payload,
SessionValue,
SoapAction},
infinity)
of
{ok, XmlDoc, ResCode, undefined} ->
{false, XmlDoc, ResCode};
{ok, XmlDoc, ResCode, SessVal} ->
{true, 0, SessVal, XmlDoc, ResCode};
{error, _, _} = Error ->
Error;
false ->
false
end.
I understand that an infinite timeout might not be reasonable in all
cases,
maybe even in most of the cases, but you will agree with me that the need
for
a timeout greather than 5000 might not be that strange...
Perhaps, a general solution for this will be to let the client
modules of
yaws+soap configure that timeout option, maybe by means of another field in
the gconf struct.
Regards,
--
Laura M. Castro
MADS Group - Computer Science Department
University of A Corunna
http://www.madsgroup.org/staff/laura/index_en.html
More information about the erlang-questions
mailing list