2

I have a controller with an action that accepts requests over AJAX, does some data manipulation, and returns some data:

function publicDirectoryAjaxSearch(){
    // Check the form token
    JSession::checkToken('get') or die('Invalid Token');

    // Don't show PHP errors in raw output
    ini_set('display_errors', 'Off');

    // Sort out the session status
    $session = JFactory::getSession();
    $session->set('getOrganisationsStatus', 'Searching...');

    // Get orgs
    $response = $this->doPublicDirectorySearch();

    // Get the document object.
    $document = JFactory::getDocument();

    // Set the MIME type for JSON output.
    $document->setMimeEncoding('application/json');

    // Change the suggested filename.
    JResponse::setHeader('Content-Disposition','attachment;filename="result.json"');

    echo json_encode($response);
}

This method can take a while, so I'm using JSession to store a status variable getOrganisationStatus that can be periodically checked via AJAX to see how far the $this->doPublicDirectorySearch() method has gotten...

function doPublicDirectorySearch(){
    ...
    while($running)
         $session->set('getOrganisationsStatus', 'Fetched '.$handled."/".$totalResults." results.");
    ...
}

However, I'm having some issues. If I set the Joomla global config session handler to Database the getOrganisationsStatus session variable always seems to 'lag' 1 data request behind. For example (in prep for this example I cleared all existing sessions):

  1. Make a data request via AJAX to publicDirectoryAjaxSearch
  2. Set an interval to get the request status session variable over AJAX to publicDirectorySearchStatus
  3. Data request still running. Session value changing as $this->doPublicDirectorySearch() works through data
  4. Status call made from setInterval to publicDirectorySearchStatus. Returned session variable is empty (this step repeats over the interval)
  5. publicDirectoryAjaxSearch data request completes. Method returns JSON object
  6. Final status call made over AJAX from setInterval to publicDirectorySearchStatus. Returned data (the session variable) now shows the correct text as set in the data request method.

If I set the Joomla global config to use None as the session handler (i.e. PHP's built in file-based handler) then the script blocks (as PHP locks the session file when a script accesses it, so the AJAX call to find out the status has to wait til the method updating the session variable finishes - defeating the point somewhat).

Where am I going wrong? How can I..

  1. Make a call to get data (takes some time)
  2. Make a separate call to get a session variable that's being manipulated over time by the first call

1 Answer 1

2

All your page requests share the same user session. Thus, if you call several pages, in an asynchronic way, under the same session, you can be finding a race condition. http://en.wikipedia.org/wiki/Race_condition

As PHP is not multithreading, there's no locking mechanisms to avoid these cases.

The best solution is to avoid the condition: reorganize the main loop and move the control to the Ajax side. In this way, the browser calls an initialization, the inner loop as many times as necessary, and the finalization.

  • You have the control so you can show the progress status
  • If you have thousands of items to process you can define discrete batchs of items to process (instead of one by one)
4
  • Thanks for taking the time to answer, however I'm not sure how this applies to my scenario. I have 2 separate AJAX calls to different methods in a given class, both of which are responding (and not blocking). The issue is JSession values seem to be locked until the first call finishes. Or am I missing something? Commented Jul 22, 2014 at 12:39
  • I think the case you are describing is caused by a race condition. At the end, Javascript is running several threads trying to get answers from PHP running a single user session (in a single thread).
    – Anibal
    Commented Jul 22, 2014 at 19:42
  • Using PHP's APC caching mechanism I can make this work, just not with JSession. This makes me think it's not a race condition as it wouldn't work full stop otherwise... Commented Jul 23, 2014 at 12:12
  • PHP's APC works in memory, instead of any disk caching. Therefore, some way of serialization may be ocurring internally.
    – Anibal
    Commented Jul 24, 2014 at 11:46

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.