Concurrency

Concurrency

Introduction

La fachada Concurrency de Laravel está actualmente en versión beta mientras recopilamos comentarios de la comunidad.

A veces puede necesitar ejecutar varias tareas lentas que no dependen entre sí. En muchos casos, se pueden lograr mejoras significativas en el rendimiento ejecutando las tareas de forma concurrente. La fachada Concurrency de Laravel proporciona una API simple y conveniente para ejecutar cierres de forma concurrente.

Concurrency Compatibility

Si actualizó a Laravel 11.x desde una aplicación Laravel 10.x, es posible que deba agregar el ConcurrencyServiceProvider al arreglo providers en el archivo de configuración config/app.php de su aplicación:

'providers' => ServiceProvider::defaultProviders()->merge([
    /*
     * Package Service Providers...
     */
    Illuminate\Concurrency\ConcurrencyServiceProvider::class, 
 
    /*
     * Application Service Providers...
     */
    App\Providers\AppServiceProvider::class,
    App\Providers\AuthServiceProvider::class,
    // App\Providers\BroadcastServiceProvider::class,
    App\Providers\EventServiceProvider::class,
    App\Providers\RouteServiceProvider::class,
])->toArray(),

How it Works

Laravel logra la concurrencia serializando los cierres dados y enviándolos a un comando CLI Artisan oculto, que deserializa los cierres y los invoca dentro de su propio proceso PHP. Después de que el cierre ha sido invocado, el valor resultante se serializa de vuelta al proceso padre.

La fachada Concurrency admite tres controladores: process (el predeterminado), fork y sync.

El controlador fork ofrece un mejor rendimiento en comparación con el controlador process predeterminado, pero solo puede usarse dentro del contexto CLI de PHP, ya que PHP no admite bifurcación durante las solicitudes web. Antes de usar el controlador fork, necesita instalar el paquete spatie/fork:

composer require spatie/fork

El controlador sync es principalmente útil durante las pruebas cuando desea deshabilitar toda la concurrencia y simplemente ejecutar los cierres dados en secuencia dentro del proceso padre.

Running Concurrent Tasks

Para ejecutar tareas concurrentes, puede invocar el método run de la fachada Concurrency. El método run acepta un arreglo de cierres que deben ejecutarse simultáneamente en procesos PHP secundarios:

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 controlador específico, puede usar el método driver:

$results = Concurrency::driver('fork')->run(...);

O, para cambiar el controlador de concurrencia predeterminado, debe publicar el archivo de configuración concurrency mediante el comando Artisan config:publish y actualizar la opción default dentro del archivo:

php artisan config:publish concurrency

Deferring Concurrent Tasks

Si desea ejecutar un arreglo de cierres de forma concurrente, pero no está interesado en los resultados devueltos por esos cierres, debería considerar usar el método defer. Cuando se invoca el método defer, los cierres dados no se ejecutan inmediatamente. En su lugar, Laravel ejecutará los cierres de forma concurrente después de que la respuesta HTTP haya sido enviada al usuario:

use App\Services\Metrics;
use Illuminate\Support\Facades\Concurrency;
 
Concurrency::defer([
    fn () => Metrics::report('users'),
    fn () => Metrics::report('orders'),
]);