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
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.
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 acallback
parameterBrandon’s machine runs BuildMolecule() but knows to grab the
$_POST['callback']
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)
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 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
https://www.php.net/manual/en/function.fastcgi-finish-request.php
If you want to solve it quickly, without building a lot of infrastructure, and you are using Linux, you could use something like this:
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.