Is there a way to execute PHP script if there is NO new requests for some time?

421 views Asked by At

Is there a way in PHP to take some action (mysql insert for example) if there is no new requests for say 1 second?

What I am trying to achieve is to determinate beginning and the end of image sequence sent from a IP camera. Camera sends series of images on detected movement and stops sending when movement stops. I know that camera makes 5 images per second (every 200ms). When there is no new images for more than 1 sec I want to flag last image as end of the sequence, insert a record in mysql, place img in appropriate folder (where all other imgs from the same sequence are already written) and instruct app to make a MJPEG clip of images in that folder.

Right now I am able to determine the first image in the sequence using Alternative PHP cash to save reference time from the previous request but the problem is because next image sequence can happen hours later and I can not instruct PHP to close the sequence if there is NO requests for some time, only when first request of the new sequence arrives.

I really need help on this. My PHP sucks almost as my English... :)

Pseudo code for my problem:

<?php
  if(isset($headers["Content-Disposition"]))
    {
        $frame_time = microtime(true);
      if(preg_match('/.*filename=[\'\"]([^\'\"]+)/', $headers["Content-Disposition"], $matches))
      { $filename = $matches[1]; }
      else if(preg_match("/.*filename=([^ ]+)/", $headers["Content-Disposition"], $matches))
      { $filename = $matches[1]; }
    }
  preg_match("/(anpr[1-9])/", $filename, $anprs);
  $anpr = $anprs[1];
  $apc_key = $anpr."_last_time"; //there are several cameras so I have to distinguish those  
  $last  = apc_fetch($apc_key);
  if (($frame_time - $last)>1)
         {
            $stream = "START"; //New sequence starts
         } else {
            $stream = "-->"; //Streaming
         };
   $file = fopen('php://input', 'r');
   $temp = fopen("test/".$filename, 'w');
   $imageSize = stream_copy_to_stream($file, $temp); //save image file on the file system
   fclose($temp);
   fclose($file);

   apc_store($apc_key, $frame_time); //replace cashed time with this frame time in APC

  // here goes mysql stuff...

  /* Now... if there is no new requests for 1 second $stream = "END";  
  calling app with exec() or similar to grab all images in the particular folder and make 
 MJPEG... if new request arrives cancel timer or whatever and execute script again. */

?>
3

There are 3 answers

0
bytesized On

What if you just keep the script running for 1 second after it stores the frame to check for more added frames? I imagine you may want to close the connection before the 1 second expires, but tomlgold2003 and arr1 have the answer for you: http://php.net/manual/en/features.connection-handling.php#93441

I think this would work for you:

<?php
ob_end_clean();
header("Connection: close\r\n");
header("Content-Encoding: none\r\n");
ignore_user_abort(true); // optional
ob_start();

// Do your stuff to store the frame

$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();     // Strange behaviour, will not work
flush();            // Unless both are called !
ob_end_clean();

// The connection should now be closed

sleep(1);
// Check to see if more frames have been added.
?>

If your server is expected to see a high load, this may not be the answer for you since when receiving 5 frames per second, there will be 5 scripts checking to see if they submitted the last frame.

1
Rustem Gafurov On

Store each request from the camera with all its data and timestamp in a file (in php serialized form). In cronjob run (every 10 seconds or so) a script that reads that file and finds requests that have more then one second after them before the following request. Save the data from such requests and delete all other requests.

0
Andras On

Could you make each request usleep 1.5 seconds before exiting, and as a last step check to see if the sequence timestamp was updated? If yes, exit and do nothing. If no, save the sequence to mysql. (This will require mutexes, since each http request will be checking and trying to save the sequence, but only one must be allowed to.)

This approach would merge the sub-file/script into the php code (single codebase, easier to maintain), but it can possibly balloon memory use (each request will stay in memory 1.5 seconds, which is a long time for a busy server).

Another approach is to make the sub-file/script into a loopback request on the localhost http server, with presumably a much smaller memory footprint. Each frame would fire off a request to finalize the sequence (similarly again, with mutexes).

Or maybe create a separate service call that checked and saved all sequences, and have a cron job ping it every few seconds. Or have each frame ping it, if a second request can detect that the service is already running it can exit. (share state in the APC cache)

Edit: I think I just suggested what bytesized said above.