跳到主要内容
本页尚未翻译

下面显示的是英文原文。

HeaderField

Each field of a headers struct without a role is a header: strings and bytes as they are, numbers in decimal, times in RFC 3339, None left out.

The header's name is the field's column name, as sqlx's rename and rename_all set it. Its value comes from HeaderField:

Field typeHeader value
String, Vec<u8>its bytes
integers, boolits decimal text, true or false
chrono::DateTime<Utc> (feature chrono), time::OffsetDateTime (feature time)its RFC 3339 text
Option<T>the value of T; None leaves the header out

A service implements HeaderField for a type of its own. A field of a type without it does not compile, and the error offers the impl or a role. The fields that play a role are not headers: the handler reads them on the message.

The header map is built on the first read of the delivery's headers, by middleware or an extractor such as Headers<T>, and a delivery whose headers nobody reads never builds it. A message published into the table through a repository carries only the headers the headers struct names, and a publish with another header fails with SqlxBrokerError::Header, so no header is lost on the way into the table. By hand, HeaderFields builds the map with put_header, which writes each value through its HeaderField.

Example​

A shipment's headers are a carrier of the service's own type, an order number, a flag, a time and an optional trace; the handler writes them to an audit table as the header map holds them.

use ruststream_sqlx::HeaderField;

#[derive(Debug, Clone, InboxHeaders, sqlx::FromRow)]
#[inbox(table = "shipment_jobs")]
struct ShipmentHeaders {
#[field(id, generated)]
job_id: i64,
#[field(locked_until)]
locked_until: Option<DateTime<Utc>>,
// Each field without a role is a header named after its column.
carrier: Carrier,
order_id: i64,
express: bool,
placed_at: DateTime<Utc>,
trace: Option<String>,
}

/// A carrier, kept by its code in the table and named in capitals in the header.
#[derive(Debug, Clone, sqlx::Type)]
#[sqlx(transparent)]
struct Carrier(String);

impl HeaderField for Carrier {
fn header(&self) -> Option<Vec<u8>> {
Some(self.0.to_uppercase().into_bytes())
}
}