Skip to main content

AsyncAPI

With the asyncapi feature the generated document carries an x-ruststream-redis extension that says which structure carries a channel and how.

The core builds the AsyncAPI document from the app, before anything connects. The specification has a redis binding, but its objects carry no fields, and a binding key is a closed list. So this crate writes an extension instead, x-ruststream-redis, at the level a binding sits at. The server reports the host and port clients dial. A channel a service reads reports the Redis structure behind it and how the subscription reads it. A channel a service publishes to reports where the publish lands and how.

Everything comes from the service's own declarations: the broker, the descriptors, the policies and the destinations the mount sites resolved. The Redis server's version stays out, because the client learns it only in the handshake. The document is published and shared, so it carries no credential. The binary #[ruststream::app] writes prints the document with asyncapi gen. This crate's asyncapi feature turns on the core's asyncapi feature with it. The core's feature alone produces a document without the extension.

Example​

The dependency line:

ruststream-fred = { version = "0.7", features = ["asyncapi"] }

The service registers its broker under the label redis, the key of its server in the document. cargo run --example redis_asyncapi --features asyncapi -- asyncapi gen prints the document.

fn service(broker: RedisBroker) -> impl App<State = ()> {
RustStream::new(AppInfo::new("orders", "1.0.0")).with_broker_labeled("redis", broker, |b| {
b.include(confirm).out_reply(pubsub::Publish::new());
b.include(run_job)
.out_reply(list::Publish::new().ttl(Duration::from_mins(1)));
b.include(on_event);
b.include(audit);
})
}

#[ruststream::app]
fn app() -> impl App<State = ()> {
let password = env::var("REDIS_PASSWORD").unwrap_or_default();
service(broker(&password))
}