skip to Main Content

There are these two applications:

  • WordPress-site with REST-API. Let’s call this Brandon.
  • Another system, using the REST-API. Let’s call this Jeremy.

I know about the WordPress Stack Exchange, but this is more a PHP question than it is a WordPress question (I think).


The problem

Jeremy creates and updates ‘atoms’ on Brandon.

Whenever Jeremy updates an atom on Brandon, then immediately after, an operation called BuildMolecules() runs, that bulks the atoms into groups and updates electron-, neutron- and proton-information on the molecules on Brandon.

But currently, this is being done on Jeremy’s thread. This means that if Jeremy updates an atom, then it has to wait for the BuildMolecules() to finish, before it returns its response. And even worse, if something goes wrong, while BuildMolecules() runs, then Jeremy receives an error, which is wrong (Since the atom got updated as it should). This last thing could and should be solved with try/catch-statements, but still…

How do I make a function that runs immediately after Jeremy updates an atom, without doing it on Jeremy’s thread?


Solution attempts and considerations

CRON-job

I considered running a cron-job every 5-10 seconds, checking if an atom was updated. And if so, then run an update operation. It just feels kind of naughty, since I would have to run this very often, to achieve a smooth integration between Jeremy and Brandon. But this should work. And if the run takes longer than the 5-10 seconds, then I would have to account for that, setting status or something, stopping BuildMolecules() to run twice, where it should only have been run once.

A new thread

Even if I could set up a new thread (I’ve never done anything like that), then I can read in this post here: Creating new thread(?) in PHP that I shouldn’t try to do it.

If WordPress offers a function for it

I looked into WordPress’ REST-documentation, but couldn’t find anything that could help me.

4

Answers


  1. If this were using an MVC framework like Laravel this is the sort of thing I would use the message queue for. If you need to do it in the context of WordPress that’s a tougher problem, but not insurmountable.

    There are standalone message queue implementations in PHP such as Bernard and php-enqueue that could do what you need, but really you’d want to be using Composer to install those,which might be difficult in a WordPress context (though possible – Bedrock is one example of a WordPress boilerplate that uses Composer). Or that might be overkill – you could implement it at a lower level using Redis or RabbitMQ, or just a database table for queued jobs.

    Regardless of how you choose to implement it, the principle is the same – in WordPress, all you do when the request is received is push the minimum of data you need to the queue backend. You have a separate worker process running, and that picks up the data and does the processing. The worker doesn’t necessarily have to be in PHP if that’s not convenient, it just needs to be able to communicate with your backend, and possibly your main application database if you’re not using that as your queue backend.

    Login or Signup to reply.
  2. Would a simple set of trigger mechanisms help?

    Jeremy updates an atom -> this triggers a request to be sent to Brandon to BuildMolecule(), sent in a curl request that doesn’t need to wait for a response. That request has a callback parameter

    $url = 'https://brandon.com/buildMolecule.php';
    $curl = curl_init();                
    $post['callback'] = 'https://jeremy.com/onBuiltMolecule.php'; 
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt ($curl, CURLOPT_POST, TRUE);
    curl_setopt ($curl, CURLOPT_POSTFIELDS, $post); 
    curl_setopt($curl, CURLOPT_TIMEOUT, 1); 
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 1);
    curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 10); 
    curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
    curl_exec($curl);   
    curl_close($curl); 
    

    Brandon’s machine runs BuildMolecule() but knows to grab the $_POST['callback']

    function onCompleteBuildMolecule($moleculeDataArray) {
        $url = $_POST['callback'];
        $curl = curl_init();                
        $post['data'] = $moleculeDataArray; 
        // the rest same as above's cURL 
    

    If this whole setup is too rudimentary, you can also utilize amazon’s SNS service (which provides a more robust wrapper for the same type of interaction)

    Login or Signup to reply.
  3. It depends on how you are calling the REST APIs.

    Is JavaScript involved? If so you could send the atom modification request and not call the build molecules
    on completion but instead just respond ok. Upon receipt of this "ok" you can send a background ajax request to rebuild the molecules.

    If this is a server to server relationship where JavaScript is not available, you can set a setting in the database that the molecules need rebuilding, and have this performed on a regular cron job.

    Lastly you could use the PHP CLI via the system function.

    <?php 
    system("nohup php -f /path/to/rebuild_molecules.php >/dev/null 2>&1 &");
    

    PHP will begin executing the rebuild_molecules script but it will not wait for completion.

    https://linux.die.net/man/1/nohup

    Edit:
    If you use PHPFPM you can also use fastcgi_finish_request

    echo 'ok';
    fastcgi_finish_request();
    do_build_molecules();
    

    https://www.php.net/manual/en/function.fastcgi-finish-request.php

    Login or Signup to reply.
  4. If you want to solve it quickly, without building a lot of infrastructure, and you are using Linux, you could use something like this:

    exec(PHP_BINDIR . "/php /var/www/html/your_php_file.php yourParameter > /dev/null &");
    

    You can also pass CLI parameters and read them in your php file by accessing $argv

    When passing variable parameters please use escapeshellcmd() to escape your variables.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search