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. | [reply] |
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 | [reply] [d/l] [select] |
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
| [reply] [d/l] [select] |