Files
alknet/docs/research/references/nats.rs/nats-async/09-quick-reference.md

8.0 KiB

async-nats: Quick Reference

Connection

// Basic connect
let client = async_nats::connect("demo.nats.io").await?;

// With options
let client = async_nats::ConnectOptions::new()
    .require_tls(true)
    .name("my-service")
    .ping_interval(Duration::from_secs(10))
    .request_timeout(Some(Duration::from_secs(5)))
    .connect("demo.nats.io")
    .await?;

// Multiple servers
let client = async_nats::connect(vec![
    "nats://server1:4222".parse()?,
    "nats://server2:4222".parse()?,
]).await?;

// Background connect
let client = async_nats::ConnectOptions::new()
    .retry_on_initial_connect()
    .connect("demo.nats.io")
    .await?;

Core NATS: Publish

// Simple publish
client.publish("subject", "payload".into()).await?;

// With reply-to
client.publish_with_reply("subject", "reply-to", "payload".into()).await?;

// With headers
let mut headers = HeaderMap::new();
headers.insert("X-Custom", "value");
client.publish_with_headers("subject", headers, "payload".into()).await?;

// Full control
client.publish_with_reply_and_headers("subject", "reply-to", headers, "payload".into()).await?;

// Flush (ensure all published messages are sent)
client.flush().await?;

Core NATS: Subscribe

use futures_util::StreamExt;

// Basic subscribe
let mut subscriber = client.subscribe("subject").await?;

// Queue group
let mut subscriber = client.queue_subscribe("subject", "group".into()).await?;

// Receive messages (Subscriber implements Stream)
while let Some(message) = subscriber.next().await {
    println!("subject: {}, payload: {:?}", message.subject, message.payload);
}

// Unsubscribe
subscriber.unsubscribe().await?;

// Unsubscribe after N messages
subscriber.unsubscribe_after(10).await?;

// Drain (wait for in-flight, then unsubscribe)
subscriber.drain().await?;

Core NATS: Request/Reply

// Simple request (uses default timeout)
let response = client.request("subject", "data".into()).await?;

// With custom timeout and headers
let request = async_nats::Request::new()
    .payload("data".into())
    .timeout(Some(Duration::from_secs(5)))
    .headers(headers);
let response = client.send_request("subject", request).await?;

// Custom inbox (bypasses multiplexer)
let request = async_nats::Request::new()
    .payload("data".into())
    .inbox("custom-inbox".into());
let response = client.send_request("subject", request).await?;

Message Structure

pub struct Message {
    pub subject: Subject,
    pub reply: Option<Subject>,
    pub payload: Bytes,
    pub headers: Option<HeaderMap>,
    pub status: Option<StatusCode>,
    pub description: Option<String>,
    pub length: usize,
}

JetStream

let jetstream = async_nats::jetstream::new(client);

// Publish (returns ack future)
let ack = jetstream.publish("events", "data".into()).await?;
let publish_ack = ack.await?;

// Stream management
let stream = jetstream.create_stream(stream::Config {
    name: "events".to_string(),
    subjects: vec!["events.>".to_string()],
    max_messages: 10_000,
    ..Default::default()
}).await?;

let stream = jetstream.get_stream("events").await?;
let stream = jetstream.get_or_create_stream(config).await?;
jetstream.delete_stream("events").await?;
jetstream.update_stream(config).await?;

// Consumer management
let consumer: PullConsumer = stream.create_consumer(pull::Config {
    durable_name: Some("my-consumer".to_string()),
    ..Default::default()
}).await?;

// Pull consumer: fetch messages
let mut messages = consumer.messages().await?;
while let Some(message) = messages.next().await {
    let message = message?;
    message.ack().await?;
}

// Push consumer (ordered)
let consumer = stream.create_consumer(push::OrderedConfig {
    deliver_subject: client.new_inbox(),
    filter_subject: "events.>".to_string(),
    ..Default::default()
}).await?;
let mut messages = consumer.messages().await?;

Key-Value Store

let kv = jetstream.create_key_value(kv::Config {
    bucket: "my-bucket".to_string(),
    history: 10,
    ..Default::default()
}).await?;

// CRUD
let revision = kv.put("key", "value".into()).await?;
let revision = kv.create("key", "value".into()).await?;
let value: Option<Bytes> = kv.get("key").await?;
let entry: Option<Entry> = kv.entry("key").await?;
let revision = kv.update("key", "new-value".into(), revision).await?;
kv.delete("key").await?;
kv.purge("key").await?;

// Watch
let mut watch = kv.watch("key").await?;
let mut watch_all = kv.watch_all().await?;

// History & Keys
let mut history = kv.history("key").await?;
let mut keys = kv.keys().await?;

Object Store

let bucket = jetstream.create_object_store(object_store::Config {
    bucket: "files".to_string(),
    ..Default::default()
}).await?;

// Put (from any AsyncRead)
let info = bucket.put("file.txt", &mut file).await?;

// Get (returns AsyncRead)
let mut object = bucket.get("file.txt").await?;
let mut bytes = Vec::new();
object.read_to_end(&mut bytes).await?;

// Info, delete, list, watch
let info = bucket.info("file.txt").await?;
bucket.delete("file.txt").await?;
let mut list = bucket.list().await?;
let mut watch = bucket.watch().await?;

Service API

use async_nats::service::ServiceExt;
use futures_util::StreamExt;

let mut service = client
    .service_builder()
    .description("product service")
    .start("products", "1.0.0")
    .await?;

let mut endpoint = service.endpoint("get").await?;

while let Some(request) = endpoint.next().await {
    request.respond(Ok("result".into())).await?;
}

Client State & Events

// Check connection state
match client.connection_state() {
    State::Connected => {},
    State::Disconnected => {},
    State::Pending => {},
}

// Get server info
let info: ServerInfo = client.server_info();
println!("max_payload: {}", info.max_payload);
println!("jetstream: {}", info.jetstream);

// Get statistics
let stats = client.statistics();
println!("in_messages: {}", stats.in_messages.load(Ordering::Relaxed));

// Force reconnect
client.force_reconnect().await?;

// Server pool management
client.set_server_pool(["nats://s1:4222".parse()?, "nats://s2:4222".parse()?].as_slice()).await?;
let pool = client.server_pool().await?;

// Drain
client.drain().await?;

Error Handling Patterns

// Connect errors
match async_nats::connect("server").await {
    Err(e) => match e.kind() {
        ConnectErrorKind::TimedOut => {},
        ConnectErrorKind::Authentication => {},
        ConnectErrorKind::AuthorizationViolation => {},
        _ => {},
    },
    Ok(client) => {},
}

// Publish errors
match client.publish("subject", "data".into()).await {
    Err(e) => match e.kind() {
        PublishErrorKind::MaxPayloadExceeded => {},
        PublishErrorKind::InvalidSubject => {},
        PublishErrorKind::Send => {},
        _ => {},
    },
    _ => {},
}

// Request errors
match client.request("subject", "data".into()).await {
    Err(e) => match e.kind() {
        RequestErrorKind::TimedOut => {},
        RequestErrorKind::NoResponders => {},
        RequestErrorKind::InvalidSubject => {},
        RequestErrorKind::MaxPayloadExceeded => {},
        _ => {},
    },
    Ok(message) => {},
}

Feature Flag Quick Reference

Feature Enables Default
jetstream JetStream streams, consumers, publish
kv Key-Value store (implies jetstream)
object-store Object store (implies jetstream + crypto)
service Service API
nkeys NKey/JWT authentication
nuid NUID-based ID generation
crypto SHA-256 (for object store)
websockets WebSocket transport
ring ring TLS crypto backend
aws-lc-rs aws-lc-rs TLS crypto backend
fips FIPS mode via aws-lc-rs
chrono chrono datetime instead of time
server_2_10 Server 2.10+ features
server_2_11 Server 2.11+ features
server_2_12 Server 2.12+ features
server_2_14 Server 2.14+ features