Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Causing two things to load in parallel?

I'm writing some PHP that does a fair amount of processing and then generates reports of the results. Previously it would do a periodic flush() but we're moving to Zend Framework and can't do that anymore. Instead, I would like to have some kind of status display that updates while the report is generated. So I made a progress bar that loads in an iframe, added shared memory to the progress bar update action and the report generation action, and caused the output to load via xmlhttprequest. This all works fine. My issue is that the browser wants to do the two requests serially instead of in parallel, so it will request the progress bar and then BLOCK until the progress bar completes BEFORE it requests the actual output. This means that the process will never end since the real work never starts.

I've searched all morning for some way around this and came up empty-handed. Is there some way to cause two connections, or am I just screwed?

My next action will be to break the processing apart some more and make the status updating action do the actual work, save the result, and then use the other action to dump it. This will be really painful and I'd like to avoid it.

Edit: Here is the javascript, as requested:

    function startProgress()
    {
        var iFrame = document.createElement('iframe');
        document.getElementsByTagName('body')[0].appendChild(iFrame);
        iFrame.id = 'progressframe';            
        iFrame.src = '/report/progress';
    }

    function Zend_ProgressBar_Update(data)
    {
        document.getElementById('pg-percent').style.width = data.percent + '%';
        document.getElementById('pg-text-1').innerHTML = data.text;
        document.getElementById('pg-text-2').innerHTML = data.text;
    }

    function Zend_ProgressBar_Finish()
    {
        document.getElementById('pg-percent').style.width = '100%';
        document.getElementById('pg-text-1').innerHTML = 'Report Completed';
        document.getElementById('pg-text-2').innerHTML = 'Report Completed';
        document.getElementById('progressbar').style.display = 'none'; // Hide it
    }

    function ajaxTimeout(){
        xmlhttp.abort();
        alert('Request timed out');
    }

    var xmlhttp;
    var xmlhttpTimeout;

    function loadResults(){
        if (window.XMLHttpRequest){
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }else{
            // code for IE6, IE5
            xmlhttp=new ActiveXObject(\"Microsoft.XMLHTTP\");
        }
        xmlhttp.open(\"POST\",\"/report/output\",true);
        xmlhttp.onreadystatechange=function(){
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                clearTimeout(xmlhttpTimeout);
                document.getElementById('report-output').innerHTML=xmlhttp.responseText;
            }
        }
        var xmlhttpTimeout=setTimeout(ajaxTimeout,600000); // Ten minutes
        xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        xmlhttp.send('".file_get_contents("php://input")."');           
    }

This gets called from the following onload script:

onload="startProgress(); setTimeout(loadResults,1000);"

The issue is not in Javascript. If you put an alert() in there, the alert will be triggered at the right time, but the browser is delaying the second http transaction until the first completes.


Thank you everyone for your input.

I didn't come up with a satisfactory answer for this within the timeframe permitted by our development schedule. It appears that every common browser wants to re-use an existing connection to a site when doing multiple transactions with that site. Nothing I could come up with would cause the browser to initiate a parallel connection on demand. Any time there are two requests from the same server the client wants to do them in a serial fashion.

I ended up breaking the processing into parts and moving it into the status bar update action, saving the report output into a temporary file on the server, then causing the status bar finish function to initiate the xmlhttprequest to load the results. The output action simply spits out the contents of the temporary file and then deletes it.

like image 243
dseagrav Avatar asked Jun 03 '11 18:06

dseagrav


People also ask

What does it mean for two loads to be connected in parallel?

A parallel circuit is one that has two or more paths for the electricity to flow, the loads are parallel to each other.

What would be the effect of adding a load in parallel to a parallel circuit?

Parallel. A parallel circuit has more than one path that current can flow on. Removing or adding loads to a parallel circuit does not affect any other load in the circuit. Most of the electrical circuits in a house, including the lighting and power points, are connected in parallel.

When two or more loads are connected parallel to each other the circuit is called?

A simple loop with all loads connected in line (in series) is called a Series Circuit. · Two loops, both connected to the battery, each with it's own loads is called a Parallel Circuit. · A series circuit is a Voltage Divider.

What causes sudden increase in the total current into a parallel circuit?

As mentioned that this is PARALLEL CIRCUIT, Current can increase only in two conditions: 1) Either resistance decreases (In this case total resistance can be decreased only if another resistor is added in parallel). 2) Voltage, applied to the circuit, increases.


1 Answers

Using two async ajaxes could do the trick. With the first ajax request you should start the process by calling the php-cli to do the actual work deep in the background (so it doesn't expire or cancel) and return the id of the process (task). Now when you have the process id, you can start the periodical ajax to display the process made.

Making a db table containing process_id, state, user would not be a bad thing. In this case even if the user would close the browser while the process is running, the process would continue until done. The user could revisit the page and see the percentage done, because the process running in cli would save the progress into the db table.

like image 134
Anze Jarni Avatar answered Oct 25 '22 21:10

Anze Jarni