Контекст
Анализ текущих связей между подсистемами 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) vs from 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.db
whatsapp_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 = день+
Контекст
Анализ текущих связей между подсистемами AI Secretary System. Цель — зафиксировать как подсистемы взаимодействуют, где проблемы, и как должно быть правильно.
1. Карта подсистем
Механизмы связи
db/integration.py+ прямойAsyncSessionLocalAsyncSessionLocalServiceContainerчерезget_container()илиDepends()from multi_bot_manager import multi_bot_managerLLMRouter(httpx + BOT_INTERNAL_TOKEN JWT)Data flow
2. Выявленные проблемы
P1 — Операционные риски (влияют на uptime)
2.1. Нет мониторинга подпроцессов ботов
multi_bot_manager.py,whatsapp_manager.pyprocess.poll()проверяется только при API-вызове/status, не проактивно.2.2. Нет graceful shutdown
orchestrator.py:1156-1161shutdown_database(). Боты НЕ останавливаются (start_new_session=True). Background tasks НЕ отменяются. Задачи_cleanup_expired_sessionsи_periodic_vacuumзапущены черезcreate_task()без сохранения reference.2.3. Потеря сессий ботов при крэше
telegram_bot/services/session_store.py,whatsapp_bot/services/session_store.py_ensure_session(), т.е. сообщения дублируются в DB. Но бот при рестарте не восстанавливает из DB — создаёт новые сессии.P2 — Архитектурный долг (усложняет развитие)
2.4. God Object — orchestrator.py (4100 строк)
2.5. Два паттерна доступа к БД
@retry_on_busy)AsyncSessionLocal(без retry)8 точек доступа обходят менеджеры → нет retry, нет единообразной обработки ошибок.
2.6. ServiceContainer покрывает только hardware-сервисы
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 сессийcloud:{provider_id}, load provider, fallback chain.P3 — Средний приоритет
2.8. Фрагментация сервисного слоя
2.9. Инкогерентность кешей
Нет единой стратегии. Пропуск ручного invalidate = stale data.
2.10. Config из трёх источников
os.getenv()повсюду2.11. Отдельные sales DB в подпроцессах
telegram_bot/sales/database.py→data/sales.dbwhatsapp_bot/sales/database.py→data/wa_sales_{id}.db3. Как должно быть правильно (рекомендации)
Tier 1 — Критичные (uptime)
process.poll()каждые 30с. Если dead +auto_start=True→ рестарт. Логирование.shutdown_event(): stop all bots → stop bridge → cancel tasks → close DB. Сохранять Task references.Tier 2 — Высокий (архитектура)
@retry_on_busy.resolve_llm_backend()→ использовать в chat.py и widget router.Tier 3 — Средний
TaskRegistry(name→Task). Cancel all in shutdown. Show in /health.Tier 4 — Low priority
4. Рекомендуемый порядок
S = 1-2 часа, M = полдня, L = день+