Consuming messages

The core gives you decode + validation + URN routing. The loop that pulls bytes off the broker is yours (or your framework adapter’s).

Decode

use BabelQueue\Codec\EnvelopeCodec;

$envelope = EnvelopeCodec::decode($rawBody); // plain PHP array

Validate before you dispatch

EnvelopeValidator::check() returns a reason (or null if valid), so you can quarantine a message you don’t understand instead of silently dropping it:

use BabelQueue\Validation\EnvelopeValidator;

if ($reason = EnvelopeValidator::check($envelope)) {
    // e.g. EnvelopeValidator::REASON_UNSUPPORTED_SCHEMA_VERSION
    // → dead-letter / quarantine, don't drop.
    return;
}

Reasons include REASON_MISSING_URN, REASON_MISSING_META, REASON_UNSUPPORTED_SCHEMA_VERSION, REASON_INVALID_DATA, REASON_MISSING_TRACE_ID, REASON_INVALID_ATTEMPTS. There is also EnvelopeValidator::isValid($envelope): bool and validate($envelope): void (which throws InvalidEnvelopeException carrying the reason + envelope).

EnvelopeCodec::accepts($envelope) is a quick boolean check for the same consumer-side rules when you don’t need the reason.

Route by URN

$urn = EnvelopeCodec::urn($envelope); // reads `job`, accepting `urn` as an alias

match ($urn) {
    'urn:babel:orders:created' => $handler->handle($envelope['data'], $envelope['meta']),
    default                    => /* apply your unknown-URN strategy */ null,
};

For unmapped URNs, the BabelQueue\Routing\UnknownUrnStrategy constants (FAIL / DELETE / RELEASE / DEAD_LETTER) name the standard choices; see error handling in the wire contract.

Cross-language

Because you decode the canonical envelope, the message may have been produced by any BabelQueue SDK — a Go service, a Python worker, a Node app — and the URN is the only shared contract. See the cross-language example.