#[cfg(not(feature = "memcached-backend"))]
fn main() {
eprintln!("This example requires the 'memcached-backend' feature.");
eprintln!("Run with: cargo run --example memcached_production --features memcached-backend");
std::process::exit(1);
}
#[cfg(feature = "memcached-backend")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use std::time::Duration;
use tower_http_cache::backend::memcached::MemcachedBackend;
use tower_http_cache::prelude::*;
use tower_http_cache::streaming::StreamingPolicy;
println!("🚀 Memcached Production Setup Example");
println!("======================================\n");
println!("📡 Connecting to Memcached...");
let backend = MemcachedBackend::builder()
.address("127.0.0.1:11211")
.namespace("myapp_prod")
.max_connections(20) .min_connections(5) .connection_timeout(Duration::from_secs(5))
.build()
.await?;
println!("✅ Connected to Memcached with connection pool");
let state = backend.pool_state();
println!("\n📊 Pool Configuration:");
println!(" Connections: {}", state.connections);
println!(" Idle: {}", state.idle_connections);
println!(" Max size: 20");
println!(" Min size: 5");
println!("\n⚙️ Configuring cache policy...");
let cache_layer = CacheLayer::builder(backend.clone())
.policy(
CachePolicy::default()
.with_ttl(Duration::from_secs(300)) .with_negative_ttl(Duration::from_secs(60)) .with_stale_while_revalidate(Duration::from_secs(30))
.with_streaming_policy(StreamingPolicy {
enabled: true,
max_cacheable_size: Some(1024 * 1024), enable_chunk_cache: false, ..Default::default()
})
.with_respect_cache_control(true),
)
.build();
println!("✅ Cache layer configured");
println!("\n📝 Production Best Practices:");
println!(" ✓ Connection pooling (20 max, 5 min)");
println!(" ✓ Namespace isolation (myapp_prod)");
println!(" ✓ TTL configuration (5m cache, 1m negative)");
println!(" ✓ Stale-while-revalidate (30s grace period)");
println!(" ✓ Size limits (1MB max per entry)");
println!(" ✓ Cache-Control header respect");
println!("\n🏥 Running health check...");
let test_key = "health_check";
let test_value = "ok";
use bytes::Bytes;
use http::StatusCode;
use tower_http_cache::backend::{CacheBackend, CacheEntry};
let entry = CacheEntry::new(
StatusCode::OK,
http::Version::HTTP_11,
vec![],
Bytes::from(test_value),
);
backend
.set(
test_key.to_string(),
entry,
Duration::from_secs(10),
Duration::ZERO,
)
.await?;
let result = backend.get(test_key).await?;
if result.is_some() {
println!("✅ Health check passed (write + read successful)");
} else {
println!("❌ Health check failed (could not read back value)");
return Err("Health check failed".into());
}
backend.invalidate(test_key).await?;
println!("✅ Cleanup successful");
println!("\n⚡ Performance Tips:");
println!(" 1. Use connection pooling (already configured)");
println!(" 2. Set appropriate TTLs based on data freshness needs");
println!(" 3. Use stale-while-revalidate for better UX");
println!(" 4. Monitor cache hit rates and adjust policies");
println!(" 5. Consider multi-tier caching (in-memory L1 + Memcached L2)");
println!("\n🌐 Multi-Server Setup:");
println!(" For HA deployments, run multiple Memcached instances:");
println!(" ```");
println!(" docker run -d -p 11211:11211 memcached");
println!(" docker run -d -p 11212:11212 memcached");
println!(" ```");
println!(" Then use a load balancer or client-side hashing");
println!("\n📈 Monitoring Recommendations:");
println!(" - Track: cache hit rate, miss rate, latency");
println!(" - Alert on: connection pool exhaustion, high error rates");
println!(" - Log: cache invalidations, stale serves");
println!(" - Metrics: Use the 'metrics' feature for Prometheus export");
println!("\n📋 Configuration Summary:");
println!(" Backend: Memcached");
println!(" Address: 127.0.0.1:11211");
println!(" Namespace: myapp_prod");
println!(" Pool: 5-20 connections");
println!(" TTL: 5m (cache), 1m (negative)");
println!(" Max entry size: 1MB");
println!(" Stale grace period: 30s");
println!("\n✅ Memcached is ready for production traffic!");
println!("\nPress Ctrl+C to exit...");
tokio::signal::ctrl_c().await?;
println!("\n👋 Shutting down gracefully...");
Ok(())
}