Retour au blog
PHP

Traitement asynchrone avec Symfony Messenger

19 Jul 2024 8 min
Symfony Messenger Async

Symfony Messenger : le traitement asynchrone simplifié

Le composant Messenger de Symfony permet de décorréler les traitements longs de vos requêtes HTTP pour une meilleure expérience utilisateur.

Architecture Message/Handler

// Message
class SendNotificationMessage
{
    public function __construct(
        public readonly int $userId,
        public readonly string $content,
    ) {}
}

// Handler
#[AsMessageHandler]
class SendNotificationHandler
{
    public function __construct(
        private NotificationService $notificationService,
    ) {}

    public function __invoke(SendNotificationMessage $message): void
    {
        $this->notificationService->send(
            $message->userId,
            $message->content,
        );
    }
}

Configuration des transports

# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            async:
                dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
                retry_strategy:
                    max_retries: 3
                    delay: 1000
                    multiplier: 2
            failed:
                dsn: 'doctrine://default?queue_name=failed'

        routing:
            App\Message\SendNotificationMessage: async
            App\Message\ProcessOrderMessage: async

Dispatch des messages

class OrderController extends AbstractController
{
    #[Route('/order', methods: ['POST'])]
    public function create(
        MessageBusInterface $bus,
        Request $request,
    ): JsonResponse {
        // Traitement synchrone rapide
        $order = $this->orderService->create($request);

        // Traitement asynchrone
        $bus->dispatch(new SendNotificationMessage(
            $order->getUserId(),
            "Commande #{$order->getId()} confirmée"
        ));

        return $this->json($order, 201);
    }
}

Supervision des workers

  • Utilisez systemd pour gérer les workers en production
  • Configurez --time-limit pour éviter les fuites mémoire
  • Surveillez la file failed pour les messages en erreur
  • Utilisez le middleware de logging pour le débogage