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

下面显示的是英文原文。

Struct

on_startup builds one value of any type; a handler takes any of its fields as a State<T> parameter.

on_startup runs once, before any broker connects, and its value becomes the application state. Its future can await: open a pool, connect a client, read a file. on_startup comes before with_broker, because it fixes the state type every handler is checked against. The lifecycle hooks after it receive the same state. #[derive(FromRef)] writes one FromRef impl per field, each cloning that field. A handler parameter State(prices): State<Prices> resolves through that impl before the body runs. A field that is expensive to clone goes behind an Arc, so a delivery pays one reference count. A handler can also borrow the whole state with ctx.state() from its &mut Context<'_, (), AppState> parameter, with no clone. A hand-written FromRef impl builds a value from several fields. A dependency-injection container fills the same role: froodi with RustStream support, or shaku wired by hand.

Example​

/// A price list, loaded once at startup.
#[derive(Clone)]
struct Prices {
per_item: u64,
}

/// The application state: each field is available to a handler as `State<FieldType>`.
#[derive(FromRef)]
struct AppState {
prices: Prices,
}

#[subscriber("orders", reply)]
async fn price(order: &Order, State(prices): State<Prices>) -> Receipt {
Receipt {
order_id: order.id,
total: order.items * prices.per_item,
}
}

fn app() -> impl App {
RustStream::new(AppInfo::new("orders", "0.1.0"))
.on_startup(async move |()| {
Ok::<_, Infallible>(AppState {
prices: Prices { per_item: 25 },
})
})
.with_broker(MemoryBroker::new(), |b| {
b.include(price).out_reply(Publish);
})
}