2

Is there a Drupal 8 way to do non-blocking HTTP client request using Guzzle? I don't need to wait for the answer of The HTTP post, as that is slowing down the site.

I already seen Non-blocking asynchronous HTTP requests, but I want to know if someone have a Drupalier solution.

3
  • Maybe you could check to use a Kernel::TERMINATE Event which will keep the synchronous aspect of the request but after the response was sent to the client.
    – Simon Vart
    Sep 15, 2020 at 16:03
  • 1
    Depending on your needs you may move the requests to a Drupal Queue, then perform the requests on cron calls so your site doesn't need to wait for the requests to finish-
    – sanzante
    Sep 15, 2020 at 17:59
  • I thought about the queue, but i can't wait for the cron. So maybe create a queue and start it at the end of my request ?
    – lchabrand
    Sep 15, 2020 at 18:13

2 Answers 2

1

There is no "Drupal 8 way." Drupal 8 relies on Guzzle as its HTTP client library so it doesn't have a built-in solution for this.

While the Guzzle client library has GuzzleHttp\Client::requestAsync(), it's not a non-blocking asynchronous method; the method will block once it has initiated the network request since it needs response data for promise methods.

In order to do something akin to your linked question (using fsockopen() / fwrite() to open a socket, send HTTP headers, & close) with Guzzle, you'll need to use a different handler than the default ones Guzzle provides. Guzzle has some documentation on to do this.

It should be noted, even the linked solution isn't non-blocking in the event there are network connection issues (e.g. if the host is unreachable, fsockopen() has $timeout set to 30, so it would block for 30s before timeout was hit). PHP being single-threaded prevents true non-blocking asynchronous execution within PHP code.

0

One solution for this type of processing is as follows:

Enqueue the item to an async queue worker for processing, where the items are constantly being processed. In this case, using RabbitMQ, which improves upon the core cron queue with an immediate queue processing feature.

  1. Install RabbitMQ and https://www.drupal.org/project/rabbitmq
  2. Add the item to the queue (include settings.php $settings['queue_service_my_queue_name'] = 'queue.rabbitmq.default';)
// Some data to send to the queue
$data = ['nid' => 12, 'url' => 'https://example.com/api'];
// Get the queue config
$queue_factory = \Drupal::service('queue');
$queue = $queue_factory->get('my_queue_name');
// Send data to the queue
$queue->createItem($data);
  1. Define your QueueWorker plugin (note: no need for cron in queue worker annotation)

  2. Process the queue with drush rabbitmq-worker my_queue_name

  3. Add a process manager, such as supervisord, or you can use kubernetes, to maintain the drush queue worker process.

This approach scales well and the queue items can be processed both immediately and asynchronously, in another queue worker process.

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.