Do not run the script if it is already running

I did not find the answer to this question at all. Hope someone here can help.

I have a PHP script (specifically a WordPress template) that automatically imports and processes images when the user clicks on it. The problem is that image processing takes up a lot of memory, especially if several users access the template at the same time and start image processing. Because of this, my server crashed several times.

My solution was not to perform the image processing function if it was already running. Before running the function, I would check the database record named image_import_running to see if it is set to false. If so, the function would then be executed. The very first thing the function did was set as image_import_running to true. Then, after everything was finished, I returned it to false.

It worked great - theoretically. Since then, the site has not crashed, I can tell you this. But there are two main problems:

  • If the user closes the page while it is loading, the script never completes the image processing and therefore never sets the image_import_running image to false. The template will never process the images again until it manually sets the value to false.

  • If the script expires during image processing - and this is a strong possibility, if there are a lot of images in the queue - you have essentially the same problem as No. 1: the script never reaches the point at which image_import_running returns false.

To handle # 1 (the first of two issues I realized), I added ignore_user_abort(true) to the script. Did it work? I do not know, because No. 2 is still a problem. That I'm at a standstill.

If I could ask the server if the script is working or not, I could do something like this:

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

But how to set this $script_not_running variable? It hits me.

I told you this whole story just in case you have another brilliant solution.

+6
source share
7 answers

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

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

+1
source

As suggested by others, it would be better to transfer image processing from the request itself.

As an interim fix, save the timestamp next to image_import_running when the processing job begins (for example, image_import_commenced ). This is a very crude mechanism, but if you know the maximum execution time of the job before the timeout expires, the script can check if this period has passed.

For example, if image_import_running is still true, but the current time is more than 10 minutes with image_import_commenced , still do the processing.

+1
source

For me, I use only this simple idea with a text document. e.g. run.txt file
at the top of the script use:

 if((file_get_contents('run.txt') != 'run'){ // here the script will work $file = fopen('run.txt', 'w+'); fwrite($file, 'run'); fclose('run.txt'); }else{ exit(); // if it find 'run' in run.txt the script will stop } 

And add this to the end of your script file

 $file = fopen('run.txt', 'w+'); fwrite($file, ''); //will delete run word for the next try ;) fclose('run.txt'); 

This will check if the script is working by checking the contents of runt.txt if the word run exists in run.txt , it will not run

+1
source

Running cron will finally be the best solution. The idea of โ€‹โ€‹storing a URL in a table is a good one.

To answer the original question, you can run the ps auxwww command using exec (Check this page: How to get a list of running php scripts using PHP exec ()? ) And move your function to a separate php file.

 exec("ps auxwww|grep myfunction.php|grep -v grep", $output); 
+1
source

How to set an expiration transition period that will throttle an operation?

 if(!get_transient( 'import_running' )) { set_transient( 'import_running', true, 30 ); // set a 30 second transient on the import. run_the_import_function(); } 
+1
source

I would rather save the job in the database, putting it on hold and setting the cron job to process one job at a time.

+1
source

Just add the following to the top of the script.

 <?php // Ensures single instance of script run at a time. $fileName = basename(__FILE__); $output = shell_exec("ps -ef | grep -v grep | grep $fileName | wc -l"); //echo $output; if ($output > 2) { echo "Already running - $fileName\n"; exit; } // Your PHP  code. ?> 
0
source

Source: https://habr.com/ru/post/951258/


All Articles