Search code examples
phpajaxcronsleep

Calling the same PHP script containing a sleep function via AJAX or CRON JOB


I have a PHP script which retrieves X records from a database, and loops through them at a rate of 1 every 10 seconds.

The same script must work with both a Cron Job, and an AJAX call via browser.

The cron part seems to work fine, I have a "master" cron job running every minute on my server, which then retrieves jobs defined in a database (with their own timing and configuration) and handles them with a curl_multi_init() logic.

The faulty part is that calling the script via AJAX freezes my entire web application until the script finishes its execution.

Here's the relevant code:

public function getAndHandleData() : array {

  //instantiate db class and variables

  $data = $database->getData();
  $sleepTime = 60/$requestsPerMinute;

  foreach ($data as $k => $v) {

            // call function which does a curl request to a web service
            // handle response

            if ($k !== array_key_last($data)) {
                // wait $sleepTime seconds before doing the next iteration, unless it's the last
                sleep(ceil($sleepTime));  
            }
        }
}

The JQuery AJAX call which freezes my app until it completes:

function apiRequestHandler(type, params) {

    $.ajax({
        type: 'POST',
        url: '/route_calling_the_same_php_function',
        data: {
            'type' : type,
            'params' : params,
        },
        cache: false,
        timeout: 800000,
        dataType: "json",
        success: function (data)
        {
            const success = data['success'] ?? null

            if (success) {...}
         },
         error: {...}
    });
}

            

Solution

  • Solved:

    The problem is caused by PHP session management, which locks the session file when a script is being executed, even if sleeping.

    Using session_write_close() before the loop+sleep solves the app freezing, while the task runs in the background, even if switching to another page.

    Final working pseudo-code:

    public function getAndHandleData() : array {
    
      //instantiate db class and variables
    
      $data = $database->getData();
      $sleepTime = 60/$requestsPerMinute;
    
      // locks session to prevent system freeze
      session_write_close();
    
      foreach ($data as $k => $v) {
    
                // call function which does a curl request to a web service
                // handle response
    
                if ($k !== array_key_last($data)) {
                    // wait $sleepTime seconds before doing the next iteration, unless it's the last
                    sleep(ceil($sleepTime));  
                }
            }
    }