habit_forming has asked for the wisdom of the Perl Monks concerning the following question:

Oh Monks hear my question! I am at the end the end of my rope.

I am using SOAP::Lite both on the client of service sides of a SOAP client/service situation. I have control of the code (on both sides) and of the web servers (Apache). All on RedHat 7.3 and it works very well, thank you. =) BUT! There is a problem. (The reason I am at the end of my rope is because this problem continues to bite me in the @ss. It is very frustrating.) I need either a CORBA like heartbeat function or some sort of KeepAlive function to keep long-running SOAP RPC function calls from timing out on the client side. I have tried using KeepAlive On under Apache and setting $SOAP::Constants::PATCH_HTTP_KEEPALIVE = 1; on the client side but that does not seem to work.

The only other thing I can think of is trying to somehow use a mulitpart document to send back a "Hey I'm still processing" SOAP reponse such that the connection doesn't timeout.

But before I dive into that I wanted to see if anyone else had a better idea.

Cheers!
--habit

P.S. I'm running over https. Just incase that makes a difference.

Replies are listed 'Best First'.
Re: SOAP::Lite and KeepAlive
by perrin (Chancellor) on Sep 26, 2004 at 03:39 UTC
    There may be a standard answer for how to handle long-running operations with SOAP. There is definitely a standard answer for how to do it HTTP, which is what your SOAP calls are going over. You are supposed to make one short request to start the action going and then periodically check back to see if it's done. See this for example.
Re: SOAP::Lite and KeepAlive
by habit_forming (Monk) on Sep 30, 2004 at 15:03 UTC
    Ok will sending back a multipart document (thru a server push) does work but the only way (I know of) to do that while still allowing something else to do something is alarm because the Perl 5.6.1 that I have does not have threads. I can not use alarm because some of the SOAP cgis I call use SOAP... Spawning a process from the mod_perl SOAP handler is not a good idea because not only does it slow me down but killing it off effectively is troublesome. And if the process is not killed off it becomes a hang-up situation for Apache.

    **sigh**

    I am really not quite sure of what to do.

    Thank you for the comment and link, perrin. But unfortunately launching the process and then periodically checking back is not really an option for me because I never know how long the user code might run. And enforcing a standard time for every function call is a Bad Thing(tm).

    The server push with a multipart document is what I need and it does work. I just have to make it work without alarm.

    --habit
Re: [solved] SOAP::Lite and KeepAlive
by habit_forming (Monk) on Oct 01, 2004 at 16:14 UTC
    Well, after thinking about it quite a bit and exploring some other options I have decided that doing a fork from a mod_perl handler is not really that bad. I took some time and made the child process more robust. What I found out was that forking a child really didn't slow the call down a noticeable difference. Not only that but the advantage of having the heartbeat on a function call is so great that the 0.001ths of a second slow-down I'm seeing is quite acceptable.

    So for those interested this is how it works.

    The SOAP::Lite client makes a standard RPC call. When that call hits the server side (Apache mod_perl) endpoint code a child process is forked and intermittently sends the parent process SIGUSR2. The parent process has a handler for that signal, of course, and even reimplements sleep in such a way that it is not interuptable by SIGUSR2. The SIGUSR2 handler then prints to STDOUT the proper returning HTTP headers with a content type of multipart/x-mixed-replace denoting a server push. This push will then keep the connection back to the client from timing out. Once the real processing has taken place in the parent, the parent kills the child nicely and writes back the response. The final response is captured in SOAP::MIMEParser::decode. But SOAP::MIMEParser::decode doesn't know about multipart/x-mixed-replace, so I had to rewrite/override that function and add about 10 lines of code... no big deal. After fixing up the response from SOAP::MIMEParser::decode everything acts as normal.

    Well that's it. That is how I implemented a heartbeat for my SOAP::Lite long running functions.

    Cheers!
    --habit