Общая архитектура
Стек
- Python 3.13+, управление зависимостями —
uv(pyproject.toml+uv.lock). - FastAPI — backend (вебхуки, API).
- NiceGUI — GUI, встраиваемое в iframe МойСклад.
- PostgreSQL — основная БД (asyncpg + SQLAlchemy ORM).
- Redis — брокер Celery + кэш.
- Celery — асинхронные задачи и периодический планировщик (beat).
- Alembic — миграции БД.
- Logfire — distributed tracing и мониторинг.
- Docker Compose — весь стек поднимается одной командой.
Сервисы Docker Compose
| Сервис | Назначение | Порт |
|---|---|---|
traefik |
Reverse proxy, TLS (Let's Encrypt) | 80, 443 |
gui |
NiceGUI/FastAPI — UI-страницы внутри МойСклад | 8080 |
backend0 |
FastAPI — вебхуки от МойСклад | 8081 |
backend1 |
FastAPI — вебхуки (резерв backend0, используется через INTERNAL_BACKEND_URL) |
8082 |
worker0..2 |
Celery workers — выполнение фоновых задач | — |
beat |
Celery beat — периодические задачи | — |
flower |
Мониторинг Celery | 5555 |
db |
PostgreSQL | 5432 |
broker |
Redis (аутентификация по паролю) | 6379 |
Два entry point
Один и тот же код монтируется в контейнеры gui и backend:
- GUI:
services/backend/src/gui.py— импортируетgui_routersиgui_class_endpointsизsrc/endpoints/routers. - Backend:
services/backend/src/backend.py— импортируетbackend_routersизsrc/endpoints/routers.
Таким образом GUI и backend — это два разных процесса, но общий код.
Модель приложения
Каждое приложение имеет две копии: dev (для тестирования) и production. Они различаются только UUID и именем, задаваемыми через переменные окружения .env / apps.env. Постоянные значения (production) — в src/constants.py, runtime-разрешение — в src/env.py.
Каждое приложение экспонирует:
- GUI-страницы в src/endpoints/main/ — NiceGUI-страница настройки внутри МойСклад.
- Виджеты в src/endpoints/widget/ — небольшие HTML-виджеты на карточках документов.
- Кнопки в src/endpoints/button/ — кнопки-действия на карточках.
- Popup в src/endpoints/popup/ — всплывающие окна.
- Webhook handlers в src/endpoints/apps.py — приём и обработка событий от МойСклад.
Поток webhook
Все backend-приложения работают по единому двухэтапному шаблону:
POST /<uid>/webhook-processor— быстрый endpoint, который ставит задачу в Celery (save_webhook). Некоторые приложения фильтруют события перед постановкой в очередь (например,set-prefix— только если измененоnameили action == CREATE).POST /<uid>/internal-webhook— worker забирает задачу и выполняет бизнес-логику приложения.
Это гарантирует, что МойСклад получит HTTP 200 максимально быстро и не будет повторять webhook.
Структура директорий backend
services/backend/src/
backend.py # Entry point для backend (webhooks)
gui.py # Entry point для GUI (NiceGUI)
bot.py # aiogram бот (не используется в production)
constants.py # Production-константы (UUID, имена приложений)
env.py # Runtime-разрешение dev/prod
enums.py # Перечисления (типы документов, webhook actions)
logger.py # Настройка логирования
endpoints/
routers.py # Агрегация всех роутеров
apps.py # Webhook-роутеры для каждого приложения
vendor.py # Vendor endpoints (установка/удаление приложений)
main/ # NiceGUI страницы настроек
widget/ # HTML-виджеты на карточках
button/ # Кнопки на карточках
popup/ # Popup-окна
services/ # Бизнес-логика каждого приложения
models/ # SQLAlchemy модели
repositories/ # Базовые репозитории (только Account/App/Install)
schemas/ # Pydantic-схемы
database/ # Инициализация БД, Alembic
moysklad/ # Клиент Moysklad API (sync + async)
utils/ # Celery, Redis, mail, UoW, репозитории
Инфраструктурные компоненты
Подробности в отдельных файлах: - База данных и модели - Celery и периодические задачи - Клиент Moysklad API