131 lines
5.1 KiB
Markdown
131 lines
5.1 KiB
Markdown
|
|
# AI Drawer: Redis Pub/Sub вместо Polling
|
|||
|
|
|
|||
|
|
## ✅ Что сделано
|
|||
|
|
|
|||
|
|
### Проблема
|
|||
|
|
Раньше использовался polling - браузер каждые 2 секунды спрашивал сервер "готово ли?". Это создавало:
|
|||
|
|
- Лишние запросы к серверу
|
|||
|
|
- Задержку до 2 секунд перед получением ответа
|
|||
|
|
- Нагрузку на БД
|
|||
|
|
- Дублирование истории (БД + n8n)
|
|||
|
|
|
|||
|
|
### Решение
|
|||
|
|
Теперь используется **Redis Pub/Sub + SSE (Server-Sent Events)** с прямой публикацией из n8n:
|
|||
|
|
- ✅ Мгновенная доставка ответов (без задержек)
|
|||
|
|
- ✅ Нет лишних запросов (одно SSE соединение)
|
|||
|
|
- ✅ Меньше нагрузка на сервер
|
|||
|
|
- ✅ Нет дублирования - история только в n8n
|
|||
|
|
- ✅ Упрощенная архитектура - без БД и callback
|
|||
|
|
- ✅ Fallback на polling если SSE не работает
|
|||
|
|
|
|||
|
|
## 📋 Архитектура
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. AI Drawer → n8n_proxy.php → возвращает task_id
|
|||
|
|
2. n8n обрабатывает → публикует ответ НАПРЯМУЮ в Redis
|
|||
|
|
3. Redis PUBLISH → канал "ai:response:{task_id}"
|
|||
|
|
4. ai_sse.php → подписан на Redis → отправляет через SSE в браузер
|
|||
|
|
5. Браузер → EventSource → получает ответ мгновенно! ⚡
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**История диалога:** Сохраняется в n8n автоматически (не дублируется в БД)
|
|||
|
|
|
|||
|
|
## 📁 Измененные файлы
|
|||
|
|
|
|||
|
|
### 1. `/aiassist/ai_sse.php` (новый)
|
|||
|
|
SSE endpoint для подписки на Redis события
|
|||
|
|
|
|||
|
|
### 2. `/aiassist/n8n_proxy.php` (упрощен)
|
|||
|
|
- ❌ Убрано сохранение в БД
|
|||
|
|
- ❌ Убран callback URL
|
|||
|
|
- ✅ Добавлены параметры Redis для n8n
|
|||
|
|
|
|||
|
|
### 3. `/callback_ai_response.php` (больше не используется)
|
|||
|
|
Можно удалить - n8n публикует напрямую в Redis
|
|||
|
|
|
|||
|
|
### 4. `/layouts/v7/resources/js/ai-drawer-simple.js` (обновлен)
|
|||
|
|
- Заменен `startPolling()` на `startSSEListener()`
|
|||
|
|
- Добавлен fallback на polling если SSE не работает
|
|||
|
|
- Добавлено поле `currentEventSource` для управления SSE соединением
|
|||
|
|
|
|||
|
|
## 🔧 Как работает
|
|||
|
|
|
|||
|
|
### Отправка запроса:
|
|||
|
|
```javascript
|
|||
|
|
// Пользователь отправляет сообщение
|
|||
|
|
sendToN8N(message) → получает task_id → startSSEListener(task_id)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Получение ответа:
|
|||
|
|
```javascript
|
|||
|
|
// SSE соединение открывается один раз
|
|||
|
|
EventSource('/aiassist/ai_sse.php?task_id=123')
|
|||
|
|
|
|||
|
|
// n8n обрабатывает и публикует НАПРЯМУЮ в Redis:
|
|||
|
|
Redis PUBLISH "ai:response:123" {
|
|||
|
|
task_id: "123",
|
|||
|
|
response: "...",
|
|||
|
|
status: "completed"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// SSE endpoint получает событие и отправляет в браузер
|
|||
|
|
// Браузер получает ответ мгновенно!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Настройка n8n:
|
|||
|
|
См. подробную инструкцию: `N8N_REDIS_SETUP.md`
|
|||
|
|
|
|||
|
|
## 🛡️ Fallback механизм
|
|||
|
|
|
|||
|
|
Если SSE не работает (старые браузеры, проблемы с сетью):
|
|||
|
|
1. Через 5 секунд автоматически переключается на polling
|
|||
|
|
2. Использует старый метод `startPollingFallback()`
|
|||
|
|
3. Проверяет БД каждые 2 секунды
|
|||
|
|
|
|||
|
|
## ⚙️ Настройки Redis
|
|||
|
|
|
|||
|
|
- **Host**: `crm.clientright.ru`
|
|||
|
|
- **Port**: `6379`
|
|||
|
|
- **Password**: `CRM_Redis_Pass_2025_Secure!`
|
|||
|
|
- **Канал**: `ai:response:{task_id}`
|
|||
|
|
|
|||
|
|
## 🧪 Тестирование
|
|||
|
|
|
|||
|
|
1. Откройте AI Drawer в CRM
|
|||
|
|
2. Отправьте сообщение
|
|||
|
|
3. Проверьте консоль браузера:
|
|||
|
|
- `AI Drawer: SSE connection opened`
|
|||
|
|
- `AI Drawer: Received response via SSE`
|
|||
|
|
4. Ответ должен прийти мгновенно после обработки n8n
|
|||
|
|
|
|||
|
|
## 📊 Преимущества
|
|||
|
|
|
|||
|
|
| Параметр | Polling (старое) | Redis Pub/Sub (новое) |
|
|||
|
|
|----------|------------------|----------------------|
|
|||
|
|
| Скорость | До 2 сек задержки | Мгновенно ⚡ |
|
|||
|
|
| Запросы | Каждые 2 сек | Одно соединение |
|
|||
|
|
| Нагрузка | Высокая | Низкая |
|
|||
|
|
| Надежность | ✅ | ✅ + fallback |
|
|||
|
|
|
|||
|
|
## 🔍 Отладка
|
|||
|
|
|
|||
|
|
### Проверить Redis публикацию:
|
|||
|
|
```bash
|
|||
|
|
redis-cli -h crm.clientright.ru -a 'CRM_Redis_Pass_2025_Secure!' \
|
|||
|
|
PUBLISH "ai:response:test-task" '{"task_id":"test-task","response":"test"}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Проверить SSE endpoint:
|
|||
|
|
```bash
|
|||
|
|
curl -N "https://crm.clientright.ru/aiassist/ai_sse.php?task_id=test-task"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Логи:
|
|||
|
|
- PHP error_log: `/var/log/php/error.log`
|
|||
|
|
- Ищите: `[AI SSE]` и `[Callback]`
|
|||
|
|
|
|||
|
|
## ✅ Результат
|
|||
|
|
|
|||
|
|
Теперь AI Drawer получает ответы **мгновенно** через Redis Pub/Sub вместо ожидания polling каждые 2 секунды!
|
|||
|
|
|