Consuming messages

Consuming is a normal Messenger handler. The serializer decodes the inbound envelope, uses the URN → class map to rebuild your message via fromBabelPayload(), and Messenger routes it to the handler for that class.

A handler

use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler]
final class OnOrderCreated
{
    public function __invoke(OrderCreated $message): void
    {
        // $message->orderId === 1042
    }
}

Run the worker exactly as you normally would:

php bin/console messenger:consume babel

How it maps to Messenger

  • Routing is Messenger’s job: the decoded message class is routed to its handler. An inbound URN with no entry in the messages map cannot be rebuilt — keep the registry in sync with the URNs you consume.
  • Retry bridges both ways: Messenger’s RedeliveryStamp ⇄ the envelope’s top-level attempts. Your existing Messenger retry strategy applies unchanged.
  • Tracing: the inbound trace_id is attached as a BabelTraceStamp. With babelqueue.messenger.trace_middleware on the bus, any message a handler dispatches inherits that trace_id, so a whole chain of work stays in one trace.

Cross-language

Because the wire format is the canonical envelope, a message your Symfony app consumes may have been produced by any BabelQueue SDK — a Laravel app, a Go service, a Python worker — and vice-versa. The URN is the only shared contract; no class is shared across languages. See the wire contract and the cross-language example.