docs: Добавлен лог сессии от 28.10.2025 - исправление SSE error handling
This commit is contained in:
356
SESSION_LOG_2025-10-28.md
Normal file
356
SESSION_LOG_2025-10-28.md
Normal file
@@ -0,0 +1,356 @@
|
||||
# 📋 Лог сессии: Исправление SSE error handling
|
||||
|
||||
**Дата:** 28 октября 2025 (00:00 - 01:00 MSK)
|
||||
**Задача:** Исправление ошибки "Ошибка подключения к серверу" при успешном распознавании полиса
|
||||
**Статус:** ✅ Успешно завершено
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Проблема
|
||||
|
||||
После успешного распознавания полиса через OCR/Vision, пользователь видел модальное окно с ошибкой:
|
||||
```
|
||||
❌ Ошибка распознавания
|
||||
Ошибка подключения к серверу
|
||||
|
||||
Полный ответ: null
|
||||
```
|
||||
|
||||
Хотя в логах backend видно, что:
|
||||
- ✅ SSE подключение установлено
|
||||
- ✅ Событие OCR получено из Redis
|
||||
- ✅ Данные отправлены клиенту
|
||||
- ✅ SSE соединение закрыто корректно
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Диагностика
|
||||
|
||||
### Backend логи показывали успешную работу:
|
||||
|
||||
```
|
||||
2025-10-28 00:41:15,187 - 🚀 SSE connection requested for task_id: CLM-2025-10-27-Y1KWA1
|
||||
2025-10-28 00:41:15,202 - 📡 Client subscribed to ocr_events:CLM-2025-10-27-Y1KWA1
|
||||
2025-10-28 00:41:15,203 - ⏳ Waiting for message on ocr_events:CLM-2025-10-27-Y1KWA1...
|
||||
2025-10-28 00:41:49,729 - 📥 Received message type: message
|
||||
2025-10-28 00:41:49,729 - 📦 Raw event data: {"claim_id":"CLM-2025-10-27-Y1KWA1","event":{"event_type":"ocr_completed","status":"completed","message":"OCR обработка завершена","data":{"output":{"is_policy":"yes","policy_number":"E1000-302545808"...
|
||||
2025-10-28 00:41:49,730 - 📦 Unwrapped n8n Redis format for CLM-2025-10-27-Y1KWA1
|
||||
2025-10-28 00:41:49,730 - 📤 Sending event to client: completed
|
||||
2025-10-28 00:41:49,730 - ✅ Task CLM-2025-10-27-Y1KWA1 finished, closing SSE
|
||||
```
|
||||
|
||||
**Вывод:** Backend работал корректно!
|
||||
|
||||
### Причина ошибки:
|
||||
|
||||
1. Backend отправляет событие OCR клиенту
|
||||
2. Backend **закрывает SSE соединение** (это нормально)
|
||||
3. Браузер получает событие закрытия SSE
|
||||
4. Браузер триггерит `eventSource.onerror`
|
||||
5. Frontend в `onerror` **перезаписывает успешный результат** ошибкой:
|
||||
|
||||
```typescript
|
||||
// ❌ СТАРЫЙ КОД (неправильный)
|
||||
eventSource.onerror = (error) => {
|
||||
console.error('❌ SSE connection error:', error);
|
||||
setOcrModalContent({
|
||||
success: false,
|
||||
data: null,
|
||||
message: 'Ошибка подключения к серверу'
|
||||
});
|
||||
setWaitingForOcr(false);
|
||||
eventSource.close();
|
||||
};
|
||||
```
|
||||
|
||||
**Проблема:** `onerror` вызывается **после** получения результата, когда backend закрывает SSE, и затирает успешный результат.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Решение
|
||||
|
||||
Добавил проверку в `eventSource.onerror` — если уже получили результат OCR, не затираем его сообщением об ошибке:
|
||||
|
||||
```typescript
|
||||
// ✅ НОВЫЙ КОД (правильный)
|
||||
eventSource.onerror = (error) => {
|
||||
console.error('❌ SSE connection error:', error);
|
||||
console.error('SSE readyState:', eventSource.readyState);
|
||||
|
||||
// Не показываем ошибку если уже получили результат (backend закрыл SSE после успешной отправки)
|
||||
setOcrModalContent((prev) => {
|
||||
if (prev && prev !== 'loading') {
|
||||
console.log('✅ SSE закрыто после получения результата, не показываем ошибку');
|
||||
return prev; // Оставляем текущий результат
|
||||
}
|
||||
return { success: false, data: null, message: 'Ошибка подключения к серверу' };
|
||||
});
|
||||
|
||||
setWaitingForOcr(false);
|
||||
eventSource.close();
|
||||
};
|
||||
```
|
||||
|
||||
**Логика:**
|
||||
- Если `prev !== 'loading'` → значит уже получили результат → **не затираем** его
|
||||
- Если `prev === 'loading'` → реальная ошибка подключения → показываем ошибку
|
||||
|
||||
---
|
||||
|
||||
## 📝 Изменённые файлы
|
||||
|
||||
### `/frontend/src/components/form/Step1Policy.tsx`
|
||||
|
||||
**Изменение:** Обработка `eventSource.onerror` с проверкой наличия результата
|
||||
|
||||
**Строки:** 147-162
|
||||
|
||||
**Было:**
|
||||
```typescript
|
||||
eventSource.onerror = (error) => {
|
||||
console.error('❌ SSE connection error:', error);
|
||||
setOcrModalContent({ success: false, data: null, message: 'Ошибка подключения к серверу' });
|
||||
setWaitingForOcr(false);
|
||||
eventSource.close();
|
||||
};
|
||||
```
|
||||
|
||||
**Стало:**
|
||||
```typescript
|
||||
eventSource.onerror = (error) => {
|
||||
console.error('❌ SSE connection error:', error);
|
||||
console.error('SSE readyState:', eventSource.readyState);
|
||||
|
||||
setOcrModalContent((prev) => {
|
||||
if (prev && prev !== 'loading') {
|
||||
console.log('✅ SSE закрыто после получения результата, не показываем ошибку');
|
||||
return prev;
|
||||
}
|
||||
return { success: false, data: null, message: 'Ошибка подключения к серверу' };
|
||||
});
|
||||
|
||||
setWaitingForOcr(false);
|
||||
eventSource.close();
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Проблемы в процессе исправления
|
||||
|
||||
### Проблема 1: Backend завис после kill -HUP
|
||||
|
||||
**Симптом:**
|
||||
```bash
|
||||
ERROR: [Errno 98] Address already in use
|
||||
```
|
||||
|
||||
**Причина:** `kill -HUP` не перезапустил uvicorn корректно, порт 8100 остался занят зависшим процессом.
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
# Убили все процессы на порту 8100
|
||||
sudo lsof -ti :8100 | xargs -r kill -9
|
||||
|
||||
# Перезапустили backend
|
||||
cd /var/www/fastuser/data/www/crm.clientright.ru/erv_platform/backend
|
||||
source venv/bin/activate
|
||||
python -m uvicorn app.main:app --host 0.0.0.0 --port 8100 --reload > ../backend.log 2>&1 &
|
||||
```
|
||||
|
||||
### Проблема 2: Изменения не применились во frontend
|
||||
|
||||
**Симптом:** После `docker-compose restart frontend` старый код всё ещё работал.
|
||||
|
||||
**Причина:** Frontend работает в Docker без volume mount — код встроен в образ при сборке.
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
# Пересборка образа с новым кодом
|
||||
docker-compose build frontend
|
||||
|
||||
# Пересоздание контейнера
|
||||
docker-compose up -d frontend
|
||||
```
|
||||
|
||||
**Проверка применения изменений:**
|
||||
```bash
|
||||
docker exec erv_platform_frontend_1 grep -A8 "eventSource.onerror" /app/src/components/form/Step1Policy.tsx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Git Commit
|
||||
|
||||
**Commit:** `0b75e01`
|
||||
**Message:** "fix: Не затираем результат OCR при закрытии SSE соединения"
|
||||
|
||||
**Полное описание:**
|
||||
```
|
||||
Проблема: Backend закрывает SSE после отправки события, браузер триггерит onerror,
|
||||
фронтенд перезаписывал успешный результат сообщением 'Ошибка подключения к серверу'.
|
||||
|
||||
Решение: Проверяем в onerror что если уже получили результат (prev !== 'loading'),
|
||||
не затираем его ошибкой.
|
||||
```
|
||||
|
||||
**Push:** ✅ `origin/main`
|
||||
|
||||
---
|
||||
|
||||
## ✅ Результат
|
||||
|
||||
### Что работает:
|
||||
1. ✅ Backend запущен (PID 25931) на порту 8100
|
||||
2. ✅ Frontend пересобран и работает на http://147.45.146.17:5173
|
||||
3. ✅ SSE подключение устанавливается корректно
|
||||
4. ✅ События OCR получаются из Redis через backend
|
||||
5. ✅ Результат распознавания отображается в модальном окне
|
||||
6. ✅ **Ошибка "Ошибка подключения к серверу" больше не появляется**
|
||||
7. ✅ Git репозиторий синхронизирован
|
||||
|
||||
### Тестирование:
|
||||
|
||||
**Сценарий 1: Успешное распознавание полиса**
|
||||
- Загрузка файла полиса → ✅
|
||||
- SSE подключение → ✅
|
||||
- OCR/Vision обработка → ✅
|
||||
- Отображение результата → ✅ "Полис распознан: E1000-302545808"
|
||||
- **Нет ошибки** при закрытии SSE → ✅
|
||||
|
||||
**Сценарий 2: Загрузка неподходящего документа**
|
||||
- Загрузка не-полиса → ✅
|
||||
- SSE подключение → ✅
|
||||
- OCR/Vision обработка → ✅
|
||||
- Отображение: "Документ не является полисом ERV" → ✅
|
||||
|
||||
**Сценарий 3: Реальная ошибка подключения**
|
||||
- Если backend недоступен → ❌ "Ошибка подключения к серверу" (корректная ошибка)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Архитектура (финальная)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ USER BROWSER │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||
│ │ React Frontend (Vite Dev Server, port 3000) │ │
|
||||
│ │ - Step1Policy.tsx (SSE Client) │ │
|
||||
│ │ - Модалка с результатом OCR │ │
|
||||
│ │ - EventSource(`/events/${claimId}`) │ │
|
||||
│ │ - ✅ Защита от затирания результата в onerror │ │
|
||||
│ └────────────┬─────────────────────────────────────────────────┘ │
|
||||
│ │ Vite Proxy (/events → host:8100) │
|
||||
└───────────────┼─────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ BACKEND (FastAPI, port 8100) │
|
||||
│ PID: 25931 │
|
||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
||||
│ │ SSE Endpoint: GET /events/{task_id} │ │
|
||||
│ │ - Подписка на Redis: ocr_events:{task_id} │ │
|
||||
│ │ - Стриминг событий через SSE │ │
|
||||
│ │ - Закрытие SSE после отправки результата │ │
|
||||
│ └────────────┬─────────────────────────────────────────────────┘ │
|
||||
└───────────────┼──────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Redis Pub/Sub (crm.clientright.ru:6379) │
|
||||
│ │
|
||||
│ Channel: ocr_events:CLM-2025-10-27-XXXXX │
|
||||
│ Format: { │
|
||||
│ "claim_id": "CLM-...", │
|
||||
│ "event": { │
|
||||
│ "event_type": "ocr_completed", │
|
||||
│ "status": "completed", │
|
||||
│ "data": { "output": { "is_policy": "yes", ... } } │
|
||||
│ } │
|
||||
│ } │
|
||||
└────────────────▲────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ PUBLISH
|
||||
│
|
||||
┌────────────────┴────────────────────────────────────────────────────┐
|
||||
│ n8n Workflow (OCR Processing) │
|
||||
│ │
|
||||
│ 1. Webhook trigger (file upload) │
|
||||
│ 2. Upload to S3 │
|
||||
│ 3. OCR Service (147.45.146.17:8001) │
|
||||
│ 4. AI Vision (OpenRouter Gemini 2.0 Flash) │
|
||||
│ 5. Redis Publish Node → ocr_events:{claim_id} │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 Метрики
|
||||
|
||||
**Время выполнения сессии:** ~1 час
|
||||
**Количество коммитов:** 1
|
||||
**Изменённых файлов:** 1
|
||||
**Строк изменено:** +10 / -1
|
||||
**Перезапусков backend:** 2
|
||||
**Rebuild frontend:** 1
|
||||
|
||||
**Проблемы решены:**
|
||||
- ✅ Затирание результата OCR при закрытии SSE
|
||||
- ✅ Backend завис после kill -HUP
|
||||
- ✅ Изменения не применялись без rebuild
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Ссылки
|
||||
|
||||
- Frontend: http://147.45.146.17:5173
|
||||
- Backend API: http://localhost:8100
|
||||
- Backend Health: http://localhost:8100/health
|
||||
- Gitea: http://147.45.146.17:3002/negodiy/erv-platform
|
||||
- n8n: http://147.45.146.17:5678
|
||||
|
||||
---
|
||||
|
||||
## 📝 Важные заметки
|
||||
|
||||
### Backend запущен вне Docker:
|
||||
```bash
|
||||
# Процесс
|
||||
PID: 25931
|
||||
Command: python -m uvicorn app.main:app --host 0.0.0.0 --port 8100 --reload
|
||||
|
||||
# Логи
|
||||
tail -f /var/www/fastuser/data/www/crm.clientright.ru/erv_platform/backend.log
|
||||
|
||||
# Перезапуск
|
||||
cd /var/www/fastuser/data/www/crm.clientright.ru/erv_platform/backend
|
||||
source venv/bin/activate
|
||||
python -m uvicorn app.main:app --host 0.0.0.0 --port 8100 --reload > ../backend.log 2>&1 &
|
||||
```
|
||||
|
||||
### Frontend требует rebuild при изменениях:
|
||||
```bash
|
||||
# Применение изменений
|
||||
docker-compose build frontend
|
||||
docker-compose up -d frontend
|
||||
|
||||
# Проверка кода в контейнере
|
||||
docker exec erv_platform_frontend_1 cat /app/src/components/form/Step1Policy.tsx
|
||||
```
|
||||
|
||||
### Redis credentials:
|
||||
```
|
||||
Host: crm.clientright.ru
|
||||
Port: 6379
|
||||
Password: cKSq8M11ZQIRi59OuUXb
|
||||
Channels: ocr_events:{claim_id}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Статус:** ✅ Успешно завершено
|
||||
**Автор:** AI Assistant (Claude Sonnet 4.5)
|
||||
**Дата:** 28 октября 2025, 01:00 MSK
|
||||
|
||||
Reference in New Issue
Block a user