Consuming messages

Consumers route on the URN. Map each URN to a handler class in config/babelqueue.php, then process the worker as usual.

Register the handler

// config/babelqueue.php
return [
    'handlers' => [
        'urn:babel:orders:created' => App\Babel\Handlers\OrderCreatedHandler::class,
    ],
    'on_unknown_urn' => 'dead_letter',
];

Write the handler

A handler receives the decoded data, the meta block and the message’s trace_id for cross-service correlation. Implement the optional failed() hook to react when processing throws:

namespace App\Babel\Handlers;

final class OrderCreatedHandler
{
    public function handle(array $data, array $meta, string $traceId): void
    {
        logger()->withContext(['trace_id' => $traceId])
            ->info('Order received', $data);

        // ... your business logic
    }

    public function failed(array $data, ?\Throwable $e): void
    {
        report($e);
    }
}

Run the worker

BabelQueue is a drop-in Laravel queue driver, so you consume with the standard worker — just point it at your polyglot connection:

php artisan queue:work babelqueue

The $traceId ties this consumer’s logs back to the original producer and to every other service that handled the same job — no matter which language emitted it. Exhausted retries and unknown URNs follow your on_unknown_urn / dead_letter policy from Configuration.

That’s the whole loop: any producer, any consumer, one schema.