stemedb/applications/aphoria/dogfood/cachewrap/docs/sources/redis-rs-lib.md
jml e758f2ebfb feat(aphoria): implement programmatic extractors for Option<T> semantics
Completes Task #3 of httpclient dogfooding with 100% detection rate (7/7 violations).

## New Extractors

- **OptionBoundsExtractor**: Detects Option<T> fields set to None (unbounded)
- **OptionValueExtractor**: Extracts values from Some(n) for threshold checks

Both extractors use context-aware pattern matching to understand Rust Option<T>
semantics, which declarative extractors cannot handle.

## Implementation

**Files Created**:
- applications/aphoria/src/extractors/option_bounds.rs (257 lines)
- applications/aphoria/src/extractors/option_value.rs (277 lines)
- applications/aphoria/docs/examples/extractors/programmatic-option-semantics.md

**Files Modified**:
- applications/aphoria/src/extractors/mod.rs - Added module declarations
- applications/aphoria/src/extractors/registry.rs - Registered extractors
- applications/aphoria/dogfood/httpclient/.aphoria/claims.toml - Added 4 claims
- applications/aphoria/dogfood/httpclient/TASK-1-SUMMARY.md - Task #3 completion

## Results

| Metric | Value |
|--------|-------|
| Detection Rate | 100% (7/7 violations) |
| Improvement | +29 percentage points (from 71%) |
| New Violations | 2 (max_redirects, max_retries unbounded) |
| Unit Tests | 13 (all passing) |

## Two-Claim Strategy

For each bounded Option<T> field:
1. **configured** claim - Detects None (unbounded)
2. **max_value** claim - Validates Some(n) threshold

Example:
- `max_redirects: None` → CONFLICT (not configured)
- `max_redirects: Some(20)` → CONFLICT (exceeds 10)
- `max_redirects: Some(5)` → PASS

## Enterprise Quality

✓ Proper error handling (no unwrap/expect)
✓ Comprehensive tests (6+7 unit tests)
✓ Full documentation with examples
✓ Reusable for 10+ similar patterns
✓ Screening patterns for performance

## Cachewrap Dogfood

Also includes complete cachewrap dogfood exercise:
- 10 claims for Redis cache wrapper
- Day 1-5 summaries
- Full retrospective and evaluation
- Declarative extractors for all patterns

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 06:43:10 +00:00

5.5 KiB

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):

// ❌ 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):

// ✅ 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):

// ❌ 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):


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):

#[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:

    open https://docs.rs/redis/latest/redis/
    
  2. Review example code:

    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:

    # 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