QuickDID is a high-performance AT Protocol identity resolution service written in Rust. It provides handle-to-DID resolution with Redis-backed caching and queue processing.
52
fork

Configure Feed

Select the types of activity you want to include in your feed.

documentation: Updating README

+82 -7
+48 -6
CLAUDE.md
··· 54 54 - `SqliteHandleResolver`: SQLite-backed persistent caching 55 55 - Uses binary serialization via `HandleResolutionResult` for space efficiency 56 56 - Resolution stack: Cache → RateLimited (optional) → Base → DNS/HTTP 57 + - Includes resolution timing measurements for metrics 57 58 58 59 2. **Binary Serialization** (`src/handle_resolution_result.rs`) 59 60 - Compact storage format using bincode ··· 70 71 - XRPC endpoints for AT Protocol compatibility 71 72 - Health check endpoint 72 73 - DID document serving via .well-known 74 + - CORS headers support for cross-origin requests 75 + - Cache-Control headers with configurable max-age and stale directives 76 + - ETag support with configurable seed for cache invalidation 77 + 78 + 5. **Metrics System** (`src/metrics.rs`) 79 + - Pluggable metrics publishing with StatsD support 80 + - Tracks counters, gauges, and timings 81 + - Configurable tags for environment/service identification 82 + - No-op adapter for development environments 73 83 74 84 ## Key Technical Details 75 85 ··· 98 108 - `HTTP_EXTERNAL`: External hostname for service endpoints (e.g., `localhost:3007`) 99 109 - `SERVICE_KEY`: Private key for service identity (DID format) 100 110 101 - ### Optional 111 + ### Optional - Core Configuration 102 112 - `HTTP_PORT`: Server port (default: 8080) 103 113 - `PLC_HOSTNAME`: PLC directory hostname (default: plc.directory) 114 + - `RUST_LOG`: Logging level (e.g., debug, info) 115 + 116 + ### Optional - Caching 104 117 - `REDIS_URL`: Redis connection URL for caching 105 118 - `SQLITE_URL`: SQLite database URL for caching (e.g., `sqlite:./quickdid.db`) 119 + - `CACHE_TTL_MEMORY`: TTL for in-memory cache in seconds (default: 600) 120 + - `CACHE_TTL_REDIS`: TTL for Redis cache in seconds (default: 7776000) 121 + - `CACHE_TTL_SQLITE`: TTL for SQLite cache in seconds (default: 7776000) 122 + 123 + ### Optional - Queue Configuration 106 124 - `QUEUE_ADAPTER`: Queue type - 'mpsc', 'redis', 'sqlite', 'noop', or 'none' (default: mpsc) 107 125 - `QUEUE_REDIS_PREFIX`: Redis key prefix for queues (default: queue:handleresolver:) 108 126 - `QUEUE_WORKER_ID`: Worker ID for queue operations (default: worker1) 109 127 - `QUEUE_BUFFER_SIZE`: Buffer size for MPSC queue (default: 1000) 110 128 - `QUEUE_SQLITE_MAX_SIZE`: Max queue size for SQLite work shedding (default: 10000) 111 - - `CACHE_TTL_MEMORY`: TTL for in-memory cache in seconds (default: 600) 112 - - `CACHE_TTL_REDIS`: TTL for Redis cache in seconds (default: 7776000) 113 - - `CACHE_TTL_SQLITE`: TTL for SQLite cache in seconds (default: 7776000) 114 129 - `QUEUE_REDIS_TIMEOUT`: Redis blocking timeout in seconds (default: 5) 130 + 131 + ### Optional - Rate Limiting 115 132 - `RESOLVER_MAX_CONCURRENT`: Maximum concurrent handle resolutions (default: 0 = disabled) 116 133 - `RESOLVER_MAX_CONCURRENT_TIMEOUT_MS`: Timeout for acquiring rate limit permit in ms (default: 0 = no timeout) 117 - - `RUST_LOG`: Logging level (e.g., debug, info) 134 + 135 + ### Optional - HTTP Cache Control 136 + - `CACHE_MAX_AGE`: Max-age for Cache-Control header in seconds (default: 86400) 137 + - `CACHE_STALE_IF_ERROR`: Stale-if-error directive in seconds (default: 172800) 138 + - `CACHE_STALE_WHILE_REVALIDATE`: Stale-while-revalidate directive in seconds (default: 86400) 139 + - `CACHE_MAX_STALE`: Max-stale directive in seconds (default: 86400) 140 + - `ETAG_SEED`: Seed value for ETag generation (default: application version) 141 + 142 + ### Optional - Metrics 143 + - `METRICS_ADAPTER`: Metrics adapter type - 'noop' or 'statsd' (default: noop) 144 + - `METRICS_STATSD_HOST`: StatsD host and port (required when METRICS_ADAPTER=statsd, e.g., localhost:8125) 145 + - `METRICS_PREFIX`: Prefix for all metrics (default: quickdid) 146 + - `METRICS_TAGS`: Comma-separated tags (e.g., env:prod,service:quickdid) 118 147 119 148 ## Error Handling 120 149 ··· 171 200 - Connection pooling for Redis 172 201 - Configurable TTLs for cache entries 173 202 - Rate limiting via semaphore-based concurrency control 203 + - HTTP caching with ETag and Cache-Control headers 204 + - Resolution timing metrics for performance monitoring 174 205 175 206 ### Code Style 176 207 - Follow existing Rust idioms and patterns 177 208 - Use `tracing` for logging, not `println!` 178 209 - Prefer `Arc` for shared state across async tasks 179 210 - Handle errors explicitly, avoid `.unwrap()` in production code 211 + - Use `httpdate` crate for HTTP date formatting (not `chrono`) 180 212 181 213 ## Common Tasks 182 214 ··· 189 221 - For in-memory: Set `CACHE_TTL_MEMORY` environment variable 190 222 - For Redis: Set `CACHE_TTL_REDIS` environment variable 191 223 - For SQLite: Set `CACHE_TTL_SQLITE` environment variable 224 + 225 + ### Configuring Metrics 226 + 1. Set `METRICS_ADAPTER=statsd` and `METRICS_STATSD_HOST=localhost:8125` 227 + 2. Configure tags with `METRICS_TAGS=env:prod,service:quickdid` 228 + 3. Use Telegraf + TimescaleDB for aggregation (see `docs/telegraf-timescaledb-metrics-guide.md`) 229 + 4. Railway deployment resources available in `railway-resources/telegraf/` 192 230 193 231 ### Debugging Resolution Issues 194 232 1. Enable debug logging: `RUST_LOG=debug` ··· 197 235 4. Monitor queue processing in logs 198 236 5. Check rate limiting: Look for "Rate limit permit acquisition timed out" errors 199 237 6. Verify DNS/HTTP connectivity to AT Protocol infrastructure 238 + 7. Monitor metrics for resolution timing and cache hit rates 200 239 201 240 ## Dependencies 202 241 - `atproto-identity`: Core AT Protocol identity resolution ··· 204 243 - `deadpool-redis`: Redis connection pooling 205 244 - `metrohash`: Fast non-cryptographic hashing 206 245 - `tokio`: Async runtime 207 - - `axum`: Web framework 246 + - `axum`: Web framework 247 + - `httpdate`: HTTP date formatting (replacing chrono) 248 + - `cadence`: StatsD metrics client 249 + - `thiserror`: Error handling
+34 -1
README.md
··· 25 25 - In-memory caching with configurable TTL (default: 600 seconds) 26 26 - Redis-backed persistent caching (default: 90-day TTL) 27 27 - SQLite-backed persistent caching (default: 90-day TTL) 28 + - **HTTP Caching**: Client-side caching support with: 29 + - ETag generation with configurable seed for cache invalidation 30 + - Cache-Control headers with max-age, stale-while-revalidate, and stale-if-error directives 31 + - CORS headers for cross-origin requests 28 32 - **Rate Limiting**: Semaphore-based concurrency control with optional timeout to protect upstream services 29 33 - **Binary Serialization**: Compact storage format reduces cache size by ~40% compared to JSON 30 34 - **Queue Processing**: Asynchronous handle resolution with multiple adapters: ··· 32 36 - Redis (distributed) 33 37 - SQLite (persistent with work shedding) 34 38 - No-op (testing) 39 + - **Metrics & Monitoring**: 40 + - StatsD metrics support for counters, gauges, and timings 41 + - Resolution timing measurements 42 + - Configurable tags for environment/service identification 43 + - Integration guides for Telegraf and TimescaleDB 35 44 - **AT Protocol Compatible**: Implements XRPC endpoints for seamless integration with AT Protocol infrastructure 36 45 - **Comprehensive Error Handling**: Structured errors with unique identifiers (e.g., `error-quickdid-config-1`), health checks, and graceful shutdown 37 46 - **12-Factor App**: Environment-based configuration following cloud-native best practices ··· 116 125 - `RESOLVER_MAX_CONCURRENT`: Maximum concurrent handle resolutions (default: 0 = disabled) 117 126 - `RESOLVER_MAX_CONCURRENT_TIMEOUT_MS`: Timeout for acquiring rate limit permit in ms (default: 0 = no timeout) 118 127 128 + #### HTTP Cache Control 129 + - `CACHE_MAX_AGE`: Max-age for Cache-Control header in seconds (default: 86400) 130 + - `CACHE_STALE_IF_ERROR`: Stale-if-error directive in seconds (default: 172800) 131 + - `CACHE_STALE_WHILE_REVALIDATE`: Stale-while-revalidate in seconds (default: 86400) 132 + - `CACHE_MAX_STALE`: Max-stale directive in seconds (default: 86400) 133 + - `ETAG_SEED`: Seed value for ETag generation (default: application version) 134 + 135 + #### Metrics 136 + - `METRICS_ADAPTER`: Metrics adapter type - 'noop' or 'statsd' (default: noop) 137 + - `METRICS_STATSD_HOST`: StatsD host and port (required when METRICS_ADAPTER=statsd) 138 + - `METRICS_PREFIX`: Prefix for all metrics (default: quickdid) 139 + - `METRICS_TAGS`: Comma-separated tags (e.g., env:prod,service:quickdid) 140 + 119 141 #### Logging 120 142 - `RUST_LOG`: Logging level (e.g., debug, info, warn, error) 121 143 122 144 ### Production Examples 123 145 124 - #### Redis-based (Multi-instance/HA) 146 + #### Redis-based with Metrics (Multi-instance/HA) 125 147 ```bash 126 148 HTTP_EXTERNAL=quickdid.example.com \ 127 149 SERVICE_KEY=did:key:yourkeyhere \ ··· 132 154 QUEUE_WORKER_ID=prod-worker-1 \ 133 155 RESOLVER_MAX_CONCURRENT=100 \ 134 156 RESOLVER_MAX_CONCURRENT_TIMEOUT_MS=5000 \ 157 + METRICS_ADAPTER=statsd \ 158 + METRICS_STATSD_HOST=localhost:8125 \ 159 + METRICS_PREFIX=quickdid \ 160 + METRICS_TAGS=env:prod,service:quickdid \ 161 + CACHE_MAX_AGE=86400 \ 135 162 RUST_LOG=info \ 136 163 ./target/release/quickdid 137 164 ``` ··· 178 205 - `GET /_health` - Health check endpoint 179 206 - `GET /xrpc/com.atproto.identity.resolveHandle` - Resolve handle to DID 180 207 - `GET /.well-known/atproto-did` - Serve DID document for the service 208 + - `OPTIONS /*` - CORS preflight support for all endpoints 181 209 182 210 ## Docker Deployment 183 211 ··· 201 229 202 230 - [Configuration Reference](docs/configuration-reference.md) - Complete list of all configuration options 203 231 - [Production Deployment Guide](docs/production-deployment.md) - Docker, monitoring, and production best practices 232 + - [Metrics Guide](docs/telegraf-timescaledb-metrics-guide.md) - Setting up metrics with Telegraf and TimescaleDB 204 233 - [Development Guide](CLAUDE.md) - Architecture details and development patterns 234 + 235 + ## Railway Deployment 236 + 237 + QuickDID includes Railway deployment resources in the `railway-resources/` directory for easy deployment with metrics support via Telegraf. See the deployment configurations for one-click deployment options. 205 238 206 239 ## License 207 240