Apache Iggy
SDKRust

Intro

The Rust SDK is the primary and most feature-complete client for Iggy. It is available on crates.io and the source code is part of the core repository.

cargo add iggy

High-level vs low-level API

The SDK provides two layers:

High-level API (recommended) - the easiest way to get started. It handles connection management, auto-batching, consumer group lifecycle, offset commits, retry logic, and reconnection out of the box. Use IggyClient, IggyProducer, and IggyConsumer for the best developer experience.

use iggy::prelude::*;

// Connect with a connection string
let client = IggyClient::from_connection_string("iggy://iggy:iggy@localhost:8090")?;
client.connect().await?;

// Or use the builder
let client = IggyClientBuilder::new()
    .with_tcp()
    .with_server_address("localhost:8090".to_string())
    .build()?;
client.connect().await?;
client.login_user("iggy", "iggy").await?;

Low-level API - direct access to individual protocol operations. Useful when you need fine-grained control over every request, or when building custom abstractions on top.

The high-level API is built on top of the low-level one, so you can always drop down when needed.

Connection string

The connection string is the simplest way to configure the client. It supports all four transport protocols:

iggy://user:pass@host:port              (TCP, default)
iggy+tcp://user:pass@host:port          (TCP, explicit)
iggy+quic://user:pass@host:port         (QUIC)
iggy+http://user:pass@host:port         (HTTP)
iggy+ws://user:pass@host:port           (WebSocket)

Options can be appended as query parameters:

iggy://iggy:iggy@my-server:8090?tls=true&tls_ca_file=/path/to/ca.crt
iggy://iggy:iggy@localhost:8090?reconnection_retries=unlimited&heartbeat_interval=5s

Personal Access Tokens are also supported:

iggy://iggypat-your-token@localhost:8090

Quick example

use iggy::prelude::*;
use std::str::FromStr;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = IggyClient::from_connection_string("iggy://iggy:iggy@127.0.0.1:8090")?;
    client.connect().await?;

    // Re-running this example is fine: an existing stream or topic is not an error.
    match client.create_stream("my-stream").await {
        Ok(_) | Err(IggyError::StreamNameAlreadyExists(_)) => {}
        Err(e) => return Err(e.into()),
    }
    match client
        .create_topic(
            &"my-stream".try_into()?,
            "my-topic",
            1,
            CompressionAlgorithm::None,
            None,
            IggyExpiry::NeverExpire,
            MaxTopicSize::ServerDefault,
        )
        .await
    {
        Ok(_) | Err(IggyError::TopicNameAlreadyExists(_, _)) => {}
        Err(e) => return Err(e.into()),
    }

    let msg = IggyMessage::from_str("hello world")?;
    client
        .send_messages(
            &"my-stream".try_into()?,
            &"my-topic".try_into()?,
            &Partitioning::partition_id(0),
            &mut [msg],
        )
        .await?;
    println!("Message sent");

    let polled = client
        .poll_messages(
            &"my-stream".try_into()?,
            &"my-topic".try_into()?,
            Some(0),
            &Consumer::default(),
            &PollingStrategy::next(),
            10,
            true,
        )
        .await?;

    for message in &polled.messages {
        let payload = std::str::from_utf8(&message.payload)?;
        println!("Offset: {}, Payload: {}", message.header.offset, payload);
    }

    Ok(())
}

For the full getting started tutorial, see Getting Started. For the high-level producer/consumer builders, see High-level SDK and Stream Builder.

On this page