-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Labels
documentationImprovements or additions to documentationImprovements or additions to documentation
Description
Контекст
Анализ текущих связей между подсистемами AI Secretary System. Цель — зафиксировать как подсистемы взаимодействуют, где проблемы, и как должно быть правильно.
1. Карта подсистем
┌─────────────────────────────────────────────┐
│ orchestrator.py (~4100 строк) │
│ God Object: startup, DI, ~100 legacy API, │
│ widget endpoints, background tasks │
├──────────────┬───────────────┬──────────────┤
│ │ │ │
┌─────┴─────┐ ┌────┴────┐ ┌──────┴──────┐ ┌───┴───┐
│ 26 Routers │ │ Service │ │ DB Layer │ │ Caches│
│ app/ │ │ Layer │ │ db/ │ │ │
│ routers/ │ │ (split) │ │ │ │ │
└─────┬──────┘ └────┬────┘ └──────┬──────┘ └───┬───┘
│ │ │ │
┌───────────┼──────────────┼───────────────┤ │
│ │ │ │ │
┌────┴───┐ ┌────┴───┐ ┌─────┴──────┐ ┌────┴─────┐ ┌────┴────┐
│TG Bot │ │WA Bot │ │Root svc: │ │db/integr.│ │In-memory│
│subproc │ │subproc │ │cloud_llm, │ │30+ mgr │ │5 кешей │
│(HTTP→ │ │(HTTP→ │ │voice,stt │ │singletons│ │+ Redis │
│ orch) │ │ orch) │ ├────────────┤ └──────────┘ └─────────┘
└────────┘ └────────┘ │app/svc: │
│amocrm,rag, │
┌────────┐ │sales,woo │
│Widget │ └────────────┘
│(public │
│HTTP) │ ┌────────────┐
└────────┘ │Claude │
│Bridge │
┌────────┐ │(subprocess)│
│Admin │ └────────────┘
│Panel │
│(JWT) │
└────────┘
Механизмы связи
| Связь | Механизм | Файлы |
|---|---|---|
| Orchestrator → DB | Импорт синглтонов из db/integration.py + прямой AsyncSessionLocal |
orchestrator.py:85-99, 3704, 3752, 3994 |
| Routers → DB | Смесь: одни через менеджеры, другие через прямой AsyncSessionLocal |
chat.py:18 vs audit.py:13 |
| Routers → Services | ServiceContainer через get_container() или Depends() |
app/dependencies.py |
| Routers → Bot managers | Прямой импорт глобальных синглтонов | from multi_bot_manager import multi_bot_manager |
| TG/WA Bot → Orchestrator | HTTP API через LLMRouter (httpx + BOT_INTERNAL_TOKEN JWT) |
telegram_bot/services/llm_router.py |
| Bot → Config | Env vars + JSON в /tmp + HTTP fallback | multi_bot_manager.py:111-150 |
| Widget → Orchestrator | Public HTTP endpoints (без auth) в orchestrator.py | orchestrator.py:3648-4040 |
| Admin Panel → Orchestrator | JWT auth, HTTP REST + SSE | admin/src/api/*.ts |
| Bridge → Orchestrator | Subprocess, OpenAI-compatible API | bridge_manager.py |
Data flow
TELEGRAM/WHATSAPP WIDGET ADMIN PANEL
↓ ↓ ↓
Message handler POST /widget/session POST /admin/chat/
↓ ↓ sessions/{id}/stream
Session store (память) Session store (DB) ↓
↓ ↓ Session (DB)
LLMRouter.chat_stream() orchestrator.py widget ep ↓
↓ ↓ chat.py streaming
POST /admin/chat/ LLM selection (дубль!) LLM selection
sessions/{id}/stream RAG injection RAG injection
↓ ↓ ↓
───────── CloudLLMService / vLLM ─────────
↓
SSE response
2. Выявленные проблемы
P1 — Операционные риски (влияют на uptime)
2.1. Нет мониторинга подпроцессов ботов
- Где:
multi_bot_manager.py,whatsapp_manager.py - Суть: Бот-подпроцесс падает — оркестратор не знает.
process.poll()проверяется только при API-вызове/status, не проактивно. - Риск: Пользователи TG/WA получают тишину. Нет авторестарта.
2.2. Нет graceful shutdown
- Где:
orchestrator.py:1156-1161 - Суть: При shutdown — только
shutdown_database(). Боты НЕ останавливаются (start_new_session=True). Background tasks НЕ отменяются. Задачи_cleanup_expired_sessionsи_periodic_vacuumзапущены черезcreate_task()без сохранения reference. - Риск: Orphaned процессы, дубли ботов при рестарте.
2.3. Потеря сессий ботов при крэше
- Где:
telegram_bot/services/session_store.py,whatsapp_bot/services/session_store.py - Суть: TG и WA боты хранят историю разговоров только в памяти. Крэш/рестарт = полная потеря контекста.
- Нюанс: Боты уже создают сессии в оркестраторе через
_ensure_session(), т.е. сообщения дублируются в DB. Но бот при рестарте не восстанавливает из DB — создаёт новые сессии.
P2 — Архитектурный долг (усложняет развитие)
2.4. God Object — orchestrator.py (4100 строк)
- Суть: Совмещает: инициализацию сервисов, ~100 legacy эндпоинтов, widget endpoints (~300 строк), background tasks, helper functions.
- Проблема: Widget-логика (LLM selection, RAG injection, amoCRM lead creation) дублирует chat.py.
2.5. Два паттерна доступа к БД
Через менеджеры (@retry_on_busy) |
Прямой AsyncSessionLocal (без retry) |
|---|---|
| chat.py, telegram.py, whatsapp.py, faq.py, llm.py, amocrm.py, wiki_rag.py, kanban.py, workspace.py, auth.py, roles.py, woocommerce.py, claude_code.py, backup.py | audit.py, usage.py, bot_sales.py, legal.py, github_webhook.py + orchestrator.py (3 места) |
8 точек доступа обходят менеджеры → нет retry, нет единообразной обработки ошибок.
2.6. ServiceContainer покрывает только hardware-сервисы
- В контейнере: TTS, STT, LLM, GSM, WikiRAG.
- Всё остальное (30+ DB-менеджеров, bot managers, bridge) — глобальные синглтоны через прямой import.
- Результат: два механизма DI —
Depends(get_llm_service)vsfrom db.integration import async_chat_manager.
2.7. Дублирование LLM backend selection
app/routers/chat.py:624-697— для admin/bot сессийorchestrator.py:3880-3892— для widget сессий- Одна и та же логика: parse
cloud:{provider_id}, load provider, fallback chain.
P3 — Средний приоритет
2.8. Фрагментация сервисного слоя
- Root (12 файлов): cloud_llm, voice, stt, managers
- app/services/ (8+ файлов): amocrm, rag, sales, woo
- Нет документированного критерия разделения.
2.9. Инкогерентность кешей
| Кеш | Файл | Тип | Инвалидация |
|---|---|---|---|
| SessionCache (jti→user) | auth_manager.py | in-memory dict | Ручная при revoke |
| PermissionsCache (role→perms) | auth_manager.py | in-memory dict | Ручная при role update |
| MemberRoleCache (user,ws→role) | auth_manager.py | in-memory dict | Ручная при role change |
| FAQ в CloudLLMService | cloud_llm_service.py | instance var | При явном reload |
| TTS streaming | orchestrator.py | dict + Lock | LRU |
| Redis (amocrm pipelines/leads) | db/redis_client.py | Redis | TTL |
Нет единой стратегии. Пропуск ручного invalidate = stale data.
2.10. Config из трёх источников
- .env →
os.getenv()повсюду - DB (config table, provider configs, bot configs)
- Subprocess env (snapshot at spawn time, не обновляется)
2.11. Отдельные sales DB в подпроцессах
telegram_bot/sales/database.py→data/sales.dbwhatsapp_bot/sales/database.py→data/wa_sales_{id}.db- Вне основной DB, нет единого view на воронку.
3. Как должно быть правильно (рекомендации)
Tier 1 — Критичные (uptime)
| # | Рекомендация | Объём | Суть |
|---|---|---|---|
| R1 | Health monitor подпроцессов | S (~50 строк) | Background task: poll process.poll() каждые 30с. Если dead + auto_start=True → рестарт. Логирование. |
| R2 | Graceful shutdown | S (~30 строк) | В shutdown_event(): stop all bots → stop bridge → cancel tasks → close DB. Сохранять Task references. |
| R3 | Bot sessions из DB | L (рефакторинг) | Бот при рестарте восстанавливает сессии из orchestrator API. Убрать дублирование in-memory ↔ DB. |
Tier 2 — Высокий (архитектура)
| # | Рекомендация | Объём | Суть |
|---|---|---|---|
| R4 | Widget → app/routers/widget.py | M (move) | Вынести ~300 строк widget endpoints из orchestrator.py. Заодно переиспользовать LLM selection из chat.py. |
| R5 | Консолидировать DB-доступ | M | 5 роутеров (audit, usage, bot_sales, legal, github_webhook) + orchestrator.py → через менеджеры. Все получат @retry_on_busy. |
| R6 | Shared LLM resolution | S (~50 строк) | Extract resolve_llm_backend() → использовать в chat.py и widget router. |
Tier 3 — Средний
| # | Рекомендация | Объём | Суть |
|---|---|---|---|
| R7 | Реестр background tasks | S | TaskRegistry(name→Task). Cancel all in shutdown. Show in /health. |
| R8 | Cache invalidation events | M | Event-based invalidation вместо ручных вызовов. |
| R9 | Merge sales DB | L | Перенести sales tables в secretary.db. Унифицировать миграции. |
Tier 4 — Low priority
| # | Рекомендация | Объём |
|---|---|---|
| R10 | Документировать правило root/ vs app/services/ | Текст |
| R11 | Hot-reload конфига ботов (без рестарта) | M |
4. Рекомендуемый порядок
R2 (shutdown) ──→ R1 (health monitor) ──→ R7 (task registry)
независимо от:
R4 (widget router) ──→ R6 (shared LLM resolution)
независимо от:
R5 (DB consolidation)
потом:
R3 (bot sessions) ──→ R9 (sales DB merge)
- R1+R2 — один PR, минимальный риск
- R4+R6 — второй PR, чистый рефакторинг (move + extract)
- R5 — третий PR, каждый роутер отдельным коммитом
S = 1-2 часа, M = полдня, L = день+
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
documentationImprovements or additions to documentationImprovements or additions to documentation