# redis-rs Library Patterns - Key Excerpts for Cache Client

**Authority Tier:** Tier 3 (Community)
**Source:** https://docs.rs/redis/ + https://github.com/redis-rs/redis-rs
**Relevance:** Canonical Rust implementation patterns for Redis clients, widely adopted in ecosystem

---

## Connection Management

> **User fills in:** Review redis-rs documentation on connection handling
>
> Look for:
> - `redis::Client::open()` - One-time vs pooled
> - Connection pooling with r2d2 or bb8
> - Async vs sync API usage

**Key Claims:**
- `cache/connection_pooling :: library = "r2d2"`
  - **Consequence:** Creating new `Client::open()` per request exhausts file descriptors

- `cache/async_api :: required = true`
  - **Consequence:** Using blocking API in async context blocks event loop - throughput collapse

**Example (from redis-rs docs):**
```rust
// ❌ VIOLATION: New connection per request
let client = redis::Client::open("redis://127.0.0.1/")?;
let mut con = client.get_connection()?;  // Blocking!

// ✅ COMPLIANT: Connection pool
let manager = RedisConnectionManager::new("redis://127.0.0.1/")?;
let pool = r2d2::Pool::builder().build(manager)?;
let mut con = pool.get()?;
```

---

## Async Patterns

> **User fills in:** Review redis-rs async examples
>
> Look for:
> - `redis::aio::Connection` usage
> - Tokio integration
> - Error handling in async contexts

**Key Claims:**
- `cache/async_runtime :: required = "tokio"`
  - **Consequence:** Mixing async runtimes (tokio + async-std) causes runtime panics

- `cache/async_methods :: required = true`
  - **Consequence:** Calling `.blocking_get()` in async code blocks executor threads

**Example (from redis-rs GitHub):**
```rust
// ✅ COMPLIANT: Async API
let client = redis::Client::open("redis://127.0.0.1/")?;
let mut con = client.get_async_connection().await?;
let value: Option<String> = con.get("key").await?;
```

---

## Error Handling

> **User fills in:** Review redis-rs error types and handling patterns
>
> Look for:
> - `redis::RedisError` variants
> - Connection failures vs command failures
> - Retry strategies

**Key Claims:**
- `cache/error_handling :: pattern = "Result<T, RedisError>"`
  - **Consequence:** Unwrapping Redis results causes panics on network failures

- `cache/retry_on_error :: types = ["ConnectionRefused", "IoError"]`
  - **Consequence:** Not retrying transient errors causes unnecessary failures

**Example (from redis-rs issues):**
```rust
// ❌ VIOLATION: Unwrap causes panic on network failure
let value: String = con.get("key").unwrap();

// ✅ COMPLIANT: Proper error handling
match con.get("key") {
    Ok(value) => Some(value),
    Err(e) if is_transient(&e) => retry(),
    Err(e) => return Err(e.into()),
}
```

---

## Common Patterns (from GitHub Issues)

> **User fills in:** Search redis-rs GitHub issues for common problems
>
> Keywords to search:
> - "connection pool"
> - "timeout"
> - "memory leak"
> - "panic"

**Key Claims (extracted from issues):**

- `cache/ttl_default :: recommended = 3600`  # 1 hour
  - **Consequence:** From issue #234 - "Forgot to set TTL, cache grew to 10 GB"
  - Provenance: https://github.com/redis-rs/redis-rs/issues/234

- `cache/pipeline_usage :: recommended = true`
  - **Consequence:** From issue #156 - "Sequential SET commands 10x slower than pipeline"
  - Provenance: https://github.com/redis-rs/redis-rs/issues/156

- `cache/connection_timeout :: maximum = 30`
  - **Consequence:** From issue #89 - "60s timeout caused request queuing during Redis restart"
  - Provenance: https://github.com/redis-rs/redis-rs/issues/89

---

## Configuration Patterns

> **User fills in:** Review redis-rs examples/ directory
>
> Look for:
> - Config struct patterns
> - Builder pattern usage
> - Default value recommendations

**Key Claims:**
- `cache/config/builder_pattern :: required = true`
  - **Consequence:** Manual struct construction error-prone (missing required fields)

- `cache/config/validation :: required = true`
  - **Consequence:** Invalid config (e.g., timeout=0) accepted at compile time, fails at runtime

**Example (from redis-rs examples):**
```rust
#[derive(Clone)]
pub struct CacheConfig {
    pub url: String,
    pub max_connections: usize,  // ✅ Required, not Option
    pub timeout: Duration,       // ✅ Required, validated > 0
    pub ttl: Duration,           // ✅ Required for expiration
}

impl CacheConfig {
    pub fn validate(&self) -> Result<(), ConfigError> {
        if self.timeout.is_zero() {
            return Err(ConfigError::InvalidTimeout);
        }
        // ...
    }
}
```

---

## Extraction Guide

1. **Browse redis-rs documentation:**
   ```bash
   open https://docs.rs/redis/latest/redis/
   ```

2. **Review example code:**
   ```bash
   git clone https://github.com/redis-rs/redis-rs
   cd redis-rs/examples/
   # Read: basic.rs, async.rs, connection-pool.rs
   ```

3. **Search GitHub issues for patterns:**
   ```bash
   # On GitHub: redis-rs/redis-rs
   # Search: "memory leak", "timeout", "panic", "connection pool"
   # Read issue descriptions and resolutions
   ```

4. **Extract usage patterns:**
   - Connection management (pooling vs one-shot)
   - Async vs sync API usage
   - Error handling strategies
   - Configuration validation

5. **Map to concept paths:**
   - `cache/connection_pooling`
   - `cache/async_api`
   - `cache/error_handling`
   - `cache/config/validation`

6. **Add to claims with provenance:**
   - Provenance: "redis-rs v0.24.0 documentation - Connection Pooling"
   - Or: "redis-rs GitHub issue #234 - Memory leak from missing TTL"
   - Link to docs page or issue URL
