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.