AsyncAPI
With the asyncapi feature the document says ZeroMQ: protocol zeromq, ZMTP 3.0, and the crate's facts under the x-ruststream-zeromq extension.
The core builds the AsyncAPI document from the app, before anything connects.
The specification has no ZeroMQ binding, and its binding keys are a closed list.
So this crate reports everything it knows in one extension, x-ruststream-zeromq, at two levels.
A server says how to attach to the endpoint: the transport, the coordinate and the side this service takes.
A channel says which socket pair its messages travel over and what their name frame holds.
A responder's reply channel has no address, and the operation points a client at the reply address instead.
Everything comes from the service's own declarations: the brokers, their endpoints and the destinations the mount sites resolved.
The binary #[ruststream::app] writes prints the document with asyncapi gen.
Peers in other languages reads from the document how a peer joins each channel.
Example
The dependency line:
ruststream-zeromq = { version = "0.7", features = ["asyncapi"] }
The service registers each broker under a label, the key of its server in the document.
cargo run --example zmq_asyncapi --features asyncapi -- asyncapi gen prints the document.
- Macros
- Manual
#[ruststream::app]
fn app() -> impl App {
// Each label is the key of the broker's server in the document.
RustStream::new(AppInfo::new("worker", "0.1.0"))
.with_broker_labeled("jobs", jobs(), |b| {
b.include(work).out_reply(ZmqQueuePublish);
})
.with_broker_labeled("rpc", greeter(), |b| {
b.include(greet)
.out_reply(ZmqRpcPublish)
.transform(ReplyToRequester)
.out_retry(ZmqRpcPublish)
.to("greeter.retry");
})
}
fn app() -> impl App {
// Each label is the key of the broker's server in the document.
RustStream::new(AppInfo::new("worker", "0.1.0"))
.with_broker_labeled("jobs", jobs(), |b| {
b.include(subscriber("jobs", Work).reply().to("results").build())
.out_reply(ZmqQueuePublish);
})
.with_broker_labeled("rpc", greeter(), |b| {
b.include(subscriber("greeter", Greet).reply().to("reply").build())
.out_reply(ZmqRpcPublish)
.transform(ReplyToRequester)
.out_retry(ZmqRpcPublish)
.to("greeter.retry");
})
}
The server of the worker's queue and the channel its results go to:
{
"servers": {
"jobs": {
"host": "worker:5555",
"protocol": "zeromq",
"protocolVersion": "3.0",
"bindings": {
"x-ruststream-zeromq": {
"transport": "tcp",
"endpoint": "worker:5555",
"role": "connect"
}
}
}
},
"channels": {
"results": {
"bindings": {
"x-ruststream-zeromq": { "socketPair": "PUSH/PULL", "nameFrame": "results" }
}
}
}
}