Skip to content

Concurrencia

Introducción

exclamation

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'),
]);