Skip to main content

Crate reliar_core

Crate reliar_core 

Source
Expand description

reliar-core is the pure envelope/message model every Reliar crate builds on: identity newtypes, the Message contract, a validated Headers map, typed Metadata, and the Envelope/SerializedEnvelope pair that carries them. It has no storage or transport dependency of its own — no sqlx, no broker client, no routing concept (a Kafka partition key, a RabbitMQ exchange, a NATS subject) — so it is useful standalone, as the shared vocabulary two independent Reliar crates (say an outbox and a transport) use to talk to each other, or as a typed envelope model for an application that does not use the rest of Reliar at all.

§The types you touch

  • Message — implement this on your own type to give it a stable, renaming-proof identity (TYPE + VERSION), never derived from std::any::type_name::<T>() or a module path.
  • Envelope<T> / SerializedEnvelope — the same generic type on both sides of serialization: an Envelope<YourType> on the way in, Envelope<bytes::Bytes> once a Serializer has turned the body to bytes. Build one with Envelope::builder.
  • Metadata — canonical, typed framework metadata (correlation, trace, routing, delivery, tenant). One source of truth: a value here is never duplicated into Headers, and Reliar never reads a framework value back out of headers.
  • Headers — your own custom, application-defined metadata. A validating newtype, not a bare map: it rejects the entire reliar- prefix case-insensitively, so a custom header can never collide with — or be mistaken for — a framework one.
  • Serializer (default impl: JsonSerializer, behind the default json feature) — converts a typed body to and from bytes.
  • Publisher — the trait a transport implements to send an envelope; paired with Classify/FailureKind so a caller can tell a retryable failure from a permanent one without inspecting transport internals.
  • uuid_id!/uuid_id_serde! — declare a UUID-backed identity newtype (from_uuid/ as_uuid, optional minting/Default/serde) in any crate; paired with the re-exported uuid so the generated signatures name one Uuid type everywhere.

§End to end

JsonSerializer ships behind the default json feature; without it this block still shows the shape but is not compiled (cargo test --doc --no-default-features would not see JsonSerializer/JsonError).

use reliar_core::{Envelope, JsonSerializer, Message, Serializer};

#[derive(serde::Serialize, serde::Deserialize)]
struct OrderCreated {
    order_id: u64,
}

impl Message for OrderCreated {
    const TYPE: &'static str = "orders.created";
    const VERSION: u16 = 1;
}

// Build a typed envelope; `message_type` and the conversation root are derived, not chosen.
let envelope = Envelope::builder(OrderCreated { order_id: 42 })
    .tenant("acme")
    .build();
assert_eq!(envelope.message_type.to_string(), "orders.created.v1");

// Serialize the body; the serialized envelope is what storage/transport crates see.
let serializer = JsonSerializer;
let bytes = serializer.serialize(&envelope.body)?;
let serialized = envelope.map_body(|_| bytes);
assert_eq!(serialized.metadata.tenant_id.as_deref(), Some("acme"));

Every public error is a hand-rolled, #[non_exhaustive] enum with a wired std::error::Error::source — no thiserror, no anyhow. Debug on payload-bearing types elides the bytes; no Display here ever prints a payload, a header value, or a credential.

Re-exports§

pub use uuid;

Macros§

uuid_id
Declares a UUID-backed identity newtype: Clone + Copy + Debug + Eq + Hash + Ord, from_uuid/ as_uuid, and a Display that renders the inner UUID verbatim. Every id Reliar mints is a UUIDv7 (ADR 0015); an application may supply any UUID and Reliar SHALL NOT inspect or reject its version.
uuid_id_serde
Implements serde::Serialize/Deserialize for a uuid_id!-declared type: the canonical hyphenated UUID string, written with collect_str and read with Uuid::parse_str — never through uuid’s own serde feature, so enabling a caller’s serde feature never has to unify uuid’s feature set.

Structs§

ContentType
A validated MIME type. Owned by the Serializer that produced a payload — never chosen at the call site (ADR 0010).
ConversationId
Groups every message in one business conversation. Always derived, never minted: an un-correlated message roots its own conversation at its MessageId (see crate::EnvelopeBuilder::build), and any other value is inherited from storage or the wire via Self::from_uuid. There is deliberately no new()/Default — a random, unrooted conversation id would silently drop a caller out of the conversation it supplied (ADR 0038); a host that wants to start one names the UUID explicitly.
CorrelationId
Application/business workflow correlation id — distinct from ConversationId (Reliar’s own conversation root) and a causation_id (the direct parent message). Capped at Self::MAX_LEN bytes: it lands in a text column read on every claim.
CorrelationMetadata
Correlation and conversation identity for one envelope.
DeliveryMetadata
Serialization and delivery hints for one envelope.
EndpointAddress
An opaque, transport-interpreted address string (a queue name, a subject, a service name — Reliar does not care which). Capped at Self::MAX_LEN bytes.
Envelope
An envelope: a typed or serialized body plus the metadata Reliar understands and the custom headers it does not. Envelope != OutboxRecord != InboxRecord — nothing here carries delivery state (attempts, leases, dead-letter bookkeeping).
EnvelopeBuilder
Builds an Envelope<T>. Obtained from Envelope::builder.
Headers
Application-defined metadata Reliar does not understand: a validating newtype, never a HashMap alias and never exposed through Deref (ADR 0011). Reserves the entire reliar- prefix (case-insensitive) so framework metadata is never duplicated here — see Metadata for the one canonical source of truth (ADR 0004).
JsonSerializerjson
The default Serializer: JSON via serde_json. Ships behind the default json feature; disable it to supply a different wire format (ADR 0010).
MessageId
Uniquely identifies one envelope end-to-end: enqueue, storage row, wire message, and, if it fails permanently, the dead entry.
MessageType
A message’s name and version, carried separately so a query can filter a name across every version. Renders as "{name}.v{version}" via its Display impl.
Metadata
Canonical, typed framework metadata: the single source of truth. No value here is ever duplicated into Headers (ADR 0004).
RequestId
Correlates an envelope back to the inbound request (HTTP call, RPC, CLI invocation) that caused it, so an outbound message can be traced to its trigger. Always host-supplied: there is deliberately no new()/Default, since a minted request id would claim an inbound request exists when none does (ADR 0038). A host wraps the id it already has with Self::from_uuid.
RoutingMetadata
Transport-independent routing only. Kafka partition keys, RabbitMQ exchanges and NATS subject options are transport concepts and must never appear here — a transport crate derives its own wire-level routing from Self::destination instead, without adding its concept to this struct.
TraceContext
W3C Trace Context, carried verbatim. Reliar never invents or re-derives it (ADR 0004, ADR 0020): a transport mapper writes these from an active span and reads them back on decode.

Enums§

ContentTypeError
ContentType::parse failures.
FailureKind
Whether a failure is worth retrying.
HeaderError
Headers::insert failures.
IdError
Validation failures shared by every capped string identity newtype in reliar-core.
JsonErrorjson
JsonSerializer failures. Display names the operation, the error class (serde_json::error::Category), and the line/column — never serde_json::Error’s own message, which for a data error embeds a fragment of the value it rejected (e.g. invalid type: string "sk-live-…", expected u64). The full underlying error, message included, is still reachable via std::error::Error::source for a caller that deliberately wants it — that caller’s own logging then owns not leaking a payload fragment, the same rule this type upholds by default.
SettingsError
Why a *Settings::from_env call failed. OutboxSettings::from_env (reliar-outbox) was the first caller; every provider’s own from_env returns this same type, so a host wiring several from_env calls handles one error type for the whole family.

Traits§

Classify
Implemented by every crate::Publisher::Error and OutboxStore::Error (reliar-outbox) so a dispatcher can decide retry vs. dead without a downcast. Carried by the error type, not by the publisher: the error value is what crosses a JoinSet boundary into the dispatcher, so it must carry its own verdict (ADR 0008).
EnvelopeMapper
Converts a SerializedEnvelope to and from one transport’s native message type M.
Message
A type that can be built into an Envelope and persisted or published.
Publisher
The wire side of the outbox. One provider implements this per transport.
Serializer
Converts a typed Message body to and from bytes. Lives in reliar-core: it touches neither storage nor transport (ADR 0010).

Type Aliases§

SerializedEnvelope
The persistence/transport form: an envelope whose body has already been serialized to bytes.