Образ собран с `uv sync --frozen --no-dev`, но `uv run` перед каждым запуском
заново синхронизирует venv и подтягивает dev-группу. В логах старта
vidconf-backend-1 и vidconf-worker-1 на проде это видно как «Downloading ruff /
mypy / pygments» и «Installed 12 packages». Хуже всего healthcheck'и: они
выполняют ту же синхронизацию каждые 15 секунд всю жизнь контейнера.
Проверено на локально собранном образе, одна и та же команда:
uv run — качает 12 пакетов, venv 456 → 574 МБ
uv run --no-sync — не качает ничего, venv остаётся 456 МБ
Флаг добавлен во все вызовы в прод-путях: CMD образа, command/entrypoint/
healthcheck всех сервисов compose, миграции и seed в install.sh, те же команды
в docs/deploy. Локальная разработка (dev-setup.md, backend/README.md, CI) не
затронута — там dev-зависимости нужны. Заодно убрано устаревшее объяснение
ретрая `up -d --wait`: первый старт больше не синхронизирует окружение.
Версия uv в образе — 0.11.33, `--no-sync` поддерживается.
Пул создавался с дефолтом SQLAlchemy (5 + 10) и под нагрузкой выгребался
за секунды. Теперь параметры заданы явно и вынесены в настройки:
DB_POOL_SIZE=10, DB_MAX_OVERFLOW=10, DB_POOL_TIMEOUT=10. Таймаут снижен с
дефолтных 30 секунд намеренно — пусть запрос падает быстро и показывает
проблему, а не висит полминуты.
Backend запускался одним процессом uvicorn: любой блокирующий вызов
останавливал и параллельные запросы, и WS-чат всех участников. Добавлен
UVICORN_WORKERS с дефолтом 2 — не по числу ядер, потому что на
четырёхъядерном сервере ядра делятся с LiveKit, а медиа важнее API.
Бюджет соединений считается на весь инстанс: каждый воркер держит свой
пул, поэтому UVICORN_WORKERS × (DB_POOL_SIZE + DB_MAX_OVERFLOW) должно
оставаться заметно ниже max_connections у Postgres.
Многопроцессность безопасна: бутстрап настроек в lifespan идемпотентен
(INSERT ... ON CONFLICT DO NOTHING), а WS-чат разносит сообщения через
Redis pub/sub и состояния в памяти процесса не держит.