Skill 寫法圖鑑

azure-eventhub-rust

Microsoft | 雲端與基礎設施 | 原文 | MIT

用 Rust 對 Azure Event Hubs 收發事件和批次送出

中文翻譯

---
name: azure-eventhub-rust
description: |
  Rust 用的 Azure Event Hubs 函式庫。收發事件,用於串流資料匯入和批次處理。
  Triggers: "event hubs rust", "ProducerClient rust", "ConsumerClient rust", "send event rust", "streaming rust", "eventhub rust".
license: MIT
metadata:
  author: Microsoft
  package: azure_messaging_eventhubs
---

# Rust 用的 Azure Event Hubs 函式庫

Azure Event Hubs 的 client 函式庫,收發事件,用於串流資料匯入。

這些情況用這個 skill:

- App 需要從 Rust 把事件送到 Azure Event Hubs
- 需要從 partition 接收並處理事件
- 需要批次送出來最佳化吞吐量
- 需要控制 consumer 的起始位置

> **重要:** 只能用 [azure-sdk](https://crates.io/users/azure-sdk) 這個 crates.io 使用者發佈的官方 `azure_messaging_eventhubs` crate。不要用非官方或社群的 crate。官方 crate 的名稱用底線,而且沒有任何一個版本是 0.21.0。

## 安裝

```sh
cargo add azure_messaging_eventhubs azure_identity tokio futures
```

> `DeveloperToolsCredential::new(None)?` 本來就回傳 `Arc<DeveloperToolsCredential>`,所以可以直接傳進 `.open()` 或 clone 它。只有在需要直接 import `azure_core` 的東西(例如 `ErrorKind`)時才加 `azure_core`。

## 環境變數

```bash
EVENTHUBS_HOST=<namespace>.servicebus.windows.net # 必須設定:完整的 namespace 名稱
EVENTHUB_NAME=<eventhub-name>                     # 必須設定:Event Hub 的名稱
```

## 關鍵概念

| 概念          | 說明                                                 |
| ------------- | ---------------------------------------------------- |
| **Namespace** | 一個或多個 Event Hub 的容器                          |
| **Event Hub** | 事件串流,切成 partition 以平行讀取                  |
| **Partition** | 有順序、只能附加的事件序列                           |
| **Producer**  | 透過 `ProducerClient` 送出事件                       |
| **Consumer**  | 透過 `ConsumerClient` 從 partition 接收事件          |

## 驗證

Rust 的 Azure SDK 程式碼不能用 `DefaultAzureCredential`,因為 Rust 的 identity crate 沒有提供這個型別。

```rust
use azure_identity::DeveloperToolsCredential;
use azure_messaging_eventhubs::ProducerClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 本機開發:DeveloperToolsCredential。正式環境:用 ManagedIdentityCredential。
    let credential = DeveloperToolsCredential::new(None)?;

    let producer = ProducerClient::builder()
        .open(
            "<namespace>.servicebus.windows.net",
            "<eventhub-name>",
            credential.clone(),
        )
        .await?;
    Ok(())
}
```

要確認 builder 的簽章和接收串流的事件 wrapper 形狀時,優先看 crate 的 README 和範例。

## 核心流程

### 送出事件

```rust
// 送出單一事件
producer.send_event(vec![1, 2, 3, 4], None).await?;
```

### 送出批次

```rust
let batch = producer.create_batch(None).await?;
batch.try_add_event_data(vec![1, 2, 3, 4], None)?;

producer.send_batch(batch, None).await?;
```

### 接收事件

```rust
use azure_identity::DeveloperToolsCredential;
use azure_messaging_eventhubs::ConsumerClient;

// 本機開發:DeveloperToolsCredential。正式環境:用 ManagedIdentityCredential。
let credential = DeveloperToolsCredential::new(None)?;
let consumer = ConsumerClient::builder()
    .open(
        "<namespace>.servicebus.windows.net",
        "<eventhub-name>".to_string(),
        credential.clone(),
    )
    .await?;
```

### 從 Partition 接收

```rust
use futures::stream::StreamExt;
use azure_messaging_eventhubs::{
    ConsumerClient, OpenReceiverOptions, StartLocation, StartPosition,
};

let receiver = consumer
    .open_receiver_on_partition(
        "0".to_string(),
        Some(OpenReceiverOptions {
            start_position: Some(StartPosition {
                location: StartLocation::Earliest,
                ..Default::default()
            }),
            ..Default::default()
        }),
    )
    .await?;

let mut stream = receiver.stream_events();
while let Some(event_result) = stream.next().await {
    match event_result {
        // body 在內層的 event data 上,不在接收到的 wrapper 上:`event.event_data().body()`。
        Ok(event) => {
            let body = event.event_data().body().unwrap_or_default();
            println!("Received: {:?}", body);
        }
        Err(err) => eprintln!("Error: {:?}", err),
    }
}
```

## RBAC 角色

用 Entra ID 驗證時,指派下面其中一個角色:

| 角色                             | 權限         |
| -------------------------------- | ------------ |
| `Azure Event Hubs Data Sender`   | 送出事件     |
| `Azure Event Hubs Data Receiver` | 接收事件     |
| `Azure Event Hubs Data Owner`    | 完整權限     |

## 最佳實務

1. **用 `cargo add` 管理依賴,不要直接編輯 `Cargo.toml`。** 新增和移除 Rust SDK 依賴一律用 cargo 指令,不要手動改 manifest。
2. **直接把 credential 傳進 `.open()` 或 clone 它。** `DeveloperToolsCredential::new(None)?` 本來就回傳 `Arc`,所以除非你要明確寫出那個 trait object 型別,否則不用把變數標註成 `Arc<dyn TokenCredential>`。
3. **對齊 builder 的簽章。** `ProducerClient::builder().open(...)` 的 hub 名稱是 `&str`,而 `ConsumerClient::builder().open(...)` 要的是擁有所有權的 `String`。
4. **本機開發用 `DeveloperToolsCredential`**,**正式環境用 `ManagedIdentityCredential`**,Rust 沒有單一的 `DefaultAzureCredential` 型別
5. **絕對不要寫死憑證**,用環境變數或 managed identity
6. **用批次**:`create_batch` + `send_batch` 最佳化吞吐量
7. **逐個事件處理錯誤**:在事件串流裡對 `Ok`/`Err` 做 match
8. **用 `event.event_data().body()` 取事件的 body**,不要用 `event.body()`,因為 `ReceivedEventData` 包著底層的 `EventData`。
9. **指定起始位置**:用 `StartLocation::Earliest` 或 `StartLocation::Latest` 控制從哪裡開始消費
10. **當 prompt、eval 或 CI 要求 lint 乾淨的輸出時,跑 `cargo clippy -- -D warnings`**

## 參考連結

| 資源          | 連結                                                                                          |
| ------------- | --------------------------------------------------------------------------------------------- |
| API Reference | https://docs.rs/azure_messaging_eventhubs/latest/azure_messaging_eventhubs                    |
| crates.io     | https://crates.io/crates/azure_messaging_eventhubs                                            |
| Source Code   | https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/eventhubs/azure_messaging_eventhubs |

英文原文

---
name: azure-eventhub-rust
description: |
  Azure Event Hubs library for Rust. Send and receive events for streaming data ingestion and batch processing.
  Triggers: "event hubs rust", "ProducerClient rust", "ConsumerClient rust", "send event rust", "streaming rust", "eventhub rust".
license: MIT
metadata:
  author: Microsoft
  package: azure_messaging_eventhubs
---

# Azure Event Hubs library for Rust

Client library for Azure Event Hubs — send and receive events for streaming data ingestion.

Use this skill when:

- An app needs to send events to Azure Event Hubs from Rust
- You need to receive and process events from partitions
- You need batch sending for throughput optimization
- You need to control consumer start position

> **IMPORTANT:** Only use the official `azure_messaging_eventhubs` crate published by the [azure-sdk](https://crates.io/users/azure-sdk) crates.io user. Do NOT use unofficial or community crates. Official crates use underscores in names and none have version 0.21.0.

## Installation

```sh
cargo add azure_messaging_eventhubs azure_identity tokio futures
```

> `DeveloperToolsCredential::new(None)?` already returns an `Arc<DeveloperToolsCredential>`, so you can pass or clone it directly into `.open()`. Add `azure_core` only when you need direct `azure_core` imports such as `ErrorKind`.

## Environment Variables

```bash
EVENTHUBS_HOST=<namespace>.servicebus.windows.net # Required — fully qualified namespace
EVENTHUB_NAME=<eventhub-name>                     # Required — name of the Event Hub
```

## Key Concepts

| Concept       | Description                                          |
| ------------- | ---------------------------------------------------- |
| **Namespace** | Container for one or more Event Hubs                 |
| **Event Hub** | Stream of events, partitioned for parallel reads     |
| **Partition** | Ordered, append-only sequence of events              |
| **Producer**  | Sends events via `ProducerClient`                    |
| **Consumer**  | Receives events from partitions via `ConsumerClient` |

## Authentication

Rust Azure SDK code must not use `DefaultAzureCredential`. The Rust identity crate does not provide that type.

```rust
use azure_identity::DeveloperToolsCredential;
use azure_messaging_eventhubs::ProducerClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Local dev: DeveloperToolsCredential. Production: use ManagedIdentityCredential.
    let credential = DeveloperToolsCredential::new(None)?;

    let producer = ProducerClient::builder()
        .open(
            "<namespace>.servicebus.windows.net",
            "<eventhub-name>",
            credential.clone(),
        )
        .await?;
    Ok(())
}
```

Prefer the crate README/examples when checking builder signatures and receive-stream event wrapper shapes.

## Core Workflow

### Send Events

```rust
// Send a single event
producer.send_event(vec![1, 2, 3, 4], None).await?;
```

### Send Batch

```rust
let batch = producer.create_batch(None).await?;
batch.try_add_event_data(vec![1, 2, 3, 4], None)?;

producer.send_batch(batch, None).await?;
```

### Receive Events

```rust
use azure_identity::DeveloperToolsCredential;
use azure_messaging_eventhubs::ConsumerClient;

// Local dev: DeveloperToolsCredential. Production: use ManagedIdentityCredential.
let credential = DeveloperToolsCredential::new(None)?;
let consumer = ConsumerClient::builder()
    .open(
        "<namespace>.servicebus.windows.net",
        "<eventhub-name>".to_string(),
        credential.clone(),
    )
    .await?;
```

### Receive from Partition

```rust
use futures::stream::StreamExt;
use azure_messaging_eventhubs::{
    ConsumerClient, OpenReceiverOptions, StartLocation, StartPosition,
};

let receiver = consumer
    .open_receiver_on_partition(
        "0".to_string(),
        Some(OpenReceiverOptions {
            start_position: Some(StartPosition {
                location: StartLocation::Earliest,
                ..Default::default()
            }),
            ..Default::default()
        }),
    )
    .await?;

let mut stream = receiver.stream_events();
while let Some(event_result) = stream.next().await {
    match event_result {
        // Body is on the inner event data, not the received wrapper: `event.event_data().body()`.
        Ok(event) => {
            let body = event.event_data().body().unwrap_or_default();
            println!("Received: {:?}", body);
        }
        Err(err) => eprintln!("Error: {:?}", err),
    }
}
```

## RBAC Roles

For Entra ID auth, assign one of these roles:

| Role                             | Access         |
| -------------------------------- | -------------- |
| `Azure Event Hubs Data Sender`   | Send events    |
| `Azure Event Hubs Data Receiver` | Receive events |
| `Azure Event Hubs Data Owner`    | Full access    |

## Best Practices

1. **Use `cargo add` to manage dependencies, never edit `Cargo.toml` directly.** Add and remove Rust SDK dependencies with cargo commands instead of manual manifest edits.
2. **Pass or clone credentials directly into `.open()`.** `DeveloperToolsCredential::new(None)?` already returns an `Arc`, so you do not need to annotate the binding as `Arc<dyn TokenCredential>` unless you are naming that trait object type explicitly.
3. **Match the builder signature.** `ProducerClient::builder().open(...)` takes the hub name as `&str`, while `ConsumerClient::builder().open(...)` takes an owned `String`.
4. **Use `DeveloperToolsCredential`** for local dev, **`ManagedIdentityCredential`** for production — Rust does not provide a single `DefaultAzureCredential` type
5. **Never hardcode credentials** — use environment variables or managed identity
6. **Use batching** — `create_batch` + `send_batch` for throughput optimization
7. **Handle errors per event** — match on `Ok`/`Err` in the event stream
8. **Extract event bodies via `event.event_data().body()`**, not `event.body()` — `ReceivedEventData` wraps the underlying `EventData`.
9. **Specify start position** — use `StartLocation::Earliest` or `StartLocation::Latest` to control where consumption begins
10. **Run `cargo clippy -- -D warnings`** when the prompt, eval, or CI expects lint-clean output

## Reference Links

| Resource      | Link                                                                                          |
| ------------- | --------------------------------------------------------------------------------------------- |
| API Reference | https://docs.rs/azure_messaging_eventhubs/latest/azure_messaging_eventhubs                    |
| crates.io     | https://crates.io/crates/azure_messaging_eventhubs                                            |
| Source Code   | https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/eventhubs/azure_messaging_eventhubs |