- Add docker-compose.ha.yml for PostgreSQL/Redis HA setup with Patroni and Sentinel - Add docker-compose.prod.yml for production deployment - Add GitHub Actions CI/CD workflow (build.yml) - Add install.cmd for Windows one-click setup - Harden Redis connection with retry logic and health checks - Add Celery HA config with Redis Sentinel support - Add HA operations runbook - Update README with deployment and architecture docs - Move landing page spec to .claude/specs/design/ - Update memory intelligence PRD
47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
"""Redis client module."""
|
|
|
|
from redis.asyncio import Redis, from_url
|
|
from redis.asyncio.sentinel import Sentinel
|
|
|
|
from app.core.config import settings
|
|
from app.core.logging import get_logger
|
|
|
|
_redis_pool: Redis | None = None
|
|
_sentinel_pool: Sentinel | None = None
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
async def get_redis() -> Redis:
|
|
"""Get global Redis client instance."""
|
|
global _redis_pool, _sentinel_pool
|
|
if _redis_pool is None:
|
|
if settings.redis_sentinel_enabled:
|
|
_sentinel_pool = Sentinel(
|
|
settings.redis_sentinel_hosts,
|
|
socket_timeout=settings.redis_sentinel_socket_timeout,
|
|
password=settings.redis_sentinel_password or None,
|
|
decode_responses=True,
|
|
)
|
|
_redis_pool = _sentinel_pool.master_for(
|
|
settings.redis_sentinel_master_name,
|
|
db=settings.redis_sentinel_db,
|
|
decode_responses=True,
|
|
)
|
|
logger.info(
|
|
"redis_connected_via_sentinel",
|
|
master_name=settings.redis_sentinel_master_name,
|
|
sentinel_nodes=settings.redis_sentinel_nodes,
|
|
)
|
|
else:
|
|
_redis_pool = from_url(settings.redis_url, encoding="utf-8", decode_responses=True)
|
|
return _redis_pool
|
|
|
|
|
|
async def close_redis():
|
|
"""Close Redis connection."""
|
|
global _redis_pool, _sentinel_pool
|
|
if _redis_pool:
|
|
await _redis_pool.close()
|
|
_redis_pool = None
|
|
_sentinel_pool = None
|