1

I am attempting to implement a live polling of a php script loop with no luck thus far in my attempts. Here is what I have thus far:

On form submit:

$.ajax({
data: $(this).serialize(),
success: showResponse,
url: 'process.php',
type: 'post'
});

function showResponse(){
$.ajax({
type: "GET",
url: "progress.php",
cache: false,
success: function(data) {
var response = $.parseJSON(data);
if (response.processing === true) {
console.log("Current Item: " + response.currentItem +
"Total Items: " + response.totalItems +
 "Percent Complete: " + response.percentComplete);
setTimeout(checkProgress, 1000);
});
}

In the process.php script:

session_start();
echo json_encode(array("processing" => true));
$totalItems = 10000000;
$_SESSION['totalItems'] = $totalItems;
$_SESSION['processing'] = true;
$_SESSION['error'] = false;
for ($i=0; $i <= $totalItems; $i++) {
$_SESSION['currentItem'] = $i;
$_SESSION['percentComplete'] = round(($i / $totalItems * 100));
}

In the progress php script:

session_start();
echo json_encode(array(
"processing" => $_SESSION['processing'],
"error" => $_SESSION['error'],
"currentItem" => $_SESSION['currentItem'],
"totalItems" => $_SESSION['totalItems'],
"percentComplete" => $_SESSION['percentComplete']
)
);

Not sure where I am going wrong here but all it does is loop once it hits 100% complete. Any suggestions would be greatly appreciated!

EDIT I changed the above to using apc in the process.php:

apc_store('totalItems', $totalItems);
apc_store('processing', true);
apc_store('error', false);
apc_store('currentItem', $i);
apc_store('percentComplete', round(($i / $totalItems * 100)));

And within the progress.php:

echo json_encode(array(
"processing" => apc_fetch('processing'),
"error" => apc_fetch('error'),
"currentItem" => apc_fetch('currentItem'),
"totalItems" => apc_fetch('totalItems'),
"percentComplete" => apc_fetch('percentComplete')
    )
);

Still doesn't work properly the way I am wanting it to work, am I doing something incorrectly? It only shows false values until the script completes and shows 100% just like the session use was doing before. Any ideas?

1 Answer 1

5

The session information is a resource that can only be used exclusively, and you have not taken this into account.

Specifically, under default settings session_start causes PHP to acquire an exclusive lock on a file that contains the session data. This file is not unlocked until the script exits or session_write_close is called.

In your example, process.php acquires the lock and starts working. In the meantime, progress.php tries to session_start() and cannot (due to the lock). Enough time needs to pass for process.php to complete and exit (thus releasing the lock) before the request for progress information can be satisfied.

A small change you can make that will have immediate effect is to call session_write_close and session_start from within your worker loop:

for ($i=0; $i <= $totalItems; $i++) {
    session_start();
    $_SESSION['currentItem'] = $i;
    $_SESSION['percentComplete'] = round(($i / $totalItems * 100));
    session_write_close();
}

This will allow the two scripts to take turns locking the session storage file, so you will see things working as intended. However, performance will tank (this is a really impolite way to treat the session storage file).

If you had need to do something like this in the real world, it would be necessary to utilize something other than the session data to enable this exchange of information between the PHP scripts (e.g. an in-memory cache like APC or memcached).

Sign up to request clarification or add additional context in comments.

2 Comments

I have apc installed I didn't even think to use that... I wasn't too concerned about performance as this script is only run by a single user once a week but I will give apc cache a try.
Thanks for this! Got it to work. Just had to check that the session hasn't been started yet if(session_status() == PHP_SESSION_NONE) { session_start(); }.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.