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

下面显示的是英文原文。

InboxHeaders

In the headers layout a headers struct describes the queue table and its header fields, and the message struct that flattens it is what a handler takes.

Two structs describe one queue. The headers struct derives InboxHeaders and describes the table: #[inbox(table, schema, advisory_lock, clock, isolation, mode)] and the fields that play a role, so it also selects the form. Its other fields are the delivery's header values. The message struct derives Inbox and holds the headers struct in a field marked #[field(headers)] and #[sqlx(flatten)], beside data of its own. It takes #[inbox(custom(..))] alone, and a role or a table attribute on it does not compile, with an error that names the headers struct as the place for it.

The headers layout is row mode: a handler takes the message struct itself, or a slice of them in a batch. Several message structs may flatten one headers struct, each read by its own subscriptions. The claim selects the ids of the rows it takes, and the default fetch reads their rows from the queue table, the headers struct's columns and the message's own fields. A subscription prepares that fetch when it opens, so a message field whose column the table lacks stops startup with SqlxBrokerError::Schema. A message whose data lives in other tables reads it with a fetch of its own.

The headers struct gets the generated insert, and the message struct gets none. By hand, one description on the message holds the whole table: .data(..) names the header columns, .fetching(..) the message's own, and .header_fields() builds the header map through HeaderFields and put_header.

Example​

A packing job: OrderHeaders describes order_jobs and its headers tenant, trace and order_id, and OrderJob adds the job's note.

/// The queue table: the columns that run the queue, and the headers `tenant`, `trace` and
/// `order_id`.
#[derive(Debug, Clone, InboxHeaders, sqlx::FromRow)]
#[inbox(table = "order_jobs")]
struct OrderHeaders {
#[field(id, generated)]
job_id: i64,
#[field(attempt, generated)]
attempt: i16,
#[field(locked_until)]
locked_until: Option<DateTime<Utc>>,
tenant: String,
trace: Option<String>,
order_id: i64,
}

/// A job and its note, read from the queue table by the default fetch.
#[derive(Debug, Clone, Inbox, sqlx::FromRow)]
struct OrderJob {
#[field(headers)]
#[sqlx(flatten)]
headers: OrderHeaders,
note: Option<String>,
}

// The header map is built from `OrderHeaders` on its first read, here by `Headers<Tenant>`.
#[subscriber(InboxQueue::<OrderJob>::new("packing"))]
async fn pack(job: &OrderJob, Headers(tenant): Headers<Tenant>) -> HandlerOutcome {
tracing::info!(
tenant = %tenant.tenant,
order = job.headers.order_id,
note = ?job.note,
"packing"
);
HandlerOutcome::ack()
}