tags:

views:

139

answers:

7

How can I have PHP 5.2 (running as apache mod_php) send a complete HTTP response to the client, and then keep executing operations for one more minute?

The long story:

I have a PHP script that has to execute a few long database requests and send e-mail, which takes 45 to 60 seconds to run. This script is called by an application that I have no control over. I need the application to report any error messages received from the PHP script (mostly invalid parameter errors).

The application has a timeout delay shorter than 45 seconds (I do not know the exact value) and therefore registers every execution of the PHP script as an error. Therefore, I need PHP to send the complete HTTP response to the client as fast as possible (ideally, as soon as the input parameters have been validated), and then run the database and e-mail processing.

I'm running mod_php, so pcntl_fork is not available. I could work my way around this by saving the data to be processed to the database and run the actual process from cron, but I'm looking for a shorter solution.

+2  A: 

What about calling a script on the file server to execute as if it had been triggered at the command line? You can do this with PHP's exec.

SorcyCat
+1, something like `Gearman` is already set up for it (but other / ones own solutions are of course equally valid).
Wrikken
+4  A: 

Have the script that handles the initial request create an entry in a processing queue, and then immediately return. Then, create a separate process (via cron maybe) that regularly runs whatever jobs are pending in the queue.

Alex Howansky
This the solution I originally had in mind. On the other hand, setting up a processing queue for the sole purpose of working around a timeout in a third party application makes me feel a bit uneasy.
Victor Nicollet
This is what I ended up doing, for lack of a portable fork-based solution...
Victor Nicollet
+1  A: 

You can use the PHP function register-shutdown-function that will execute something after the script has completed its dialog with the browser.

See also ignore_user_abort - but you shouldn't need this function if you use the register_shutdown_function. On the same page, set_time_limit(0) will prevent your script to time out.

ring0
Apparently, according to the docs, register_shutdown_function is called before the script completed the dialog since 4.1.0. Your other link, however, contains a promising comment: http://www.php.net/manual/en/features.connection-handling.php#89177 I'll try to delve deeper into this and report back here.
Victor Nicollet
A: 

Bah, I misunderstood your requirements. Looks like they're actually:

  • Script receives input from an external source you do not control
  • Script processes and validates the input, and lets the external app know if they're good or not and terminates the session.
  • Script kicks off a long-running proccess.

In this case, then yes, using an outside job queue and/or cron would work. After the input is validated, insert the job details into the queue, and exit. Another script can then run, pick up the job details from the queue, and kick off the longer process. Alex Howansky has the right idea.

Sorry, I admit I skimmed a bit the first time around.

Ryan Chouinard
A: 

You can split these functions into three scripts. 1. Initiate process and call second one via exec or command, this is also possible to run via http call. 2. second one will run database processing and at the end will start last one 3. last one will email

Aram
A: 

What you need is this kind of setup

alt text

Yanick Rochon
A: 

I would recommend spawning a new async request at the end, rather than continuing the process with the user.

You can spawn the other request using the answer here: http://stackoverflow.com/questions/124462/asynchronous-php-calls/2924987#2924987

UltimateBrent