feat: add optional Redis caching layer for API endpoints

Add Redis-backed response caching for read-heavy API endpoints (nodes,
advertisements, messages, channels, dashboard, profiles) with configurable
TTL, key prefix isolation, and graceful fallback when Redis is unavailable.

New files:
- common/redis.py: CacheBackend, NullCache, RedisCacheBackend
- api/cache.py: @cached decorator, sorted_query_string helper
- tests/test_api/test_cache.py: 23 unit tests

Changes:
- pyproject.toml: add redis[hiredis] dependency
- common/config.py: 8 Redis settings on APISettings
- api/cli.py: Redis Click options + startup banner
- api/app.py: Redis lifespan init/cleanup, X-Cache middleware, health check
- 6 route files: apply @cached decorator to list endpoints
- docker-compose.yml: Redis service (cache profile), env vars
- docker-compose.dev.yml: Redis port exposure
- .env.example, README.md, AGENTS.md, docs/upgrading.md: documentation

Redis is disabled by default (REDIS_ENABLED=false). Enable with
--profile cache and REDIS_ENABLED=true.
This commit is contained in:
Louis King
2026-06-09 23:08:49 +01:00
parent a4419a8987
commit 385d1ab141
21 changed files with 1574 additions and 84 deletions
+11
View File
@@ -55,6 +55,7 @@ MeshCore Hub is a Python 3.14+ monorepo for managing and orchestrating MeshCore
| Database ORM | SQLAlchemy 2.0 (async) |
| Migrations | Alembic |
| REST API | FastAPI |
| Redis Client | redis[hiredis] (optional) |
| MQTT Client | paho-mqtt |
| MQTT Broker | [meshcore-mqtt-broker](https://github.com/michaelhart/meshcore-mqtt-broker) (WebSocket + JWT auth) |
| Templates | Jinja2 (server), lit-html (SPA) |
@@ -262,6 +263,7 @@ meshcore-hub/
│ │ ├── i18n.py # Translation loading
│ │ ├── health.py # Health check utilities
│ │ ├── hash_utils.py # Hash utility functions
│ │ ├── redis.py # Redis cache backend
│ │ ├── models/ # SQLAlchemy models
│ │ │ ├── node.py # Node model
│ │ │ ├── channel.py # Channel model (encryption keys)
@@ -287,6 +289,7 @@ meshcore-hub/
│ │ ├── auth.py # Authentication
│ │ ├── dependencies.py
│ │ ├── metrics.py # Prometheus metrics endpoint
│ │ ├── cache.py # API response caching (Redis)
│ │ └── routes/ # API routes
│ │ ├── user_profiles.py # User profile endpoints (GET/PUT profile)
│ │ ├── adoptions.py # Node adoption endpoints (POST adopt, DELETE release)
@@ -645,6 +648,14 @@ Key variables:
- `CORS_ORIGINS` - Comma-separated list of allowed CORS origins for the API (optional)
- `METRICS_ENABLED` - Enable Prometheus metrics endpoint at /metrics (default: `true`)
- `METRICS_CACHE_TTL` - Seconds to cache metrics output (default: `60`)
- `REDIS_ENABLED` - Enable Redis API response caching (default: `false`)
- `REDIS_HOST` - Redis server host (default: `localhost`)
- `REDIS_PORT` - Redis server port (default: `6379`)
- `REDIS_DB` - Redis database number (default: `0`)
- `REDIS_PASSWORD` - Redis password (optional)
- `REDIS_KEY_PREFIX` - Cache key prefix for multi-instance isolation (default: `hub`)
- `REDIS_CACHE_TTL` - Default cache TTL in seconds (default: `30`)
- `REDIS_CACHE_TTL_DASHBOARD` - Cache TTL for dashboard endpoints in seconds (default: `30`)
- `WEB_HOST` - Web server bind address (default: `0.0.0.0`)
- `WEB_PORT` - Web server port (default: `8080`)
- `API_BASE_URL` - API server base URL for the web dashboard (default: `http://localhost:8000`)