Files
aiform_prod/docs/REDIS_VS_POSTGRESQL_SPEED.md
AI Assistant 0978e485dc feat: Add claim plan confirmation flow via Redis SSE
Problem:
- After wizard form submission, need to wait for claim data from n8n
- Claim data comes via Redis channel claim:plan:{session_token}
- Need to display confirmation form with claim data

Solution:
1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token}
   - Subscribes to Redis channel claim:plan:{session_token}
   - Streams claim data from n8n to frontend
   - Handles timeouts and errors gracefully

2. Frontend: Added subscription to claim:plan channel
   - StepWizardPlan: After form submission, subscribes to SSE
   - Waits for claim_plan_ready event
   - Shows loading message while waiting
   - On success: saves claimPlanData and shows confirmation step

3. New component: StepClaimConfirmation
   - Displays claim confirmation form in iframe
   - Receives claimPlanData from parent
   - Generates HTML form (placeholder - should call n8n for real HTML)
   - Handles confirmation/cancellation via postMessage

4. ClaimForm: Added conditional step for confirmation
   - Shows StepClaimConfirmation when showClaimConfirmation=true
   - Step appears after StepWizardPlan
   - Only visible when claimPlanData is available

Flow:
1. User fills wizard form → submits
2. Form data sent to n8n via /api/v1/claims/wizard
3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token}
4. n8n processes data → publishes to Redis claim:plan:{session_token}
5. Backend receives → streams to frontend via SSE
6. Frontend receives → shows StepClaimConfirmation
7. User confirms → proceeds to next step

Files:
- backend/app/api/events.py: Added stream_claim_plan endpoint
- frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan
- frontend/src/components/form/StepClaimConfirmation.tsx: New component
- frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00

7.1 KiB
Raw Permalink Blame History

Redis vs PostgreSQL: Когда что использовать?

Скорость доступа

Redis:

  • 0.1-1 мс (данные в памяти)
  • Мгновенный доступ
  • Идеально для частых чтений

PostgreSQL:

  • 🐢 1-10 мс (с индексами)
  • Зависит от нагрузки и индексов
  • Но всё равно очень быстро

Когда Redis имеет смысл

Используй Redis, если:

  1. Очень частые чтения (каждый запрос, каждый клик)

    • Например: счетчики, rate limiting, сессии
  2. Временные данные (TTL, автоочистка)

    • Например: SMS коды, временные токены
  3. Кеширование результатов запросов

    • Например: результаты AI классификации, шаблоны визардов
  4. Pub/Sub события (реал-тайм)

    • Например: ocr_events:{claim_id} для SSE

Когда PostgreSQL достаточно

Используй только PostgreSQL, если:

  1. Данные читаются не так часто

    • Загрузка страницы, переход между шагами
    • Пользователь не заметит разницу 1-10 мс
  2. Важна консистентность

    • Нужна гарантия актуальности данных
    • Нет риска рассинхронизации
  3. Данные уже в PostgreSQL

    • Не нужно дублировать
    • Проще архитектура

Для веб-формы: Анализ использования

Когда читаются данные заявки:

  1. При загрузке страницы (1 раз)

    • Пользователь открывает форму
    • Можно загрузить из PostgreSQL (10 мс) - не критично
  2. При переходах между шагами (редко)

    • Пользователь нажимает "Далее"
    • Можно загрузить из PostgreSQL (10 мс) - не критично
  3. При обновлении данных (редко)

    • Пользователь заполняет форму
    • Сохраняется в PostgreSQL

Вывод:

  • НЕ критично по скорости - пользователь не заметит разницу
  • Важнее консистентность - данные всегда актуальные
  • Проще архитектура - один источник истины

Компромиссное решение

Вариант: Кеширование в Redis с инвалидацией

# При чтении данных заявки
async def get_claim(claim_id: str):
    # 1. Пробуем Redis (быстро)
    cached = await redis.get(f"claim:{claim_id}")
    if cached:
        return json.loads(cached)
    
    # 2. Если нет в кеше - из PostgreSQL
    claim = await db.get_claim(claim_id)
    
    # 3. Сохраняем в кеш на 1 час
    await redis.set(f"claim:{claim_id}", json.dumps(claim), ttl=3600)
    
    return claim

# При обновлении данных
async def update_claim(claim_id: str, data: dict):
    # 1. Обновляем PostgreSQL
    await db.update_claim(claim_id, data)
    
    # 2. Инвалидируем кеш (удаляем из Redis)
    await redis.delete(f"claim:{claim_id}")
    
    # Или обновляем кеш сразу
    await redis.set(f"claim:{claim_id}", json.dumps(data), ttl=3600)

Плюсы:

  • Быстрый доступ (если есть в кеше)
  • Актуальные данные (инвалидация при обновлении)
  • Fallback на PostgreSQL (если кеш пуст)

Минусы:

  • Дополнительная сложность
  • Нужно инвалидировать кеш при каждом обновлении
  • Риск устаревших данных (если забыли инвалидировать)

Рекомендация для веб-формы

Вариант 1: Только PostgreSQL (рекомендую)

Когда использовать:

  • Данные читаются не так часто (загрузка страницы, переходы)
  • Важна консистентность
  • Простота архитектуры важнее скорости

Плюсы:

  • Просто (один источник данных)
  • Всегда актуальные данные
  • Нет рассинхронизации
  • PostgreSQL с индексами всё равно быстро (1-10 мс)

Минусы:

  • Чуть медленнее, чем Redis (но не критично)

Вариант 2: PostgreSQL + Redis кеш (если нужна скорость)

Когда использовать:

  • Очень частые чтения (каждый запрос)
  • Критична скорость (но для веб-формы это не так)

Плюсы:

  • Быстрый доступ (0.1-1 мс)
  • Меньше нагрузки на PostgreSQL

Минусы:

  • Сложнее (нужна инвалидация кеша)
  • Риск устаревших данных
  • Больше кода для поддержки

Итог

Для веб-формы:

Рекомендую: Только PostgreSQL

Почему:

  1. PostgreSQL с индексами быстро (1-10 мс) - пользователь не заметит
  2. Всегда актуальные данные (нет рассинхронизации)
  3. Проще архитектура (один источник истины)
  4. Данные читаются не так часто (не каждый запрос)

Redis используй только для:

  • Pub/Sub (ocr_events:{claim_id}) - события в реальном времени
  • Кеширование AI ответов (классификация, визарды) - если нужно
  • SMS коды, временные токены - с TTL

НЕ используй Redis для:

  • Основных данных заявки (есть в PostgreSQL)
  • Документов (есть в PostgreSQL)
  • Ответов визарда (есть в PostgreSQL)

Если всё-таки нужен Redis кеш

Можно добавить опциональное кеширование:

# В n8n workflow после claimsave
if (channel === 'web_form' && enable_cache === true) {
  // Опционально: кешируем в Redis на 1 час
  await redis.set(
    `claim:${claim_id}`,
    JSON.stringify(claim_data),
    ttl=3600
  );
}

Но это опционально и не обязательно для веб-формы.