The AsyncAPI document
asyncapi gen prints the shop's AsyncAPI document: every topic, who reads and writes it, the schemas, the retry cap, and the description the app gives itself.
The document is built from the app itself, so it cannot describe a topic the code does not use.
Each subscription is a receive operation, each reply and slot a send operation.
A payload's schema comes from its JsonSchema derive, and a doc comment becomes a description.
max_attempts and dead_letter appear on the operation, so a reader sees where a failing message ends up.
AsyncAPI covers servers, security schemes and serving the document over HTTP.
The document needs the crate's asyncapi feature.
The entry point
main.rs builds the shop on the in-memory broker.
#[ruststream::app] gives the binary its commands: run starts the shop, asyncapi gen prints the document.
- Macros
- Manual
/// `run` starts the shop; `asyncapi gen` prints its AsyncAPI document.
#[ruststream::app(flavor = "current_thread")]
fn app() -> impl App<State = Shop> {
service::shop(MemoryBroker::new())
}
fn app() -> impl App<State = Shop> {
service::shop(MemoryBroker::new())
}
/// What `#[ruststream::app]` writes: `run` starts the shop; `asyncapi gen` prints its AsyncAPI
/// document.
fn main() -> ExitCode {
run_main_on(AppRuntime::CurrentThread, app)
}
What the shop says about itself
AppInfo is the document's info block: the title, the version, a description, a contact, a license and tags.
- Macros
- Manual
/// What the AsyncAPI document says about the shop.
fn info() -> AppInfo {
AppInfo::new("shop", "0.1.0")
.description("Takes orders, charges them, ships them and tells the customer.")
.contact(Contact::new().name("Shop team").email("shop@example.com"))
.license(License::new("Apache-2.0"))
.tag(Tag::new("orders"))
}
/// What the AsyncAPI document says about the shop.
fn info() -> AppInfo {
AppInfo::new("shop", "0.1.0")
.description("Takes orders, charges them, ships them and tells the customer.")
.contact(Contact::new().name("Shop team").email("shop@example.com"))
.license(License::new("Apache-2.0"))
.tag(Tag::new("orders"))
}
The document
cargo run --example guide --features testing,macros,memory,json,cbor,asyncapi -- asyncapi gen --yaml
The operation of charge reads the topic, answers on payments.settled, and declares the cap:
receive_payments_requested:
action: receive
channel:
$ref: '#/channels/payments.requested'
messages:
- $ref: '#/channels/payments.requested/messages/PaymentRequest'
description: Charges an order through the payment provider.
reply:
channel:
$ref: '#/channels/payments.settled'
messages:
- $ref: '#/channels/payments.settled/messages/Paid'
x-ruststream-retry:
maxAttempts: 5
deadLetter: payments.dead
Both forms of the shop produce the same document.
A test in each compares the document with examples/guide/asyncapi.json, so a change to a topic shows up in review.