Concurrencia
Introducción
La facade Concurrency
de Laravel está actualmente en beta mientras recopilamos comentarios de la comunidad.
A veces es posible que necesites ejecutar varias tareas lentas que no dependen entre sí. En muchos casos, se pueden lograr mejoras de rendimiento significativas al ejecutar las tareas de forma concurrente. La facade Concurrency
de Laravel proporciona una API simple y conveniente para ejecutar funciones anónimas de manera concurrente.
Compatibilidad de Concurrencia
Si actualizaste a Laravel 11.x desde una aplicación Laravel 10.x, es posible que debas agregar el ConcurrencyServiceProvider
al array providers
en el archivo de configuración config/app.php
de tu aplicación:
'providers' => ServiceProvider::defaultProviders()->merge([ /* * Package Service Providers... */ Illuminate\Concurrency\ConcurrencyServiceProvider::class, // [tl! add] /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, ])->toArray(),
Cómo Funciona
Laravel logra concurrencia serializando las funciones anónimas
dadas y enviándolas a un comando CLI de Artisan oculto, que deserializa las funciones anónimas
y las invoca dentro de su propio proceso PHP. Después de que se ha invocado la función anónima
, el valor resultante se serializa de nuevo al proceso padre.
El Facade Concurrency
admite tres controladores: process
(el predeterminado), fork
y sync
.
El driver fork
ofrece un rendimiento mejorado en comparación con el driver process
predeterminado, pero solo puede usarse dentro del contexto de la CLI de PHP, ya que PHP no admite el forking durante las solicitudes web. Antes de usar el driver fork
, necesitas instalar el paquete spatie/fork
:
composer require spatie/fork
El driver sync
es principalmente útil durante las pruebas cuando deseas desactivar toda la concurrencia y simplemente ejecutar las funciones anónimas
dadas en secuencia dentro del proceso principal.
Ejecutando Tareas Concurrentes
Para ejecutar tareas concurrentes, puedes invocar el método run
de el facade Concurrency
. El método run
acepta un array de funciones anónimas que se deben ejecutar simultáneamente en procesos PHP hijo:
use Illuminate\Support\Facades\Concurrency; use Illuminate\Support\Facades\DB; [$userCount, $orderCount] = Concurrency::run([ fn () => DB::table('users')->count(), fn () => DB::table('orders')->count(), ]);
Para usar un driver específico, puedes usar el método driver
:
$results = Concurrency::driver('fork')->run(...);
O, para cambiar el driver de concurrencia predeterminado, debes publicar el archivo de configuración concurrency
a través del comando Artisan config:publish
y actualizar la opción default
dentro del archivo:
php artisan config:publish concurrency
Diferir Tareas Concurrentes
Si deseas ejecutar un array de funciones anónimas
de manera concurrente, pero no te interesan los resultados devueltos por esas funciones anónimas
, deberías considerar usar el método defer
. Cuando se invoca el método defer
, las funciones anónimas
dadas no se ejecutan de inmediato. En su lugar, Laravel ejecutará las funciones anónimas
de forma concurrente después de que se haya enviado la respuesta HTTP al usuario:
use App\Services\Metrics; use Illuminate\Support\Facades\Concurrency; Concurrency::defer([ fn () => Metrics::report('users'), fn () => Metrics::report('orders'), ]);