diff --git a/COMMIT_MSG_SESSION_DUPLICATE_EXTERNAL_REDIS.txt b/COMMIT_MSG_SESSION_DUPLICATE_EXTERNAL_REDIS.txt new file mode 100644 index 0000000..6cceb7f --- /dev/null +++ b/COMMIT_MSG_SESSION_DUPLICATE_EXTERNAL_REDIS.txt @@ -0,0 +1,8 @@ +Session: дублировать сессии во внешний Redis для доступа из n8n + +- backend/app/api/session.py: при записи сессии в локальный Redis (6383) теперь также дублируем те же ключи + в внешний Redis (REDIS_HOST/REDIS_PORT) через redis_service.client. +- Дублируются оба вида ключей: + - session:{channel}:{channel_user_id} + - session:{session_token} +- Ошибки внешнего Redis не ломают авторизацию: при недоступности — warning в логах. diff --git a/backend/app/api/session.py b/backend/app/api/session.py index 179aafa..6f1acf0 100644 --- a/backend/app/api/session.py +++ b/backend/app/api/session.py @@ -16,6 +16,8 @@ from fastapi import APIRouter, HTTPException from pydantic import BaseModel import redis.asyncio as redis +from ..services.redis_service import redis_service + logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/v1/session", tags=["session"]) @@ -59,10 +61,20 @@ async def set_session_by_channel_user( "verified_at": datetime.utcnow().isoformat(), } ttl = SESSION_BY_CHANNEL_TTL_HOURS * 3600 if SESSION_BY_CHANNEL_TTL_HOURS else None + body = json.dumps(payload) if ttl: - await redis_client.setex(key, ttl, json.dumps(payload)) + await redis_client.setex(key, ttl, body) else: - await redis_client.set(key, json.dumps(payload)) + await redis_client.set(key, body) + # Дублируем сессию в внешний Redis, чтобы n8n мог читать по тем же ключам + try: + if redis_service.client: + if ttl: + await redis_service.client.setex(key, ttl, body) + else: + await redis_service.client.set(key, body) + except Exception as e: + logger.warning("Не удалось продублировать сессию в внешний Redis (channel): %s", e) logger.info("Сессия записана: %s, unified_id=%s", key, payload.get("unified_id")) @@ -94,10 +106,20 @@ async def set_session_by_token(session_token: str, data: Dict[str, Any]) -> None "verified_at": datetime.utcnow().isoformat(), } ttl = SESSION_BY_CHANNEL_TTL_HOURS * 3600 if SESSION_BY_CHANNEL_TTL_HOURS else None + body = json.dumps(payload) if ttl: - await redis_client.setex(key, ttl, json.dumps(payload)) + await redis_client.setex(key, ttl, body) else: - await redis_client.set(key, json.dumps(payload)) + await redis_client.set(key, body) + # Дублируем сессию по токену в внешний Redis для доступа из n8n + try: + if redis_service.client: + if ttl: + await redis_service.client.setex(key, ttl, body) + else: + await redis_service.client.set(key, body) + except Exception as e: + logger.warning("Не удалось продублировать сессию в внешний Redis (token): %s", e) class SessionVerifyRequest(BaseModel):