Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't run script if it's already running

Tags:

php

wordpress

I've been completely unsuccessful finding an answer to this question. Hopefully someone here can help.

I have a PHP script (a WordPress template, to be specific) that automatically imports and processes images when a user hits it. The problem is that the image processing takes up a lot of memory, particularly if multiple users are accessing the template at the same time and initiating the image processing. My server crashed multiple times because of this.

My solution to this was to not execute the image-processing function if it was already running. Before the function started running, I would check a database entry named image_import_running to see if it was set to false. If it was, the function then ran. The very first thing the function did was set image_import_running to true. Then, after it was all finished, I set it back to false.

It worked great -- in theory. The site hasn't crashed since, I can tell you that. But there are two major problems with it:

  1. If the user closes the page while it's loading, the script never finishes processing the images and therefore never sets image_import_running back to false. The template will never process images again until it's manually set to false.

  2. If the script times out while it's processing images -- and that's a strong possibility if there are many images in the queue -- you have essentially the same problem as No. 1: the script never gets to the point where it sets image_import_running back to false.

To handle No. 1 (the first one of the two problems I realized), I added ignore_user_abort(true) to the script. Did it work? I don't know, because No. 2 is still an issue. That's where I'm stumped.

If I could ask the server whether the script was running or not, I could do something like this:

if($import_running && $script_not_running) {
    $import_running = false;
}

But how do I set that $script_not_running variable? Beats me.

I've shared this entire story with you just in case you have some other brilliant solution.

like image 762
boulevardofdef Avatar asked Aug 07 '13 21:08

boulevardofdef


3 Answers

Try using ignore_user_abort(true); it will continue to run even if the person leaves and closes the browser.

you might also want to put a number instead of true false in the db record and set a maximum number of processes that can run together

like image 172
Dvid Silva Avatar answered Nov 12 '22 05:11

Dvid Silva


As others have suggested, it would be best to move the image processing out of the request itself.

As an interim "fix", store a timestamp alongside image_import_running when a processing job begins (e.g., image_import_commenced). This is a very crude mechanism, but if you know the maximum time that a job can run before timing out, the script can check whether that period of time has elapsed.

e.g., if image_import_running is still true but the current time is more than 10 minutes since image_import_commenced, run the processing anyway.

like image 20
plasmid87 Avatar answered Nov 12 '22 03:11

plasmid87


What about setting a transient with an expiry time that would throttle the operation?

if(!get_transient( 'import_running' )) {
  set_transient( 'import_running', true, 30 ); // set a 30 second transient on the import.
  run_the_import_function();
}
like image 1
murdaugh Avatar answered Nov 12 '22 03:11

murdaugh