Does not work: I am trying to run multiple HTTP requests concurrently using Laravel’s HTTP facade.
Unfortunately, Laravel always executes them in sequence when I am using Http::async()->get(...)
:
use IlluminateSupportFacadesHttp;
use GuzzleHttpPromiseUtils;
$promises = [
Http::async()->get('https://postman-echo.com/delay/3'),
Http::async()->get('https://postman-echo.com/delay/3'),
];
$combinedPromise = Utils::all($promises);
$results = $combinedPromise->wait();
Works: If I am using Laravel’s pool API instead the requests are executed concurrently as expected:
use IlluminateSupportFacadesHttp;
use IlluminateHttpClientPool;
$responses = Http::pool(fn(Pool $pool) => [
$pool->get('https://postman-echo.com/delay/3'),
$pool->get('https://postman-echo.com/delay/3'),
]);
Works: Also, using GuzzleHttp directly I am able to execute the requests concurrently:
use GuzzleHttpClient;
use GuzzleHttpPromiseUtils;
$client = new Client([
'base_uri' => 'https://postman-echo.com'
]);
$promises = [
$client->getAsync('/delay/3'),
$client->getAsync('/delay/3'),
];
$combinedPromise = Utils::all($promises);
$results = $combinedPromise->wait();
Versions used: I tested it with "laravel/framework": "9.47.0"
and "laravel/framework": "10.14.1"
in combination with PHP 8.2.1
.
Question: Does anyone know why my Http::async()->get(...)
calls are not executed concurrently but in sequence?
2
Answers
Thanks to @txyoji who pointed me to the correct Laravel code I was able to find a solution that works with Laravel 9 and 10:
Since Laravel 9
PendingRequest.buildClient()
no longer callsPendingRequest.getReusableClient()
to reuse the same GuzzleHttp Client across async requests.PendingRequest.buildClient()
PendingRequest.buildClient()
The code above explicitly sets a GuzzleHttp Client that is then reused across the async requests.
Docs show using pool to accomplish this.
The Http facade returns a IlluminateHttpClientPendingRequest object.
If PendingRequest async() is true, it doesn’t reuse the client.
My guess is each call of the Http facade is providing a separate client object.
Use the same client and it should work.