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>
52 lines
1.4 KiB
Rust
52 lines
1.4 KiB
Rust
//! Error types for cachewrap
|
|
|
|
use std::fmt;
|
|
|
|
/// Error type for cache operations
|
|
#[derive(Debug)]
|
|
pub enum CacheError {
|
|
/// Redis connection error
|
|
ConnectionError(String),
|
|
|
|
/// Redis command error
|
|
CommandError(String),
|
|
|
|
/// Serialization/deserialization error
|
|
SerializationError(String),
|
|
|
|
/// Invalid configuration
|
|
ConfigError(String),
|
|
|
|
/// Timeout error
|
|
TimeoutError(String),
|
|
}
|
|
|
|
impl fmt::Display for CacheError {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
CacheError::ConnectionError(msg) => write!(f, "Connection error: {}", msg),
|
|
CacheError::CommandError(msg) => write!(f, "Command error: {}", msg),
|
|
CacheError::SerializationError(msg) => write!(f, "Serialization error: {}", msg),
|
|
CacheError::ConfigError(msg) => write!(f, "Configuration error: {}", msg),
|
|
CacheError::TimeoutError(msg) => write!(f, "Timeout error: {}", msg),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for CacheError {}
|
|
|
|
impl From<redis::RedisError> for CacheError {
|
|
fn from(err: redis::RedisError) -> Self {
|
|
CacheError::CommandError(err.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<serde_json::Error> for CacheError {
|
|
fn from(err: serde_json::Error) -> Self {
|
|
CacheError::SerializationError(err.to_string())
|
|
}
|
|
}
|
|
|
|
/// Result type alias for cache operations
|
|
pub type Result<T> = std::result::Result<T, CacheError>;
|