# Исправление проблемы с отправкой сообщений ## Проблема Когда пользователь отправлял сообщение, оно не появлялось в чате ни у отправителя, ни у получателя до перезагрузки страницы. ## Корневые причины ### 1. **Backend - Порядок операций** В файле [backend/app/chats/service.py](backend/app/chats/service.py): - Сообщения отправлялись через WebSocket **ДО** коммита в БД - Это могло привести к отправке неполных или незапомненных данных **Исправление:** Перемещены вызовы `await session.commit()` **перед** `await cls._send_ws_message()` во всех трех методах: - `send_message()` - отправка нового сообщения - `update_message()` - редактирование сообщения - `delete_message()` - удаление сообщения ### 2. **Frontend - Отсутствие оптимистичного обновления** В файле [frontend/src/pages/ChatPage.tsx](frontend/src/pages/ChatPage.tsx): - Приложение ждало получения сообщения через WebSocket перед показом в UI - Без WebSocket подписки или задержки сообщение не отображалось **Исправление:** Добавлено оптимистичное обновление UI: - Сообщение добавляется в UI **сразу** после отправки с временным ID (`temp-{timestamp}`) - При получении подтверждения через WebSocket, временное сообщение заменяется на реальное - Если отправка завершится с ошибкой, временное сообщение удаляется ### 3. **Backend - Логирование и обработка ошибок** В файле [backend/app/services/messenger_service.py](backend/app/services/messenger_service.py): - Добавлена обработка исключений при отправке WebSocket сообщений - Улучшено логирование (удален `print("test")`, заменен на `log.info()`) ## Что изменилось ### Backend (3 файла) 1. **service.py** - 3 исправления: - `send_message()`: commit перед WebSocket отправкой - `update_message()`: commit перед WebSocket отправкой - `delete_message()`: commit перед WebSocket отправкой 2. **messenger_service.py** - 2 исправления: - Добавлен try-catch в `handle_message()` - Заменено логирование с `print()` на `log.info()` ### Frontend (1 файл) 1. **ChatPage.tsx** - 2 исправления: - `handleSendMessage()`: добавлено оптимистичное обновление UI - `ws.onmessage()`: улучшена логика замены временных сообщений на реальные ## Поток отправки сообщения (новый) ``` 1. Пользователь нажимает "Отправить" ↓ 2. Frontend создает временное сообщение (temp-ID) и добавляет в UI ↓ 3. Frontend отправляет запрос к backend (/chats/message) ↓ 4. Backend сохраняет сообщение в БД ↓ 5. Backend коммитит транзакцию в БД ↓ 6. Backend отправляет сообщение в Redis (pub/sub) ↓ 7. Redis PubSub listener отправляет WebSocket всем участникам чата ↓ 8. Frontend получает сообщение через WebSocket и заменяет temp-сообщение на реальное ↓ 9. UI обновлена и синхронизирована со всеми участниками ``` ## Тестирование 1. **Базовое тестирование:** - Откройте приложение в 2 браузерах для разных пользователей - Отправьте сообщение из первого браузера - Сообщение должно появиться **сразу** в обоих браузерах - НЕ требуется перезагрузка страницы 2. **Проверка временных сообщений:** - В DevTools откройте Console - Ищите сообщение вида `temp-TIMESTAMP` в начальном списке - После получения WebSocket ответа, ID должно измениться на UUID 3. **Проверка обновлений:** - Отредактируйте сообщение - Изменение должно появиться сразу у обоих пользователей 4. **Проверка удаления:** - Удалите сообщение - Оно должно исчезнуть сразу у обоих пользователей ## Возможные проблемы и решения ### Проблема: Сообщения все еще не появляются **Решение:** Проверьте: 1. Redis работает (`docker ps | grep redis`) 2. Backend логирует: "Starting Redis PubSub subscriber" 3. WebSocket подключение открыто (`ws.onopen` в Console) 4. Сообщение отправляется: смотрите сетевые запросы в DevTools ### Проблема: Дублирование сообщений **Решение:** Может быть, если: 1. Сообщение приходит через WebSocket и добавляется дважды 2. Проверьте логику замены temp-сообщений в `onmessage` ### Проблема: Сообщение показывается с ошибкой **Решение:** 1. Проверьте формат данных в backend (логи Redis) 2. Убедитесь, что Message тип совпадает со схемой