Add comprehensive production documentation
Documentation created: - Updated README.md with Docker deployment and production domain - docs/DEPLOYMENT.md: Complete Docker/Caddy deployment guide - docs/ARCHITECTURE.md: System design and caching strategies - docs/QUICKSTART.md: 5-minute setup with real examples - Updated USAGE.md with production URLs Key updates: - Production domain: https://rentcache.l.supported.systems - Docker Compose with Caddy reverse proxy - Make commands for easy management - Cost savings examples (70-90% reduction) - Complete architecture documentation - Production deployment checklist - Monitoring and maintenance guides The system is now fully documented for production deployment.
This commit is contained in:
parent
f46bdc978e
commit
345ad00692
151
README.md
151
README.md
@ -2,7 +2,9 @@
|
||||
|
||||
🏠 **Reduce your Rentcast API costs by 70-90% with intelligent caching, rate limiting, and usage management.**
|
||||
|
||||
**RentCache** is a sophisticated FastAPI proxy server that sits between your applications and the Rentcast API, providing intelligent caching, cost optimization, and usage analytics. Perfect for real estate applications that need frequent property data access without breaking the budget.
|
||||
**RentCache** is a production-ready FastAPI proxy server that sits between your applications and the Rentcast API, providing intelligent caching, cost optimization, and usage analytics. Perfect for real estate applications that need frequent property data access without breaking the budget.
|
||||
|
||||
**🌐 Live Demo**: [https://rentcache.l.supported.systems](https://rentcache.l.supported.systems)
|
||||
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://fastapi.tiangolo.com)
|
||||
@ -57,49 +59,72 @@
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Installation
|
||||
### Docker Deployment (Recommended)
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://git.supported.systems/MCP/rentcache.git
|
||||
cd rentcache
|
||||
|
||||
# Install with uv (recommended)
|
||||
# Start with Docker (includes reverse proxy)
|
||||
make setup
|
||||
|
||||
# Or manually:
|
||||
docker network create caddy 2>/dev/null || true
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
**✅ Ready!** RentCache is now available at: **https://rentcache.l.supported.systems**
|
||||
|
||||
### Local Development
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
uv sync
|
||||
|
||||
# Or with pip
|
||||
pip install -e .
|
||||
# Start development server
|
||||
make local-dev
|
||||
|
||||
# Or manually:
|
||||
uv run rentcache server --reload
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
1. **Start the server**:
|
||||
1. **Create an API key**:
|
||||
```bash
|
||||
# Using CLI
|
||||
rentcache server
|
||||
# Using Docker
|
||||
make create-key NAME=my_app KEY=your_rentcast_api_key
|
||||
|
||||
# Or directly
|
||||
uvicorn rentcache.server:app --reload
|
||||
# Or locally
|
||||
uv run rentcache create-key my_app your_rentcast_api_key
|
||||
```
|
||||
|
||||
2. **Create an API key**:
|
||||
2. **Make API calls**:
|
||||
```bash
|
||||
rentcache create-key my_app YOUR_RENTCAST_API_KEY
|
||||
```
|
||||
# Production endpoint
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX"
|
||||
|
||||
3. **Make API calls**:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_RENTCAST_API_KEY" \
|
||||
# Local development
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"http://localhost:8000/api/v1/properties?city=Austin&state=TX"
|
||||
```
|
||||
|
||||
4. **Check metrics**:
|
||||
3. **Monitor performance**:
|
||||
```bash
|
||||
curl "http://localhost:8000/metrics"
|
||||
# View metrics
|
||||
curl "https://rentcache.l.supported.systems/metrics"
|
||||
|
||||
# Health check
|
||||
curl "https://rentcache.l.supported.systems/health"
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
- **[Deployment Guide](docs/DEPLOYMENT.md)** - Docker & production deployment
|
||||
- **[Architecture Overview](docs/ARCHITECTURE.md)** - System design & caching strategy
|
||||
- **[Quick Start Guide](docs/QUICKSTART.md)** - 5-minute setup walkthrough
|
||||
- **[Installation Guide](docs/INSTALLATION.md)** - Detailed setup instructions
|
||||
- **[Usage Guide](docs/USAGE.md)** - Comprehensive usage examples
|
||||
- **[API Reference](docs/API.md)** - Complete endpoint documentation
|
||||
@ -400,77 +425,57 @@ Provides detailed system metrics including:
|
||||
- Cost analysis and savings
|
||||
- System resource utilization
|
||||
|
||||
## 🚢 Deployment
|
||||
## 🐳 Docker Deployment
|
||||
|
||||
### Docker
|
||||
### Quick Start with Make
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.13-slim
|
||||
```bash
|
||||
# Complete setup with reverse proxy
|
||||
make setup
|
||||
|
||||
WORKDIR /app
|
||||
# Development mode with hot reload
|
||||
make dev
|
||||
|
||||
# Install uv
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||
# Production mode
|
||||
make prod
|
||||
|
||||
# Copy dependency files
|
||||
COPY pyproject.toml uv.lock ./
|
||||
# View logs
|
||||
make logs
|
||||
|
||||
# Install dependencies
|
||||
RUN uv sync --frozen --no-cache --no-dev
|
||||
# Health check
|
||||
make health
|
||||
|
||||
# Copy application
|
||||
COPY src/ ./src/
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["uv", "run", "uvicorn", "rentcache.server:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
# Management commands
|
||||
make create-key NAME=my_app KEY=your_rentcast_key
|
||||
make list-keys
|
||||
make stats
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
### Manual Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
rentcache:
|
||||
build: .
|
||||
ports:
|
||||
- "8000:8000"
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://user:pass@db:5432/rentcache
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- REDIS_ENABLED=true
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
```bash
|
||||
# Create external network (if not exists)
|
||||
docker network create caddy
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
environment:
|
||||
POSTGRES_DB: rentcache
|
||||
POSTGRES_USER: user
|
||||
POSTGRES_PASSWORD: pass
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
# Development with hot reload
|
||||
docker compose up --build -d
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
# Production mode
|
||||
MODE=production DEBUG=false docker compose up --build -d
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
# With Redis for better performance
|
||||
docker compose --profile redis up --build -d
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
### Production Features
|
||||
|
||||
1. **Use PostgreSQL**: Replace SQLite with PostgreSQL for production
|
||||
2. **Enable Redis**: Use Redis for better cache performance
|
||||
3. **Configure Logging**: Use structured JSON logging
|
||||
4. **Set Up Monitoring**: Monitor metrics and health endpoints
|
||||
5. **Use Reverse Proxy**: Nginx or Traefik for SSL termination
|
||||
6. **Environment Variables**: Never commit secrets to code
|
||||
- **🔄 Multi-stage Docker builds** for optimized images
|
||||
- **🌐 Caddy reverse proxy** with automatic HTTPS
|
||||
- **📊 Health checks** and graceful shutdown
|
||||
- **🔒 Non-root user** for security
|
||||
- **📦 Efficient caching** with multi-layer cache mounts
|
||||
- **🚀 Hot reload** in development mode
|
||||
- **📈 Production monitoring** with metrics and logging
|
||||
|
||||
## 📈 Performance Tips
|
||||
|
||||
|
641
docs/ARCHITECTURE.md
Normal file
641
docs/ARCHITECTURE.md
Normal file
@ -0,0 +1,641 @@
|
||||
# Architecture Overview
|
||||
|
||||
This document provides a comprehensive overview of RentCache's system architecture, design decisions, and technical implementation details.
|
||||
|
||||
## 🏗️ System Architecture
|
||||
|
||||
### High-Level Architecture
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Client[Client Applications] --> LB[Load Balancer/Caddy]
|
||||
LB --> App[RentCache FastAPI]
|
||||
|
||||
App --> Auth[Authentication Layer]
|
||||
Auth --> Rate[Rate Limiting]
|
||||
Rate --> Cache[Cache Manager]
|
||||
|
||||
Cache --> L1[L1 Cache<br/>Redis]
|
||||
Cache --> L2[L2 Cache<br/>SQLite/PostgreSQL]
|
||||
|
||||
Cache --> API[Rentcast API]
|
||||
|
||||
App --> Analytics[Usage Analytics]
|
||||
Analytics --> DB[(Database)]
|
||||
|
||||
App --> Monitor[Health Monitoring]
|
||||
App --> Metrics[Metrics Collection]
|
||||
|
||||
subgraph "Data Layer"
|
||||
L1
|
||||
L2
|
||||
DB
|
||||
end
|
||||
|
||||
subgraph "External Services"
|
||||
API
|
||||
end
|
||||
```
|
||||
|
||||
### Component Responsibilities
|
||||
|
||||
#### **FastAPI Application Server**
|
||||
- **Primary Role**: HTTP request handling and API routing
|
||||
- **Key Features**:
|
||||
- Async/await architecture for high concurrency
|
||||
- OpenAPI documentation generation
|
||||
- Request/response validation with Pydantic
|
||||
- Middleware stack for cross-cutting concerns
|
||||
|
||||
#### **Authentication & Authorization**
|
||||
- **Method**: Bearer token authentication using SHA-256 hashed API keys
|
||||
- **Storage**: Secure key storage with expiration and usage limits
|
||||
- **Features**: Per-key rate limiting and usage tracking
|
||||
|
||||
#### **Multi-Level Caching System**
|
||||
- **L1 Cache (Redis)**: In-memory cache for ultra-fast access
|
||||
- **L2 Cache (Database)**: Persistent cache with analytics
|
||||
- **Strategy**: Write-through with intelligent TTL management
|
||||
|
||||
#### **Rate Limiting Engine**
|
||||
- **Implementation**: Token bucket algorithm with sliding windows
|
||||
- **Granularity**: Global and per-endpoint limits
|
||||
- **Backend**: Redis-based distributed rate limiting
|
||||
|
||||
#### **Usage Analytics**
|
||||
- **Tracking**: Request patterns, costs, and performance metrics
|
||||
- **Storage**: Time-series data in relational database
|
||||
- **Reporting**: Real-time dashboards and historical analysis
|
||||
|
||||
## 🔄 Request Flow Architecture
|
||||
|
||||
### 1. Request Processing Pipeline
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Client
|
||||
participant A as Auth Layer
|
||||
participant R as Rate Limiter
|
||||
participant CM as Cache Manager
|
||||
participant RC as Redis Cache
|
||||
participant DB as Database
|
||||
participant RA as Rentcast API
|
||||
|
||||
C->>A: HTTP Request + API Key
|
||||
A->>A: Validate & Hash Key
|
||||
|
||||
alt Valid API Key
|
||||
A->>R: Check Rate Limits
|
||||
alt Within Limits
|
||||
R->>CM: Cache Lookup
|
||||
CM->>RC: Check L1 Cache
|
||||
|
||||
alt Cache Hit (L1)
|
||||
RC-->>CM: Return Cached Data
|
||||
CM-->>C: Response + Cache Headers
|
||||
else Cache Miss (L1)
|
||||
CM->>DB: Check L2 Cache
|
||||
alt Cache Hit (L2)
|
||||
DB-->>CM: Return Cached Data
|
||||
CM->>RC: Populate L1
|
||||
CM-->>C: Response + Cache Headers
|
||||
else Cache Miss (L2)
|
||||
CM->>RA: Upstream API Call
|
||||
RA-->>CM: API Response
|
||||
CM->>DB: Store in L2
|
||||
CM->>RC: Store in L1
|
||||
CM-->>C: Response + Cost Headers
|
||||
end
|
||||
end
|
||||
else Rate Limited
|
||||
R-->>C: 429 Rate Limit Exceeded
|
||||
end
|
||||
else Invalid API Key
|
||||
A-->>C: 401 Unauthorized
|
||||
end
|
||||
```
|
||||
|
||||
### 2. Cache Key Generation
|
||||
|
||||
**Cache Key Strategy**: MD5 hash of request signature
|
||||
```python
|
||||
cache_key = md5(json.dumps({
|
||||
"endpoint": "properties",
|
||||
"method": "GET",
|
||||
"path_params": {"property_id": "123"},
|
||||
"query_params": {"city": "Austin", "state": "TX"},
|
||||
"body": {}
|
||||
}, sort_keys=True)).hexdigest()
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Deterministic cache keys
|
||||
- Collision resistance
|
||||
- Parameter order independence
|
||||
- Efficient storage and lookup
|
||||
|
||||
## 💾 Caching Strategy
|
||||
|
||||
### Multi-Level Cache Architecture
|
||||
|
||||
#### **Level 1: Redis Cache (Hot Data)**
|
||||
- **Purpose**: Ultra-fast access to frequently requested data
|
||||
- **TTL**: 30 minutes to 2 hours
|
||||
- **Eviction**: LRU (Least Recently Used)
|
||||
- **Size**: Memory-limited, optimized for speed
|
||||
|
||||
```python
|
||||
# L1 Cache Configuration
|
||||
REDIS_CONFIG = {
|
||||
"maxmemory": "512mb",
|
||||
"maxmemory_policy": "allkeys-lru",
|
||||
"save": ["900 1", "300 10", "60 10000"], # Persistence snapshots
|
||||
"appendonly": True, # AOF for durability
|
||||
"appendfsync": "everysec"
|
||||
}
|
||||
```
|
||||
|
||||
#### **Level 2: Database Cache (Persistent)**
|
||||
- **Purpose**: Persistent cache with analytics and soft deletion
|
||||
- **TTL**: 1 hour to 48 hours based on endpoint volatility
|
||||
- **Storage**: Full response data + metadata
|
||||
- **Features**: Soft deletion, usage tracking, cost analytics
|
||||
|
||||
```sql
|
||||
-- Cache Entry Schema
|
||||
CREATE TABLE cache_entries (
|
||||
id SERIAL PRIMARY KEY,
|
||||
cache_key VARCHAR(64) UNIQUE NOT NULL,
|
||||
endpoint VARCHAR(50) NOT NULL,
|
||||
method VARCHAR(10) NOT NULL,
|
||||
params_hash VARCHAR(64) NOT NULL,
|
||||
response_data JSONB NOT NULL,
|
||||
status_code INTEGER NOT NULL,
|
||||
estimated_cost DECIMAL(10,2) DEFAULT 0.0,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
is_valid BOOLEAN DEFAULT TRUE,
|
||||
hit_count INTEGER DEFAULT 0,
|
||||
last_accessed TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### Cache TTL Strategy
|
||||
|
||||
| Endpoint Type | Data Volatility | Default TTL | Rationale |
|
||||
|---------------|----------------|-------------|-----------|
|
||||
| **Property Records** | Very Low | 24 hours | Property characteristics rarely change |
|
||||
| **Value Estimates** | Medium | 1 hour | Market fluctuations affect valuations |
|
||||
| **Rent Estimates** | Medium | 1 hour | Rental markets change regularly |
|
||||
| **Listings** | High | 30 minutes | Active market with frequent updates |
|
||||
| **Market Statistics** | Low | 2 hours | Aggregated data changes slowly |
|
||||
| **Comparables** | Medium | 1 hour | Market-dependent analysis |
|
||||
|
||||
### Stale-While-Revalidate Pattern
|
||||
|
||||
```python
|
||||
async def get_with_stale_while_revalidate(cache_key: str, ttl: int):
|
||||
"""
|
||||
Serve stale data immediately while refreshing in background
|
||||
"""
|
||||
cached_data = await cache.get(cache_key)
|
||||
|
||||
if cached_data:
|
||||
if not cached_data.is_expired:
|
||||
return cached_data # Fresh data
|
||||
else:
|
||||
# Serve stale data, trigger background refresh
|
||||
asyncio.create_task(refresh_cache_entry(cache_key))
|
||||
return cached_data # Stale but usable
|
||||
|
||||
# Cache miss - fetch fresh data
|
||||
return await fetch_and_cache(cache_key, ttl)
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Improved user experience (no waiting for fresh data)
|
||||
- Reduced upstream API calls during traffic spikes
|
||||
- Graceful handling of upstream service issues
|
||||
|
||||
## 🚦 Rate Limiting Implementation
|
||||
|
||||
### Token Bucket Algorithm
|
||||
|
||||
```python
|
||||
class TokenBucket:
|
||||
def __init__(self, capacity: int, refill_rate: float):
|
||||
self.capacity = capacity
|
||||
self.tokens = capacity
|
||||
self.refill_rate = refill_rate # tokens per second
|
||||
self.last_refill = time.time()
|
||||
|
||||
async def consume(self, tokens: int = 1) -> bool:
|
||||
await self._refill()
|
||||
if self.tokens >= tokens:
|
||||
self.tokens -= tokens
|
||||
return True
|
||||
return False
|
||||
|
||||
async def _refill(self):
|
||||
now = time.time()
|
||||
tokens_to_add = (now - self.last_refill) * self.refill_rate
|
||||
self.tokens = min(self.capacity, self.tokens + tokens_to_add)
|
||||
self.last_refill = now
|
||||
```
|
||||
|
||||
### Multi-Tier Rate Limiting
|
||||
|
||||
#### **Global Limits**
|
||||
- **Purpose**: Prevent overall API abuse
|
||||
- **Scope**: Per API key across all endpoints
|
||||
- **Implementation**: Redis-based distributed counters
|
||||
|
||||
#### **Per-Endpoint Limits**
|
||||
- **Purpose**: Protect expensive operations
|
||||
- **Scope**: Specific endpoints (e.g., value estimates)
|
||||
- **Implementation**: Endpoint-specific token buckets
|
||||
|
||||
#### **Dynamic Rate Limiting**
|
||||
```python
|
||||
RATE_LIMITS = {
|
||||
"properties": "60/minute", # Standard property searches
|
||||
"value_estimate": "30/minute", # Expensive AI/ML operations
|
||||
"rent_estimate": "30/minute", # Expensive AI/ML operations
|
||||
"market_stats": "20/minute", # Computationally intensive
|
||||
"listings_sale": "100/minute", # Less expensive, higher volume
|
||||
"listings_rental": "100/minute", # Less expensive, higher volume
|
||||
"comparables": "40/minute" # Moderate complexity
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Database Schema Design
|
||||
|
||||
### Core Tables
|
||||
|
||||
#### **API Keys Management**
|
||||
```sql
|
||||
CREATE TABLE api_keys (
|
||||
id SERIAL PRIMARY KEY,
|
||||
key_name VARCHAR(100) UNIQUE NOT NULL,
|
||||
key_hash VARCHAR(64) UNIQUE NOT NULL, -- SHA-256 hash
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
daily_limit INTEGER DEFAULT 1000,
|
||||
monthly_limit INTEGER DEFAULT 30000,
|
||||
daily_usage INTEGER DEFAULT 0,
|
||||
monthly_usage INTEGER DEFAULT 0,
|
||||
last_daily_reset TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
last_monthly_reset TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
expires_at TIMESTAMP WITH TIME ZONE,
|
||||
last_used TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
```
|
||||
|
||||
#### **Usage Analytics**
|
||||
```sql
|
||||
CREATE TABLE usage_stats (
|
||||
id SERIAL PRIMARY KEY,
|
||||
api_key_id INTEGER REFERENCES api_keys(id),
|
||||
endpoint VARCHAR(50) NOT NULL,
|
||||
method VARCHAR(10) NOT NULL,
|
||||
status_code INTEGER NOT NULL,
|
||||
response_time_ms DECIMAL(10,2) NOT NULL,
|
||||
cache_hit BOOLEAN NOT NULL,
|
||||
estimated_cost DECIMAL(10,2) DEFAULT 0.0,
|
||||
user_agent TEXT,
|
||||
ip_address INET,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
#### **Rate Limiting State**
|
||||
```sql
|
||||
CREATE TABLE rate_limits (
|
||||
id SERIAL PRIMARY KEY,
|
||||
api_key_id INTEGER REFERENCES api_keys(id),
|
||||
endpoint VARCHAR(50) NOT NULL,
|
||||
current_tokens INTEGER DEFAULT 0,
|
||||
last_refill TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(api_key_id, endpoint)
|
||||
);
|
||||
```
|
||||
|
||||
### Indexing Strategy
|
||||
|
||||
```sql
|
||||
-- Performance indexes
|
||||
CREATE INDEX idx_cache_entries_key ON cache_entries(cache_key);
|
||||
CREATE INDEX idx_cache_entries_endpoint_expires ON cache_entries(endpoint, expires_at);
|
||||
CREATE INDEX idx_cache_entries_created_at ON cache_entries(created_at);
|
||||
|
||||
CREATE INDEX idx_usage_stats_api_key_created ON usage_stats(api_key_id, created_at);
|
||||
CREATE INDEX idx_usage_stats_endpoint_created ON usage_stats(endpoint, created_at);
|
||||
CREATE INDEX idx_usage_stats_cache_hit ON usage_stats(cache_hit, created_at);
|
||||
|
||||
CREATE INDEX idx_api_keys_hash ON api_keys(key_hash);
|
||||
CREATE INDEX idx_api_keys_active ON api_keys(is_active);
|
||||
```
|
||||
|
||||
## 🔒 Security Architecture
|
||||
|
||||
### Authentication Flow
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Client --> |Bearer Token| Auth[Auth Middleware]
|
||||
Auth --> Hash[SHA-256 Hash]
|
||||
Hash --> DB[(Database Lookup)]
|
||||
DB --> Validate[Validate Expiry & Status]
|
||||
Validate --> |Valid| Allow[Allow Request]
|
||||
Validate --> |Invalid| Deny[401 Unauthorized]
|
||||
```
|
||||
|
||||
### Security Measures
|
||||
|
||||
#### **API Key Protection**
|
||||
- **Storage**: Only SHA-256 hashes stored, never plaintext
|
||||
- **Transmission**: HTTPS only, bearer token format
|
||||
- **Rotation**: Configurable expiration dates
|
||||
- **Revocation**: Instant deactivation capability
|
||||
|
||||
#### **Network Security**
|
||||
- **HTTPS Enforcement**: Automatic SSL with Caddy
|
||||
- **CORS Configuration**: Configurable origin restrictions
|
||||
- **Rate Limiting**: DDoS and abuse protection
|
||||
- **Request Validation**: Comprehensive input sanitization
|
||||
|
||||
#### **Container Security**
|
||||
- **Non-root User**: Containers run as unprivileged user
|
||||
- **Minimal Images**: Alpine Linux base images
|
||||
- **Secret Management**: Environment variable injection
|
||||
- **Network Isolation**: Docker network segregation
|
||||
|
||||
## 📈 Performance Optimizations
|
||||
|
||||
### Application Level
|
||||
|
||||
#### **Async Architecture**
|
||||
```python
|
||||
# Concurrent request handling
|
||||
async def handle_multiple_requests():
|
||||
tasks = [
|
||||
process_request(req1),
|
||||
process_request(req2),
|
||||
process_request(req3)
|
||||
]
|
||||
results = await asyncio.gather(*tasks)
|
||||
return results
|
||||
```
|
||||
|
||||
#### **Connection Pooling**
|
||||
```python
|
||||
# HTTP client configuration
|
||||
http_client = httpx.AsyncClient(
|
||||
timeout=30.0,
|
||||
limits=httpx.Limits(
|
||||
max_connections=100,
|
||||
max_keepalive_connections=20
|
||||
)
|
||||
)
|
||||
|
||||
# Database connection pooling
|
||||
engine = create_async_engine(
|
||||
DATABASE_URL,
|
||||
pool_size=20,
|
||||
max_overflow=30,
|
||||
pool_pre_ping=True,
|
||||
pool_recycle=3600
|
||||
)
|
||||
```
|
||||
|
||||
#### **Response Optimization**
|
||||
- **GZip Compression**: Automatic response compression
|
||||
- **JSON Streaming**: Large response streaming
|
||||
- **Conditional Requests**: ETag and If-Modified-Since support
|
||||
|
||||
### Database Level
|
||||
|
||||
#### **Query Optimization**
|
||||
```sql
|
||||
-- Efficient cache lookup
|
||||
EXPLAIN ANALYZE
|
||||
SELECT response_data, expires_at, is_valid
|
||||
FROM cache_entries
|
||||
WHERE cache_key = $1
|
||||
AND expires_at > NOW()
|
||||
AND is_valid = TRUE;
|
||||
```
|
||||
|
||||
#### **Connection Management**
|
||||
- **Prepared Statements**: Reduced parsing overhead
|
||||
- **Connection Pooling**: Shared connection resources
|
||||
- **Read Replicas**: Separate analytics queries
|
||||
|
||||
### Caching Level
|
||||
|
||||
#### **Cache Warming Strategies**
|
||||
```python
|
||||
async def warm_cache():
|
||||
"""Pre-populate cache with common requests"""
|
||||
common_requests = [
|
||||
{"endpoint": "properties", "city": "Austin", "state": "TX"},
|
||||
{"endpoint": "properties", "city": "Dallas", "state": "TX"},
|
||||
{"endpoint": "market_stats", "zipCode": "78701"}
|
||||
]
|
||||
|
||||
for request in common_requests:
|
||||
await fetch_and_cache(request)
|
||||
```
|
||||
|
||||
#### **Memory Management**
|
||||
- **TTL Optimization**: Balanced freshness vs. efficiency
|
||||
- **Compression**: Response data compression
|
||||
- **Eviction Policies**: Smart cache replacement
|
||||
|
||||
## 📊 Monitoring and Observability
|
||||
|
||||
### Metrics Collection
|
||||
|
||||
#### **Business Metrics**
|
||||
- Cache hit ratios by endpoint
|
||||
- API cost savings
|
||||
- Request volume trends
|
||||
- Error rates and patterns
|
||||
|
||||
#### **System Metrics**
|
||||
- Response time percentiles
|
||||
- Database query performance
|
||||
- Memory and CPU utilization
|
||||
- Connection pool statistics
|
||||
|
||||
#### **Custom Metrics**
|
||||
```python
|
||||
# Prometheus-style metrics
|
||||
cache_hit_ratio = Gauge('cache_hit_ratio', 'Cache hit ratio by endpoint', ['endpoint'])
|
||||
api_request_duration = Histogram('api_request_duration_seconds', 'API request duration')
|
||||
upstream_calls = Counter('upstream_api_calls_total', 'Total upstream API calls')
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
#### **Application Health**
|
||||
```python
|
||||
async def health_check():
|
||||
checks = {
|
||||
"database": await check_database_connection(),
|
||||
"cache": await check_cache_availability(),
|
||||
"upstream": await check_upstream_api(),
|
||||
"disk_space": await check_disk_usage()
|
||||
}
|
||||
|
||||
overall_status = "healthy" if all(checks.values()) else "unhealthy"
|
||||
return {"status": overall_status, "checks": checks}
|
||||
```
|
||||
|
||||
#### **Dependency Health**
|
||||
- Database connectivity and performance
|
||||
- Redis availability and memory usage
|
||||
- Upstream API response times
|
||||
- Disk space and system resources
|
||||
|
||||
## 🔧 Configuration Management
|
||||
|
||||
### Environment-Based Configuration
|
||||
|
||||
```python
|
||||
class Settings(BaseSettings):
|
||||
# Server
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 8000
|
||||
debug: bool = False
|
||||
|
||||
# Database
|
||||
database_url: str
|
||||
database_echo: bool = False
|
||||
|
||||
# Cache
|
||||
redis_url: Optional[str] = None
|
||||
redis_enabled: bool = False
|
||||
default_cache_ttl: int = 3600
|
||||
|
||||
# Rate Limiting
|
||||
enable_rate_limiting: bool = True
|
||||
global_rate_limit: str = "1000/hour"
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
case_sensitive = False
|
||||
```
|
||||
|
||||
### Feature Flags
|
||||
|
||||
```python
|
||||
class FeatureFlags:
|
||||
ENABLE_REDIS_CACHE = os.getenv("ENABLE_REDIS_CACHE", "true").lower() == "true"
|
||||
ENABLE_ANALYTICS = os.getenv("ENABLE_ANALYTICS", "true").lower() == "true"
|
||||
ENABLE_CACHE_WARMING = os.getenv("ENABLE_CACHE_WARMING", "false").lower() == "true"
|
||||
STRICT_RATE_LIMITING = os.getenv("STRICT_RATE_LIMITING", "false").lower() == "true"
|
||||
```
|
||||
|
||||
## 🚀 Scalability Considerations
|
||||
|
||||
### Horizontal Scaling
|
||||
|
||||
#### **Stateless Design**
|
||||
- No server-side sessions
|
||||
- Shared state in Redis/Database
|
||||
- Load balancer friendly
|
||||
|
||||
#### **Container Orchestration**
|
||||
```yaml
|
||||
# Kubernetes deployment example
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: rentcache
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: rentcache
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: rentcache
|
||||
image: rentcache:latest
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
### Vertical Scaling
|
||||
|
||||
#### **Resource Optimization**
|
||||
- Memory: Cache size tuning
|
||||
- CPU: Async I/O optimization
|
||||
- Storage: Database indexing and partitioning
|
||||
- Network: Connection pooling and keep-alive
|
||||
|
||||
### Data Partitioning
|
||||
|
||||
#### **Database Sharding**
|
||||
```sql
|
||||
-- Partition by date for analytics
|
||||
CREATE TABLE usage_stats (
|
||||
-- columns
|
||||
) PARTITION BY RANGE (created_at);
|
||||
|
||||
CREATE TABLE usage_stats_2024_01 PARTITION OF usage_stats
|
||||
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
|
||||
```
|
||||
|
||||
#### **Cache Distribution**
|
||||
- Redis Cluster for distributed caching
|
||||
- Consistent hashing for cache key distribution
|
||||
- Regional cache replication
|
||||
|
||||
## 🔄 Disaster Recovery
|
||||
|
||||
### Backup Strategy
|
||||
|
||||
#### **Database Backups**
|
||||
```bash
|
||||
# Automated daily backups
|
||||
pg_dump rentcache | gzip > backup-$(date +%Y%m%d).sql.gz
|
||||
|
||||
# Point-in-time recovery
|
||||
pg_basebackup -D /backup/base -Ft -z -P
|
||||
```
|
||||
|
||||
#### **Configuration Backups**
|
||||
- Environment variables
|
||||
- Docker Compose files
|
||||
- SSL certificates
|
||||
- Application configuration
|
||||
|
||||
### Recovery Procedures
|
||||
|
||||
#### **Database Recovery**
|
||||
```bash
|
||||
# Restore from backup
|
||||
gunzip -c backup-20240115.sql.gz | psql rentcache
|
||||
|
||||
# Point-in-time recovery
|
||||
pg_ctl stop -D /var/lib/postgresql/data
|
||||
rm -rf /var/lib/postgresql/data/*
|
||||
pg_basebackup -D /var/lib/postgresql/data -R
|
||||
```
|
||||
|
||||
#### **Cache Recovery**
|
||||
- Redis persistence (RDB + AOF)
|
||||
- Cache warming from database
|
||||
- Graceful degradation to upstream API
|
||||
|
||||
---
|
||||
|
||||
This architecture is designed for high availability, performance, and cost optimization while maintaining security and operational simplicity. For implementation details, see the [Deployment Guide](DEPLOYMENT.md) and [Usage Guide](USAGE.md).
|
583
docs/DEPLOYMENT.md
Normal file
583
docs/DEPLOYMENT.md
Normal file
@ -0,0 +1,583 @@
|
||||
# Deployment Guide
|
||||
|
||||
This guide covers deploying RentCache in production using Docker, with Caddy reverse proxy, and comprehensive monitoring.
|
||||
|
||||
## 🐳 Docker Deployment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Docker Engine**: 20.10+ with Compose V2
|
||||
- **External Caddy Network**: For reverse proxy integration
|
||||
- **Domain**: Configured with DNS pointing to your server
|
||||
- **SSL Certificate**: Automatic with Caddy (Let's Encrypt)
|
||||
|
||||
### Quick Production Deployment
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://git.supported.systems/MCP/rentcache.git
|
||||
cd rentcache
|
||||
|
||||
# Set up environment
|
||||
cp .env.example .env
|
||||
nano .env # Configure your settings
|
||||
|
||||
# Deploy with reverse proxy
|
||||
make setup
|
||||
```
|
||||
|
||||
This command:
|
||||
1. Creates the external Caddy network if needed
|
||||
2. Builds the Docker images
|
||||
3. Starts services with reverse proxy
|
||||
4. Makes RentCache available at your domain
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
#### Production .env File
|
||||
|
||||
```env
|
||||
# Domain Configuration
|
||||
DOMAIN=your-domain.com
|
||||
COMPOSE_PROJECT=rentcache-prod
|
||||
|
||||
# Mode Configuration
|
||||
MODE=production
|
||||
DEBUG=false
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# Server Configuration
|
||||
HOST=0.0.0.0
|
||||
PORT=8000
|
||||
|
||||
# Database Configuration (Production)
|
||||
DATABASE_URL=postgresql://rentcache:secure_password@postgres:5432/rentcache
|
||||
DATABASE_ECHO=false
|
||||
|
||||
# Redis Configuration (Recommended for Production)
|
||||
REDIS_URL=redis://redis:6379
|
||||
REDIS_ENABLED=true
|
||||
|
||||
# Cache Settings (Optimized for Production)
|
||||
DEFAULT_CACHE_TTL=7200
|
||||
EXPENSIVE_ENDPOINTS_TTL=172800
|
||||
ENABLE_STALE_WHILE_REVALIDATE=true
|
||||
|
||||
# Rate Limiting (Production Limits)
|
||||
ENABLE_RATE_LIMITING=true
|
||||
GLOBAL_RATE_LIMIT=2000/hour
|
||||
PER_ENDPOINT_RATE_LIMIT=100/minute
|
||||
|
||||
# Security (Restrict Access)
|
||||
ALLOWED_HOSTS=your-domain.com,api.your-domain.com
|
||||
CORS_ORIGINS=https://your-domain.com,https://app.your-domain.com
|
||||
|
||||
# Monitoring
|
||||
ENABLE_METRICS=true
|
||||
LOG_FORMAT=json
|
||||
```
|
||||
|
||||
### Docker Compose Production Setup
|
||||
|
||||
The included `docker-compose.yml` supports multiple deployment scenarios:
|
||||
|
||||
#### Basic Production Deployment
|
||||
|
||||
```bash
|
||||
# Production mode with PostgreSQL
|
||||
MODE=production docker compose up -d rentcache postgres
|
||||
```
|
||||
|
||||
#### High-Performance Deployment with Redis
|
||||
|
||||
```bash
|
||||
# Production with Redis caching
|
||||
MODE=production docker compose --profile redis up -d
|
||||
```
|
||||
|
||||
#### Development with Hot Reload
|
||||
|
||||
```bash
|
||||
# Development mode with file watching
|
||||
make dev
|
||||
```
|
||||
|
||||
## 🌐 Reverse Proxy with Caddy
|
||||
|
||||
### Caddy Docker Proxy Integration
|
||||
|
||||
RentCache is designed to work with [caddy-docker-proxy](https://github.com/lucaslorentz/caddy-docker-proxy) for automatic HTTPS and load balancing.
|
||||
|
||||
#### Setup External Caddy Network
|
||||
|
||||
```bash
|
||||
# Create the external network (if not exists)
|
||||
docker network create caddy
|
||||
|
||||
# Verify network exists
|
||||
docker network ls | grep caddy
|
||||
```
|
||||
|
||||
#### Caddy Labels Configuration
|
||||
|
||||
The `docker-compose.yml` includes automatic Caddy configuration:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
rentcache:
|
||||
# ... other config
|
||||
networks:
|
||||
- caddy
|
||||
labels:
|
||||
caddy: ${DOMAIN:-rentcache.l.supported.systems}
|
||||
caddy.reverse_proxy: "{{upstreams}}"
|
||||
caddy.header.X-Forwarded-Proto: https
|
||||
caddy.header.X-Real-IP: "{remote_host}"
|
||||
```
|
||||
|
||||
#### Manual Caddy Configuration
|
||||
|
||||
If using standalone Caddy, create a `Caddyfile`:
|
||||
|
||||
```caddyfile
|
||||
your-domain.com {
|
||||
reverse_proxy rentcache:8000
|
||||
|
||||
# Security headers
|
||||
header {
|
||||
X-Content-Type-Options nosniff
|
||||
X-Frame-Options DENY
|
||||
X-XSS-Protection "1; mode=block"
|
||||
Strict-Transport-Security "max-age=31536000;"
|
||||
}
|
||||
|
||||
# Health check endpoint
|
||||
handle /health {
|
||||
reverse_proxy rentcache:8000
|
||||
}
|
||||
|
||||
# API endpoints
|
||||
handle /api/* {
|
||||
reverse_proxy rentcache:8000
|
||||
}
|
||||
|
||||
# Admin endpoints (restrict access)
|
||||
handle /admin/* {
|
||||
reverse_proxy rentcache:8000
|
||||
# Add basic auth or IP restrictions here
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🗄️ Database Configuration
|
||||
|
||||
### PostgreSQL Production Setup
|
||||
|
||||
#### Using Docker Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
environment:
|
||||
POSTGRES_DB: rentcache
|
||||
POSTGRES_USER: rentcache
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
networks:
|
||||
- caddy
|
||||
restart: unless-stopped
|
||||
command: >
|
||||
postgres
|
||||
-c shared_preload_libraries=pg_stat_statements
|
||||
-c max_connections=200
|
||||
-c shared_buffers=256MB
|
||||
-c effective_cache_size=1GB
|
||||
-c maintenance_work_mem=64MB
|
||||
-c checkpoint_completion_target=0.9
|
||||
-c wal_buffers=16MB
|
||||
-c default_statistics_target=100
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
#### External PostgreSQL
|
||||
|
||||
For external PostgreSQL (AWS RDS, Google Cloud SQL, etc.):
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgresql://username:password@host:5432/database?sslmode=require
|
||||
DATABASE_ECHO=false
|
||||
```
|
||||
|
||||
### Redis Configuration
|
||||
|
||||
#### Docker Redis
|
||||
|
||||
```yaml
|
||||
services:
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
command: >
|
||||
redis-server
|
||||
--appendonly yes
|
||||
--appendfsync everysec
|
||||
--save 900 1
|
||||
--save 300 10
|
||||
--save 60 10000
|
||||
--maxmemory 512mb
|
||||
--maxmemory-policy allkeys-lru
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- caddy
|
||||
restart: unless-stopped
|
||||
profiles:
|
||||
- redis
|
||||
|
||||
volumes:
|
||||
redis_data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
#### External Redis
|
||||
|
||||
```env
|
||||
REDIS_URL=redis://username:password@host:6379/0
|
||||
REDIS_ENABLED=true
|
||||
```
|
||||
|
||||
## 🔐 Security Configuration
|
||||
|
||||
### SSL/TLS
|
||||
|
||||
With Caddy, SSL is automatic using Let's Encrypt. For manual SSL:
|
||||
|
||||
```caddyfile
|
||||
your-domain.com {
|
||||
tls your-email@domain.com # Let's Encrypt
|
||||
# OR
|
||||
tls /path/to/cert.pem /path/to/key.pem # Custom certificates
|
||||
|
||||
reverse_proxy rentcache:8000
|
||||
}
|
||||
```
|
||||
|
||||
### API Key Security
|
||||
|
||||
```bash
|
||||
# Create production API key with strict limits
|
||||
docker compose exec rentcache uv run rentcache create-key production_app YOUR_RENTCAST_KEY \
|
||||
--daily-limit 5000 \
|
||||
--monthly-limit 100000 \
|
||||
--expires 2024-12-31
|
||||
|
||||
# Create development key with higher limits
|
||||
docker compose exec rentcache uv run rentcache create-key dev_app YOUR_RENTCAST_KEY \
|
||||
--daily-limit 10000 \
|
||||
--monthly-limit 200000
|
||||
```
|
||||
|
||||
### Network Security
|
||||
|
||||
```yaml
|
||||
# Restrict network access
|
||||
services:
|
||||
rentcache:
|
||||
networks:
|
||||
- caddy
|
||||
- internal
|
||||
# Don't expose ports directly in production
|
||||
|
||||
postgres:
|
||||
networks:
|
||||
- internal # Only internal network
|
||||
# No external access
|
||||
|
||||
redis:
|
||||
networks:
|
||||
- internal # Only internal network
|
||||
|
||||
networks:
|
||||
caddy:
|
||||
external: true
|
||||
internal:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
## 📊 Monitoring and Logging
|
||||
|
||||
### Health Checks
|
||||
|
||||
```yaml
|
||||
services:
|
||||
rentcache:
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
```
|
||||
|
||||
### Logging Configuration
|
||||
|
||||
#### JSON Structured Logging
|
||||
|
||||
```env
|
||||
LOG_FORMAT=json
|
||||
LOG_LEVEL=INFO
|
||||
```
|
||||
|
||||
#### Log Aggregation with Docker
|
||||
|
||||
```yaml
|
||||
services:
|
||||
rentcache:
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "5"
|
||||
tag: "rentcache-{{.Name}}"
|
||||
```
|
||||
|
||||
#### Centralized Logging
|
||||
|
||||
For production, consider using:
|
||||
|
||||
- **ELK Stack** (Elasticsearch, Logstash, Kibana)
|
||||
- **Grafana Loki** with Promtail
|
||||
- **Fluentd** or **Fluent Bit**
|
||||
|
||||
Example Promtail configuration:
|
||||
|
||||
```yaml
|
||||
# promtail-config.yml
|
||||
server:
|
||||
http_listen_port: 9080
|
||||
grpc_listen_port: 0
|
||||
|
||||
positions:
|
||||
filename: /tmp/positions.yaml
|
||||
|
||||
clients:
|
||||
- url: http://loki:3100/loki/api/v1/push
|
||||
|
||||
scrape_configs:
|
||||
- job_name: rentcache
|
||||
docker_sd_configs:
|
||||
- host: unix:///var/run/docker.sock
|
||||
refresh_interval: 5s
|
||||
relabel_configs:
|
||||
- source_labels: ['__meta_docker_container_label_com_docker_compose_service']
|
||||
target_label: 'service'
|
||||
- source_labels: ['__meta_docker_container_name']
|
||||
target_label: 'container'
|
||||
```
|
||||
|
||||
### Metrics Collection
|
||||
|
||||
#### Prometheus Integration
|
||||
|
||||
```yaml
|
||||
# prometheus.yml
|
||||
scrape_configs:
|
||||
- job_name: 'rentcache'
|
||||
static_configs:
|
||||
- targets: ['rentcache:8000']
|
||||
metrics_path: '/metrics'
|
||||
scrape_interval: 30s
|
||||
scrape_timeout: 10s
|
||||
```
|
||||
|
||||
#### Grafana Dashboard
|
||||
|
||||
Key metrics to monitor:
|
||||
|
||||
- **Cache Hit Ratio**: Target > 80%
|
||||
- **Response Time**: 95th percentile < 200ms
|
||||
- **Error Rate**: < 1%
|
||||
- **API Cost**: Daily/monthly spending
|
||||
- **Request Volume**: Requests per minute
|
||||
- **Database Performance**: Query time, connection pool
|
||||
|
||||
## 🚀 Production Deployment Checklist
|
||||
|
||||
### Pre-Deployment
|
||||
|
||||
- [ ] **Environment Variables**: Configure production .env
|
||||
- [ ] **SSL Certificates**: Verify domain and SSL setup
|
||||
- [ ] **Database**: PostgreSQL configured and accessible
|
||||
- [ ] **Redis**: Optional but recommended for performance
|
||||
- [ ] **Monitoring**: Health checks and metrics collection
|
||||
- [ ] **Backup Strategy**: Database and configuration backups
|
||||
- [ ] **Security**: Network restrictions and API key management
|
||||
|
||||
### Deployment Steps
|
||||
|
||||
```bash
|
||||
# 1. Clone and configure
|
||||
git clone https://git.supported.systems/MCP/rentcache.git
|
||||
cd rentcache
|
||||
cp .env.example .env
|
||||
# Edit .env with production settings
|
||||
|
||||
# 2. Deploy
|
||||
make setup
|
||||
|
||||
# 3. Verify deployment
|
||||
curl https://your-domain.com/health
|
||||
|
||||
# 4. Create API keys
|
||||
make create-key NAME=production_app KEY=your_rentcast_key
|
||||
|
||||
# 5. Test API access
|
||||
curl -H "Authorization: Bearer your_rentcast_key" \
|
||||
"https://your-domain.com/api/v1/properties?city=Austin&state=TX&limit=1"
|
||||
|
||||
# 6. Monitor metrics
|
||||
curl https://your-domain.com/metrics
|
||||
```
|
||||
|
||||
### Post-Deployment
|
||||
|
||||
- [ ] **Monitor Logs**: Check for errors and warnings
|
||||
- [ ] **Test All Endpoints**: Verify API functionality
|
||||
- [ ] **Cache Performance**: Monitor hit ratios
|
||||
- [ ] **Cost Tracking**: Track API cost savings
|
||||
- [ ] **Backup Verification**: Test restore procedures
|
||||
- [ ] **Performance Baseline**: Establish performance metrics
|
||||
|
||||
## 🔄 Maintenance and Updates
|
||||
|
||||
### Regular Maintenance
|
||||
|
||||
```bash
|
||||
# Update containers
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
|
||||
# Clean old images
|
||||
docker system prune -f
|
||||
|
||||
# Check logs
|
||||
make logs
|
||||
|
||||
# Monitor health
|
||||
make health
|
||||
|
||||
# View statistics
|
||||
make stats
|
||||
```
|
||||
|
||||
### Database Maintenance
|
||||
|
||||
```bash
|
||||
# PostgreSQL maintenance
|
||||
docker compose exec postgres psql -U rentcache -d rentcache -c "VACUUM ANALYZE;"
|
||||
|
||||
# Clear old cache entries (older than 7 days)
|
||||
docker compose exec rentcache uv run rentcache clear-cache --older-than 168
|
||||
```
|
||||
|
||||
### Backup Procedures
|
||||
|
||||
```bash
|
||||
# Database backup
|
||||
docker compose exec postgres pg_dump -U rentcache rentcache > backup-$(date +%Y%m%d).sql
|
||||
|
||||
# Configuration backup
|
||||
tar -czf config-backup-$(date +%Y%m%d).tar.gz .env docker-compose.yml
|
||||
|
||||
# Restore database
|
||||
docker compose exec -T postgres psql -U rentcache -d rentcache < backup-20240115.sql
|
||||
```
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Service Won't Start
|
||||
|
||||
```bash
|
||||
# Check logs
|
||||
docker compose logs rentcache
|
||||
|
||||
# Check network
|
||||
docker network ls | grep caddy
|
||||
|
||||
# Verify configuration
|
||||
docker compose config
|
||||
```
|
||||
|
||||
#### SSL Certificate Issues
|
||||
|
||||
```bash
|
||||
# Check Caddy logs
|
||||
docker logs caddy-docker-proxy
|
||||
|
||||
# Force certificate renewal
|
||||
docker exec caddy-docker-proxy caddy reload
|
||||
```
|
||||
|
||||
#### Database Connection Issues
|
||||
|
||||
```bash
|
||||
# Test database connection
|
||||
docker compose exec rentcache uv run python -c "
|
||||
from sqlalchemy import create_engine
|
||||
engine = create_engine('$DATABASE_URL')
|
||||
print('Database connection successful!')
|
||||
"
|
||||
```
|
||||
|
||||
#### High Response Times
|
||||
|
||||
```bash
|
||||
# Enable Redis if not already
|
||||
docker compose --profile redis up -d
|
||||
|
||||
# Check cache hit ratio
|
||||
curl https://your-domain.com/metrics | jq '.cache_hit_ratio'
|
||||
|
||||
# Monitor database performance
|
||||
docker compose exec postgres psql -U rentcache -d rentcache -c "
|
||||
SELECT query, mean_time, calls
|
||||
FROM pg_stat_statements
|
||||
ORDER BY mean_time DESC
|
||||
LIMIT 10;"
|
||||
```
|
||||
|
||||
### Performance Tuning
|
||||
|
||||
#### Database Optimization
|
||||
|
||||
```sql
|
||||
-- Create indexes for better performance
|
||||
CREATE INDEX IF NOT EXISTS idx_cache_entries_endpoint ON cache_entries(endpoint);
|
||||
CREATE INDEX IF NOT EXISTS idx_cache_entries_created_at ON cache_entries(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_stats_api_key_id ON usage_stats(api_key_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_stats_created_at ON usage_stats(created_at);
|
||||
```
|
||||
|
||||
#### Application Tuning
|
||||
|
||||
```env
|
||||
# Increase cache TTLs for stable data
|
||||
DEFAULT_CACHE_TTL=7200
|
||||
EXPENSIVE_ENDPOINTS_TTL=172800
|
||||
|
||||
# Optimize rate limits
|
||||
GLOBAL_RATE_LIMIT=5000/hour
|
||||
PER_ENDPOINT_RATE_LIMIT=200/minute
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Ready for production? Ensure you've followed all security best practices and monitoring is properly configured. Check the [Architecture Guide](ARCHITECTURE.md) for system design details.
|
391
docs/QUICKSTART.md
Normal file
391
docs/QUICKSTART.md
Normal file
@ -0,0 +1,391 @@
|
||||
# Quick Start Guide
|
||||
|
||||
Get RentCache running in 5 minutes and start saving on Rentcast API costs immediately.
|
||||
|
||||
## ⚡ 5-Minute Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Docker & Docker Compose**: [Install Docker](https://docs.docker.com/get-docker/)
|
||||
- **Rentcast API Key**: [Get your key](https://developers.rentcast.io/)
|
||||
- **Domain** (optional): For production deployment
|
||||
|
||||
### Step 1: Clone and Configure
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://git.supported.systems/MCP/rentcache.git
|
||||
cd rentcache
|
||||
|
||||
# Quick setup with defaults
|
||||
make setup
|
||||
```
|
||||
|
||||
### Step 2: Create API Key
|
||||
|
||||
```bash
|
||||
# Replace 'your_rentcast_api_key' with your actual Rentcast API key
|
||||
make create-key NAME=quickstart KEY=your_rentcast_api_key
|
||||
```
|
||||
|
||||
### Step 3: Test Your Setup
|
||||
|
||||
```bash
|
||||
# Test with a simple property search
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX&limit=1"
|
||||
```
|
||||
|
||||
**🎉 That's it!** RentCache is now proxying your Rentcast API calls with intelligent caching.
|
||||
|
||||
## 🔍 Verify Everything Works
|
||||
|
||||
### Check System Health
|
||||
|
||||
```bash
|
||||
curl https://rentcache.l.supported.systems/health
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2024-01-15T10:30:00Z",
|
||||
"version": "1.0.0",
|
||||
"database": "healthy",
|
||||
"cache_backend": "sqlite",
|
||||
"active_keys": 1,
|
||||
"total_cache_entries": 0,
|
||||
"cache_hit_ratio_24h": null
|
||||
}
|
||||
```
|
||||
|
||||
### View API Documentation
|
||||
|
||||
Open in browser: **https://rentcache.l.supported.systems/docs**
|
||||
|
||||
### Monitor Performance
|
||||
|
||||
```bash
|
||||
# View real-time metrics
|
||||
curl https://rentcache.l.supported.systems/metrics | jq
|
||||
```
|
||||
|
||||
## 🚀 First API Calls
|
||||
|
||||
### Property Search
|
||||
|
||||
```bash
|
||||
# Search properties in Austin, TX
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX&limit=5"
|
||||
```
|
||||
|
||||
### Value Estimate
|
||||
|
||||
```bash
|
||||
# Get property value estimate
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/value?address=123%20Main%20St&city=Austin&state=TX"
|
||||
```
|
||||
|
||||
### Rent Estimate
|
||||
|
||||
```bash
|
||||
# Get rent estimate
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/rent?address=123%20Main%20St&city=Austin&state=TX"
|
||||
```
|
||||
|
||||
### Market Statistics
|
||||
|
||||
```bash
|
||||
# Get market stats for ZIP code
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/markets/stats?zipCode=78701"
|
||||
```
|
||||
|
||||
## 💰 See Your Savings
|
||||
|
||||
### Make the Same Call Twice
|
||||
|
||||
```bash
|
||||
# First call (cache miss - costs money)
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Dallas&state=TX&limit=1"
|
||||
|
||||
# Second call (cache hit - FREE!)
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Dallas&state=TX&limit=1"
|
||||
```
|
||||
|
||||
### Check Response Headers
|
||||
|
||||
```bash
|
||||
# Look for cache hit indicators
|
||||
curl -I -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Dallas&state=TX&limit=1"
|
||||
```
|
||||
|
||||
**Response Headers:**
|
||||
```
|
||||
X-Cache-Hit: true
|
||||
X-Response-Time-MS: 12.5
|
||||
# X-Estimated-Cost header only appears on cache misses
|
||||
```
|
||||
|
||||
### View Usage Statistics
|
||||
|
||||
```bash
|
||||
# Check your savings so far
|
||||
curl https://rentcache.l.supported.systems/metrics | jq '{
|
||||
total_requests: .total_requests,
|
||||
cache_hits: .cache_hits,
|
||||
cache_hit_ratio: .cache_hit_ratio,
|
||||
estimated_savings: "Calculated from cache hits"
|
||||
}'
|
||||
```
|
||||
|
||||
## 🔧 Common Use Cases
|
||||
|
||||
### Real Estate Applications
|
||||
|
||||
#### Property Portfolio Analysis
|
||||
```bash
|
||||
# Get multiple properties in a neighborhood
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?zipCode=78701&limit=50"
|
||||
|
||||
# Get value estimates for each (subsequent calls will be cached)
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/value?zipCode=78701&propertyType=Single%20Family"
|
||||
```
|
||||
|
||||
#### Market Research
|
||||
```bash
|
||||
# Research multiple markets efficiently
|
||||
for city in Austin Dallas Houston; do
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/markets/stats?city=$city&state=TX"
|
||||
done
|
||||
```
|
||||
|
||||
#### Rental Property Management
|
||||
```bash
|
||||
# Monitor rental market for your properties
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/listings/rental?city=Austin&state=TX&bedrooms=3&limit=20"
|
||||
|
||||
# Get rent estimates for comparison
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/rent?address=123%20Property%20St&city=Austin&state=TX"
|
||||
```
|
||||
|
||||
### Investment Analysis
|
||||
|
||||
#### Comparative Market Analysis
|
||||
```bash
|
||||
# Get comparable properties
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/comparables?address=456%20Investment%20Ave&city=Austin&state=TX"
|
||||
|
||||
# Analyze multiple similar properties (cached for efficiency)
|
||||
for address in "123 Main St" "456 Oak Ave" "789 Pine St"; do
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/value?address=$address&city=Austin&state=TX"
|
||||
done
|
||||
```
|
||||
|
||||
## 🎛️ Cache Control
|
||||
|
||||
### Force Fresh Data
|
||||
|
||||
When you need the absolute latest data:
|
||||
|
||||
```bash
|
||||
# Force refresh (bypasses cache)
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/value?address=123%20Main%20St&city=Austin&state=TX&force_refresh=true"
|
||||
```
|
||||
|
||||
### Custom Cache Duration
|
||||
|
||||
Set custom cache times for your specific needs:
|
||||
|
||||
```bash
|
||||
# Cache for 2 hours (7200 seconds)
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX&ttl_override=7200"
|
||||
|
||||
# Cache for 10 minutes (600 seconds) for frequently changing data
|
||||
curl -H "Authorization: Bearer your_rentcast_api_key" \
|
||||
"https://rentcache.l.supported.systems/api/v1/listings/rental?city=Austin&state=TX&ttl_override=600"
|
||||
```
|
||||
|
||||
## 📊 Monitoring Your Usage
|
||||
|
||||
### Real-Time Dashboard
|
||||
|
||||
Access your usage dashboard:
|
||||
**https://rentcache.l.supported.systems/docs**
|
||||
|
||||
### CLI Monitoring
|
||||
|
||||
```bash
|
||||
# View usage statistics
|
||||
make stats
|
||||
|
||||
# Check system health
|
||||
make health
|
||||
|
||||
# View recent logs
|
||||
make logs
|
||||
```
|
||||
|
||||
### Key Metrics to Watch
|
||||
|
||||
1. **Cache Hit Ratio**: Aim for >80%
|
||||
```bash
|
||||
curl -s https://rentcache.l.supported.systems/metrics | jq '.cache_hit_ratio'
|
||||
```
|
||||
|
||||
2. **Response Times**: Should be <50ms for cache hits
|
||||
```bash
|
||||
curl -s https://rentcache.l.supported.systems/metrics | jq '.avg_response_time_ms'
|
||||
```
|
||||
|
||||
3. **Cost Savings**: Track your monthly savings
|
||||
```bash
|
||||
curl -s https://rentcache.l.supported.systems/metrics | jq '.cost_24h'
|
||||
```
|
||||
|
||||
## 🛠️ Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### "401 Unauthorized" Error
|
||||
```bash
|
||||
# Check if your API key is created and active
|
||||
make list-keys
|
||||
|
||||
# Recreate if needed
|
||||
make create-key NAME=quickstart KEY=your_correct_rentcast_key
|
||||
```
|
||||
|
||||
#### "Service Unavailable" Error
|
||||
```bash
|
||||
# Check system health
|
||||
curl https://rentcache.l.supported.systems/health
|
||||
|
||||
# Check logs
|
||||
make logs
|
||||
```
|
||||
|
||||
#### Slow Response Times
|
||||
```bash
|
||||
# Check if Redis is enabled for better cache performance
|
||||
make dev # Includes Redis profile
|
||||
```
|
||||
|
||||
### Getting Help
|
||||
|
||||
1. **Check Logs**: `make logs`
|
||||
2. **Verify Health**: `curl https://rentcache.l.supported.systems/health`
|
||||
3. **Test API Key**: `make list-keys`
|
||||
4. **View Documentation**: https://rentcache.l.supported.systems/docs
|
||||
|
||||
## 🎯 Next Steps
|
||||
|
||||
### Optimize for Your Workload
|
||||
|
||||
1. **Adjust Cache TTLs**: Based on your data freshness needs
|
||||
2. **Monitor Usage Patterns**: Use the metrics endpoint
|
||||
3. **Set Up Alerts**: Monitor cache hit ratios and costs
|
||||
4. **Scale Resources**: Add Redis for high-traffic applications
|
||||
|
||||
### Integration Examples
|
||||
|
||||
#### Python Application
|
||||
```python
|
||||
import httpx
|
||||
|
||||
class RentCacheClient:
|
||||
def __init__(self, api_key: str, base_url: str = "https://rentcache.l.supported.systems"):
|
||||
self.api_key = api_key
|
||||
self.base_url = base_url
|
||||
self.client = httpx.AsyncClient()
|
||||
|
||||
async def search_properties(self, city: str, state: str, limit: int = 10):
|
||||
headers = {"Authorization": f"Bearer {self.api_key}"}
|
||||
params = {"city": city, "state": state, "limit": limit}
|
||||
|
||||
response = await self.client.get(
|
||||
f"{self.base_url}/api/v1/properties",
|
||||
headers=headers,
|
||||
params=params
|
||||
)
|
||||
return response.json()
|
||||
|
||||
# Usage
|
||||
client = RentCacheClient("your_rentcast_api_key")
|
||||
properties = await client.search_properties("Austin", "TX")
|
||||
```
|
||||
|
||||
#### Node.js Application
|
||||
```javascript
|
||||
const axios = require('axios');
|
||||
|
||||
class RentCacheClient {
|
||||
constructor(apiKey, baseUrl = 'https://rentcache.l.supported.systems') {
|
||||
this.apiKey = apiKey;
|
||||
this.baseUrl = baseUrl;
|
||||
this.client = axios.create({
|
||||
baseURL: baseUrl,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiKey}`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async searchProperties(city, state, limit = 10) {
|
||||
const response = await this.client.get('/api/v1/properties', {
|
||||
params: { city, state, limit }
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
const client = new RentCacheClient('your_rentcast_api_key');
|
||||
const properties = await client.searchProperties('Austin', 'TX');
|
||||
```
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
#### Custom Deployment
|
||||
```bash
|
||||
# Clone for custom configuration
|
||||
git clone https://git.supported.systems/MCP/rentcache.git
|
||||
cd rentcache
|
||||
|
||||
# Edit configuration
|
||||
cp .env.example .env
|
||||
nano .env # Customize settings
|
||||
|
||||
# Deploy with custom config
|
||||
make setup
|
||||
```
|
||||
|
||||
#### Production Deployment
|
||||
See the [Deployment Guide](DEPLOYMENT.md) for:
|
||||
- PostgreSQL database setup
|
||||
- Redis configuration
|
||||
- SSL certificate management
|
||||
- Monitoring and alerting
|
||||
- Backup strategies
|
||||
|
||||
---
|
||||
|
||||
**🎉 Congratulations!** You're now using RentCache to reduce your Rentcast API costs. Monitor your cache hit ratio and enjoy the savings!
|
||||
|
||||
**Need help?** Check the [Usage Guide](USAGE.md) for detailed examples or the [API Reference](API.md) for complete endpoint documentation.
|
@ -132,6 +132,10 @@ curl -H "X-Api-Key: YOUR_RENTCAST_KEY" \
|
||||
"https://api.rentcast.io/v1/properties?city=Austin&state=TX"
|
||||
|
||||
# Through RentCache (what you should do now)
|
||||
curl -H "Authorization: Bearer YOUR_RENTCAST_KEY" \
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX"
|
||||
|
||||
# Or for local development
|
||||
curl -H "Authorization: Bearer YOUR_RENTCAST_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?city=Austin&state=TX"
|
||||
```
|
||||
@ -143,22 +147,22 @@ curl -H "Authorization: Bearer YOUR_RENTCAST_KEY" \
|
||||
```bash
|
||||
# Basic property search
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?city=Austin&state=TX&limit=10"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX&limit=10"
|
||||
|
||||
# Advanced property search
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?address=123%20Main%20St&zipCode=78701&propertyType=Single%20Family&bedrooms=3&bathrooms=2&squareFootage=1500"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?address=123%20Main%20St&zipCode=78701&propertyType=Single%20Family&bedrooms=3&bathrooms=2&squareFootage=1500"
|
||||
|
||||
# With pagination
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?city=Austin&state=TX&offset=20&limit=20"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX&offset=20&limit=20"
|
||||
```
|
||||
|
||||
#### Get Property by ID
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties/12345"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties/12345"
|
||||
```
|
||||
|
||||
### Value and Rent Estimates
|
||||
@ -168,11 +172,11 @@ curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
```bash
|
||||
# Get value estimate
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/estimates/value?address=123%20Main%20St&city=Austin&state=TX"
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/value?address=123%20Main%20St&city=Austin&state=TX"
|
||||
|
||||
# Value estimate with property details
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/estimates/value?zipCode=78701&propertyType=Single%20Family&bedrooms=3&bathrooms=2&squareFootage=1800"
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/value?zipCode=78701&propertyType=Single%20Family&bedrooms=3&bathrooms=2&squareFootage=1800"
|
||||
```
|
||||
|
||||
#### Rent Estimates
|
||||
@ -256,7 +260,7 @@ Force a fresh API call even if cached data exists:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?city=Austin&state=TX&force_refresh=true"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX&force_refresh=true"
|
||||
```
|
||||
|
||||
#### Override TTL
|
||||
@ -266,11 +270,11 @@ Set custom cache duration (in seconds):
|
||||
```bash
|
||||
# Cache for 2 hours (7200 seconds)
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/estimates/value?address=123%20Main%20St&ttl_override=7200"
|
||||
"https://rentcache.l.supported.systems/api/v1/estimates/value?address=123%20Main%20St&ttl_override=7200"
|
||||
|
||||
# Cache for 10 minutes (600 seconds)
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/listings/sale?city=Austin&ttl_override=600"
|
||||
"https://rentcache.l.supported.systems/api/v1/listings/sale?city=Austin&ttl_override=600"
|
||||
```
|
||||
|
||||
### Reading Response Headers
|
||||
@ -279,7 +283,7 @@ Every response includes cache information:
|
||||
|
||||
```bash
|
||||
curl -I -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?city=Austin&state=TX"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?city=Austin&state=TX"
|
||||
|
||||
# Response headers include:
|
||||
# X-Cache-Hit: true
|
||||
@ -363,10 +367,10 @@ uv run rentcache health
|
||||
|
||||
```bash
|
||||
# Get detailed system metrics
|
||||
curl http://localhost:8000/metrics | jq '.'
|
||||
curl https://rentcache.l.supported.systems/metrics | jq '.'
|
||||
|
||||
# Key metrics to monitor:
|
||||
curl http://localhost:8000/metrics | jq '{
|
||||
curl https://rentcache.l.supported.systems/metrics | jq '{
|
||||
cache_hit_ratio: .cache_hit_ratio,
|
||||
avg_response_time: .avg_response_time_ms,
|
||||
requests_24h: .requests_24h,
|
||||
@ -396,10 +400,10 @@ RentCache tracks estimated costs for different endpoint types:
|
||||
uv run rentcache stats | grep -A 5 "Cost"
|
||||
|
||||
# Daily cost tracking
|
||||
curl http://localhost:8000/metrics | jq '.cost_24h'
|
||||
curl https://rentcache.l.supported.systems/metrics | jq '.cost_24h'
|
||||
|
||||
# Calculate savings
|
||||
curl http://localhost:8000/metrics | jq '
|
||||
curl https://rentcache.l.supported.systems/metrics | jq '
|
||||
.total_requests as $total |
|
||||
.cache_hits as $hits |
|
||||
($hits / $total * 100) as $hit_ratio |
|
||||
@ -413,21 +417,21 @@ curl http://localhost:8000/metrics | jq '
|
||||
```bash
|
||||
# Cache property records for 48 hours instead of 24
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?address=123%20Main%20St&ttl_override=172800"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?address=123%20Main%20St&ttl_override=172800"
|
||||
```
|
||||
|
||||
2. **Batch Related Requests**:
|
||||
```bash
|
||||
# Instead of multiple individual requests, search broader then filter locally
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/properties?zipCode=78701&limit=100"
|
||||
"https://rentcache.l.supported.systems/api/v1/properties?zipCode=78701&limit=100"
|
||||
```
|
||||
|
||||
3. **Use Appropriate Endpoints**:
|
||||
```bash
|
||||
# Use less expensive listing searches when you don't need full property records
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
"http://localhost:8000/api/v1/listings/sale?city=Austin&state=TX"
|
||||
"https://rentcache.l.supported.systems/api/v1/listings/sale?city=Austin&state=TX"
|
||||
```
|
||||
|
||||
## 🔧 Advanced Configuration
|
||||
@ -597,7 +601,7 @@ tail -f /var/log/rentcache.log | grep "ERROR\|WARNING"
|
||||
|
||||
```bash
|
||||
# Monitor request patterns
|
||||
watch -n 5 'curl -s http://localhost:8000/metrics | jq "{requests_24h, cache_hits_24h, hit_ratio: (.cache_hits_24h / .requests_24h * 100)}"'
|
||||
watch -n 5 'curl -s https://rentcache.l.supported.systems/metrics | jq "{requests_24h, cache_hits_24h, hit_ratio: (.cache_hits_24h / .requests_24h * 100)}"'
|
||||
|
||||
# Monitor system resources
|
||||
htop
|
||||
|
Loading…
x
Reference in New Issue
Block a user