Travis February 2016

PHP script continuing to run after page close [initiated from AJAX]

Everything I google tells me this should not be happening, however it is.

I'm building a migration tool to build a 'master database'. I have an admin panel, only accessible to a few select people. There is a merge button that starts an AJAX call to run the migration php function. I'm not positive how long this script takes considering I'm still developing it but none the less I'm expecting a minimum of 20 minutes once pushed to production and populated with the production database. I do NOT need a lecture on best practices telling me not to do it via a GUI. This will become a cron as well, however I want to be able to induce it manually, if the admin desires.

So here's my process. The migration function immediately closes the session session_write_close() allowing me to run multiple php scripts simultaneously. I do this because I start a setInterval that checks to see a session variable. This is my 'progress' which is just an int on what loop iteration I'm on. In my migration script I open sessions, add 1 to that int, and close the sessions again. I do this at the end of each loop.

By doing this I have successfully created a progress for my AJAX. Now I noticed something. If I start my migration, then close out of my tab - or refresh. Once I reload the page my progress continues to grow. This tells me that the migration script is still executing in the background.

If I close 100% out of my browser, or clear my sessions I no longer see progress go up. This however is not because the script stops. This is because my progress indication relies on sessions and once I clear my sessions or close out my browser my session cookie changes. However I know the script is still running because I can query the database manually and see that entries are being added.

NOW to my question: I do NOT want this. If my browser closes, if I press refresh, if I loose connection, etc I want the script to be TERMINATED.

Answers


Travis February 2016

I am, and did, go with the solution to ping from the client to indicate if the client is still alive or not.

So essentially this is what I did:

From the client, in javascript, I set up a setInterval to run every 1.5 seconds and that hits a php script via AJAX. This php script updates a session variable with the current timestamp (this could easily be a database value if you needed to, however I didn't want the overhead of another query).

$_SESSION['migration_listsync_clientLastPing_'.$decodedJson['progressKey']] = time();

Then, inside my migration function I run a check to see if the 'timestamp' is over 10 seconds old, and if it is I die - thus killing the script.

if(isset($_SESSION['migration_listsync_clientLastPing_'.$progressKey])){
    $calc = time() - $_SESSION['migration_listsync_clientLastPing_'.$progressKey];
    if($calc > 10){
        die();
    }
}

I added a 'progressKey' param which is a random number from 1-100 that is generated when the function is called. This number is generated in javascript and passed into both of my AJAX calls. This way if the user refreshes the page and then immediately pressed the button again we won't have 2 instances of the function running. The 'old' instance will die after a few seconds and the new instance will take over.

This isn't an ideal solution however it is an effective one.

Post Status

Asked in February 2016
Viewed 1,089 times
Voted 14
Answered 1 times

Search




Leave an answer