[erlang-questions] Troubleshooting using YAWS + SOAP

David Mercer <>
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: 
[mailto:] 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