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
7.1 KiB
7.1 KiB
Redis vs PostgreSQL: Когда что использовать?
Скорость доступа
Redis:
- ⚡ 0.1-1 мс (данные в памяти)
- Мгновенный доступ
- Идеально для частых чтений
PostgreSQL:
- 🐢 1-10 мс (с индексами)
- Зависит от нагрузки и индексов
- Но всё равно очень быстро
Когда Redis имеет смысл
✅ Используй Redis, если:
-
Очень частые чтения (каждый запрос, каждый клик)
- Например: счетчики, rate limiting, сессии
-
Временные данные (TTL, автоочистка)
- Например: SMS коды, временные токены
-
Кеширование результатов запросов
- Например: результаты AI классификации, шаблоны визардов
-
Pub/Sub события (реал-тайм)
- Например:
ocr_events:{claim_id}для SSE
- Например:
Когда PostgreSQL достаточно
✅ Используй только PostgreSQL, если:
-
Данные читаются не так часто
- Загрузка страницы, переход между шагами
- Пользователь не заметит разницу 1-10 мс
-
Важна консистентность
- Нужна гарантия актуальности данных
- Нет риска рассинхронизации
-
Данные уже в PostgreSQL
- Не нужно дублировать
- Проще архитектура
Для веб-формы: Анализ использования
Когда читаются данные заявки:
-
При загрузке страницы (1 раз)
- Пользователь открывает форму
- Можно загрузить из PostgreSQL (10 мс) - не критично
-
При переходах между шагами (редко)
- Пользователь нажимает "Далее"
- Можно загрузить из PostgreSQL (10 мс) - не критично
-
При обновлении данных (редко)
- Пользователь заполняет форму
- Сохраняется в 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
Почему:
- ⚡ PostgreSQL с индексами быстро (1-10 мс) - пользователь не заметит
- ✅ Всегда актуальные данные (нет рассинхронизации)
- ✅ Проще архитектура (один источник истины)
- ✅ Данные читаются не так часто (не каждый запрос)
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
);
}
Но это опционально и не обязательно для веб-формы.