Percentage of process - php

I do a post with jQuery to a PHP script that do some tasks.
$.post("script.php", params, function(data) { // task done }
In script.php I know in each moment how much percentage of the complete task have been done. At the end, PHP writes a json_encode() string with the data that the first HTML receives and then completes the $.post call.
What I'd like is to tell (for example, each second) from script.php to the HTML the percentage of the tasks done (to print that in screen)
Is that possible ?

You can store the status of your php script server side with memcached or even a single text file.
Create a php that reads out this status, and return its value.
Now start your script, and also start the status checking, which you can run every 1000 ms.

It's technically possible, with a keep-alive connection, but it's complicated to implement.

Related

Getting real time feedback from a server process [in PHP]

Requirement:
I need to run a background process (per a user request) that takes about 30 to 60 seconds to complete. I'd like to give the user some status feedback. Note: Toly is right, 'Background' is not required.
What's working:
The process prints about 20 status messages during this time and I retrieve them with a proc_open and listening on a read pipe using fgets. I can save those messages into a session var and using timestamps (to help debug) I can see that the session array is getting written to with these messages as the process progresses.
The Trouble:
My plan was to poll the server with ajax calls (every sec) to retrieve these session vars for display in the DOM. The bottleneck seems to be that the server cannot service the ajax request while it's still running the background process. Everything dumps out at once when the background process completes. From what I can tell, the issue is not with output buffering because using (debugging) timestamps saved with each process message shows the server is writing to the session var sequentially, so that's how I know the proc_open and pipe reads are working as I expect. The issue appears to be the server not being able to give the AJAX request it's JSON object until it is done with the process; or, probably more accurately, done with the loop that is reading the pipe.
Obvious Misconception:
I thought sending a process to the background (using &) might give me a solution here. Apparently I do not know the difference between a background process and a forked process. What benefit is gained - if any - by running a process in the background when doing so appears to make no difference to me in this scenario?
Possible Solutions:
I do not expect the user initiated process that runs this
process/scenario to be that heavy, but if there's something I can
build into this solution that would help a heavy load then I would
like to do that now.
Is this a multi-threading (pthreads) or a
multi-process (fork) solution?
Or, should I save a process id,
let go polling it with a while( .. fgets ..) statement and then
come back to the process after the server has serviced the ajax
request?
I suppose I could run fake status messages and then
response accurately when the results come back after completion.
The time to process the request is not dependent upon the user, so
my fake timing could be pretty accurate. However, I would like to
know what the solution would be to provide real-time feedback.
After google-ing one day for a technique to get the same behavior you are describing here I come up with an easy solution for my project.
A bit of important theory:
- session_start () and a set like $_SESSION["x"] = "y" will always lock the session file.
Case scenario:
- A - process.php - running through an ajax call
- B - get_session.php - a second ajax call;
The main problem is/was, that even if you set a $_SESSION inside a process that is being run through an AJAX it will always have to wait the for the session file to get unlocked and it will result into a sync between the two processes (A. + B.) - both finishing at the same time!
So, the easiest way to fix this matter and get a good result is by using session_write_close() after each set. E.g.:
%_SESSION["A"] = "B";
$_SESSION["x"] = "y";
session_write_close();
PS: Best approach is to have a customed set of functions to handle the sessions.
Sorry for the mark-up. I just created an stack account.
Why would you think that you need a background process? Also, where did you get the idea that you needed one?
A normal php script, with sufficient time out set, with flush() function used every step of the way will give you the output you need for your AJAX.
What's even easier, since you use sessions - AJAX request to a separate handler, that will just check what's in session, and if there is smth new - will return you the new part.
$_SESSION['progress'] = array();
inside process.php
$_SESSION['progress'][] = 'Done 5%';
// complete some commands
$_SESSION['progress'][] = 'Done 10%';
inside ajax.php
if(count($_SESSION['progress']) > $_GET['laststep']) {
// echo the new messages
}
inside your normal page
$.ajax('ajax.php', 'GET', 'laststep=1', success: function(data){ show(data);})
Something like that should work.

Javascript getting progress of PHP-script

I need to provide interaction between js on html-page and php-script.
- Use AJAX.
Ok. But the problem is that php-script executing for a long time, and i need to know the state of this script processing (e.g. 60% complete)
What should i do? Create 2 php-scripts (client&server) and do ajax-request to client.php which will do requests to server.php via sockets or smth?
Are there more elegant solutions?
What if you had the script doing the processing write its status to a file once in awhile. Make a second script that will read the file and return the status of the original one.
You should never have a long-running process being executed entirely within an HTTP session.
A simple and common approach to this problem is message queuing. Basically, you have your UI queue up the request into a database table and then have external daemon(s) process the queue.
To provide feedback, have the daemon periodically update the table with the status for the row it's currently working on. Then, your javascript code can make AJAX requests to a script that retrieves the status for that work item from the database and displays it to the user.
See: Dealing with long server-side operations using ajax?
Ajax call php script and return information that script is runing.
Main script create lock.file.
Script called from cron is checking if lock.file exists and run the correct script.
The correct script saves the current progress into progress.txt.
Ajax is reading progress.txt and when progress is 100% then return information that script processing is finished.
edited: Thanks to Justin for poiting the timeout problem ;)
If you want to be really fancy, write output from the php script to stdout, and capture it via a pipe. This would require running the php script using exec() or proc_open() (http://php.net/manual/en/function.proc-open.php) and pipe the output to a file (or if you want to be extra-extra fancy, use node.JS to listen for that data)
There are quite a few ways to accomplish this:
Node.JS
An Ajax query every x seconds
A META/Javascript page reload
An iframe that is routinely reloading with the status in it.
Good luck!
You could use PHP's output buffering (see ob_flush) to flush the contents at certain points in your script and tailor your JavaScript so that it uses the flushed contents. I believe readyState in your AJAX call won't be set to 4 on flushes so that's where you'll have to handle that yourself (see this article). I think its a much nicer way than writing to a file and checking the contents of that.
on your process.php:
// 1st task
$_SESSION['progress'] = 0;
// your code for the first task here ...
// 2nd task
$_SESSION['progress'] = 10;
// you code for 2nd task ...
// 3rd task
$_SESSION['progress'] = 17;
// continue ...
// everything finished?
$_SESSION['progress'] = 100;
on your progress.php:
// simply output
echo $_SESSION['progress'];
now from your client-side, just make a request to your progress.php, receive the number and give it to your progress bar ...
didn't check that by myself, but hope that it works! :)

using AJAX with php to display the data on the web page after some calculation is finished

Here's the situation. I have a php file. I can get the value in one of the variables array in this php file really fast. But further processing on the data inside the array takes too long resulting into timeout. I would like to use AJAX so that when the page is loaded, the processed result is displayed and updated as soon as individual data inside the variable array is processed.
Any example would be highly appreciated.
An easier way to do this might be to turn off buffering, have a look at the PHP flush method, the comments explain a neat method you could try
You can then do your processing at the bottom of your page (after flushing the output) after the closing </html> tag and update your results with javascript when the processing has completed
Steps to follow (I would call this a "standard way" of doing what you need):
request that generates page stores to DB data that should be processed
cron job runs in background and
periodically checks if mentioned DB
has any data to process; if yes, it
starts processing data; after
processing it stores results to DB
ajax script that's located in
page periodically (say, once in 15
seconds; depends on how long it
takes to process the data) connects
to server to check if data is
already processed; if it is, it
loads results, if no, it may load
some status information - like
number of jobs in queue or something
like "15% done"
You might also think about using some flash client and java server to communicate over plain TCP socket connection to get the data faster and with smaller overhead.

Getting XMLHttpRequest Progress from PHP Script

I am using javascript to run a XMLHttpRequest to a PHP script which returns data. Basically I want to be able to provide the user with a progress bar (instead of a spinning circle or something) that shows the progress of getting and receiving the data. I know if I was getting a file, I could just check the content length header and use that, but in the case of a script, you don't know how much data it's retrieving.
The answer to this might be as easy as, "it's not possible," because right now it seems that way. But in conclusion: How do you monitor progress of a running script (php) over and XMLHttpRequest?
If you're using FireFox (and I'm fairly sure most other browsers other than IE), then there is indeed a way to report how much data has been transferred during an XHR operation. If the operation in question sends the correct header, it's fairly easy to use this information to calculate the percentage of the data downloaded.
I wrote this code for determining the percentage of data transferred in an XHR operation years ago, so I apologize for it not reflecting the years of coding experience I've gained since. I almost certainly wouldn't write it this way now! Still, I managed to fish it out, and hope it's of use for you.
At the time this was written, IE7 was the latest version of Explorer available, and I remember the code didn't work in that, hence it contains code to prevent it initializing under IE. I've never tried this code out under version 8 or the beta of version 9, and it may indeed work in those versions as well, but I can't vouch for it. If you can get it working in a new version of IE, please let me know!
It works by running code in beforeSend (a callback jQuery provides for code you want to run before starting an ajax request) to set up a Javascript interval (in the code I've put 50 miliseconds, which is probably far too often. 200 miliseconds should still be plenty, and put less strain on the system). Every time the interval timer fires, it runs a function that looks at the responseText attribute of the XHR request. The responseText attribute holds the raw text of the data received thus far. By counting how many characters are in there with the length() string method, we can work out how many bytes have been collected so far.
As far as working out the percentage of total data to be sent, this will require that your server side code sends a content-length header with an accurate count of how many bytes it is going to send. This will require a little cleverness on your part, but shouldn't prove too difficult. If you send an accurate content-length header, then it is used to calculate a percentage of data received so far. If you don't set a content header, then the amount of data received so far is displayed instead.
<script type="text/javascript">
$.ajax ({
beforeSend : function (thisXHR)
{
// IE doesn't support responseText access in interactive mode
if (!$.browser.msie)
{
myTrigger = setInterval (function ()
{
if (thisXHR.readyState > 2)
// When there is partial data available use it to determine how much of the document is downloaded
{
var dlBytes = thisXHR.responseText.length;
if (totalBytes == -1)
totalBytes = thisXHR.getResponseHeader ('Content-length');
(totalBytes > 0)?
$('#progress').html (Math.round ((dlBytes / totalBytes) * 100) + "%"):
$('#progress').html (Math.round (dlBytes / 1024) + "K");
}
}, 50); // Check the status every 50 miliseconds
}
},
complete : function ()
{
// Kill the download progress polling timer
if (myTrigger)
clearInterval (myTrigger);
}
});
</script>
Off the top of my head you could use 2 ajax requests. One to start and wait for the job to complete, and another to check on the job progress. I'm pretty sure most browsers can do at least 2 ajax requests at a time.
The PHP script (Lets call it job.php) that's actually doing the job can update the session variable $_SESSION['job_progress'] with the percentage the job is complete.
You have another PHP script (Lets call it progress.php) that echos that value, i.e.
<?php echo $_SESSION['job_progress'];
Client side you fire off your ajax request to job.php. You have another ajax request to progress.php that runs every 3 seconds. You update your progress bar with the value returned.
You could also do this with one ajax request if the request to job.php returns before the job is finished. Then you can keep using a single ajax request to ping the progress.php script.
In some browsers (firefox for one), onreadystatechange with readyState 3 (i.e. loading) is invoked mutiple times so download progress could be monitored.
Also, in some browsers the responseText property contains the result returns so far, and it could be examined to get some idea of the progress.
However, Internet Explorer (at least for IE7, not sure about later) does not support this, and it is an error to query responseText or responseBody for readyState 3. I have also heard the IE only calls onreadystatechange once with readyState 3 which would make it pretty useless for your purpose, but I would suggest testing it out.
Create a session. (Probably, you already have one).
Create a UID for the query, when you request it to start processing.
Store somewhere on the server (in database, in file, etc) a progress together with the SID+UID, as the query progresses.
Use a second ajax request with timer to poll the progress by SID+UID.
*You can get by only UID, probably, but I've found it to be more manageable when you also could monitor tasks by user/session.

PHP display progress messages on the fly

I am working in a tool in PHP that processes a lot of data and takes a while to finish. I would like to keep the user updated with what is going on and the current task processed.
What is in your opinion the best way to do it? I've got some ideas but can't decide for the most effective one:
The old way: execute a small part of the script and display a page to the user with a Meta Redirect or a JavaScript timer to send a request to continue the script (like /script.php?step=2).
Sending AJAX requests constantly to read a server file that PHP keeps updating through fwrite().
Same as above but PHP updates a field in the database instead of saving a file.
Does any of those sound good? Any ideas?
Thanks!
Rather than writing to a static file you fetch with AJAX or to an extra database field, why not have another PHP script that simply returns a completion percentage for the specified task. Your page can then update the progress via a very lightweight AJAX request to said PHP script.
As for implementing this "progress" script, I could offer more advice if I had more insight as to what you mean by "processes a lot of data". If you are writing to a file, your "progress" script could simply check the file size and return the percentage complete. For more complex tasks, you might assign benchmarks to particular processes and return an estimated percentage complete based on which process has completed last or is currently running.
UPDATE
This is one suggested method to "check the progress" of an active script which is simply waiting for a response from a request. I have a data mining application that I use a similar method for.
In your script that makes the request you're waiting for (the script you want to check the progress of), you can store (either in a file or a database, I use a database as I have hundreds of processes running at any time which all need to track their progress, and I have another script that allows me to monitor progress of these processes) a progress variable for the process. When the process begins, set this to 1. You can easily select an arbitrary number of 'checkpoints' the script will pass and calculate the percentage given the current checkpoint. For a large request, however, you might be more interested in knowing the approximate percent the request has completed. One possible solution would be to know the size of the returned content and set your status variable according to the percentage received at any moment. I.e. if you receive the request data in a loop, each iteration you could update the status. Or if you are downloading to a flat file you could poll the size of the file. This could be done less accurately with time (rather than file size) if you know the approximate time the request should take to complete and simply compare against the script's current execution time. Obviously neither of these are perfect solutions, but I hope they'll give you some insight into your options.
I suggest using the AJAX method, but not using a file or a database. You could probably use session values or something like that, that way you don't have to create a connection or open a file to do anything.
In the past, I've just written messages out to the page and used flush() to flush the output buffer. Very simple, but it may not work correctly on every web server or with every web browser (as they may do their own internal buffering).
Personally, I like your second option the best. Should be reliable and fairly simple to implement.
I like option 2 - using AJAX to read a status file that PHP writes to periodically. This opens up a lot of different presentation options. If you write a JSON object to the file, you can easily parse it and display things like a progress bar, status messages, etc...
A 'dirty' but quick-and-easy approach is to just echo out the status as the script runs along. So long as you don't have output buffering on, the browser will render the HTML as it receives it from the server (I know WordPress uses this technique for it's auto-upgrade).
But yes, a 'better' approach would be AJAX, though I wouldn't say there's anything wrong with 'breaking it up' use redirects.
Why not incorporate 1 & 2, where AJAX sends a request to script.php?step=1, checks response, writes to the browser, then goes back for more at script.php?step=2 and so on?
if you can do away with IE then use server sent events. its the ideal solution.

Categories