Compare commits
3 Commits
b528785249
...
v0.0.13
| Author | SHA1 | Date | |
|---|---|---|---|
| 705f160912 | |||
| 7a5e9d2d8a | |||
| eb4e5ea83f |
@@ -112,7 +112,7 @@ SMTP_TIMEOUT_S=30
|
|||||||
# --- Версия инстанса (релиз v0.0.1) ---
|
# --- Версия инстанса (релиз v0.0.1) ---
|
||||||
# install.sh копирует значение из корневого файла VERSION при каждой
|
# install.sh копирует значение из корневого файла VERSION при каждой
|
||||||
# установке/обновлении — руками менять не нужно.
|
# установке/обновлении — руками менять не нужно.
|
||||||
VIDCONF_VERSION=0.0.12
|
VIDCONF_VERSION=0.0.13
|
||||||
|
|
||||||
# --- Профили compose. Дефолт ниже (`media,monitoring`) — только для ручного
|
# --- Профили compose. Дефолт ниже (`media,monitoring`) — только для ручного
|
||||||
# `docker compose up` БЕЗ install.sh: медиа (LiveKit+coturn) + мониторинг,
|
# `docker compose up` БЕЗ install.sh: медиа (LiveKit+coturn) + мониторинг,
|
||||||
|
|||||||
29
CHANGELOG.md
29
CHANGELOG.md
@@ -3,6 +3,35 @@
|
|||||||
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/),
|
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/),
|
||||||
проект придерживается [семантического версионирования](https://semver.org/lang/ru/).
|
проект придерживается [семантического версионирования](https://semver.org/lang/ru/).
|
||||||
|
|
||||||
|
## [0.0.13] — 2026-07-28
|
||||||
|
|
||||||
|
Снижение нагрузки на сеть: клиент перестаёт получать полное качество всех
|
||||||
|
чужих камер независимо от того, какого размера плитка на экране.
|
||||||
|
|
||||||
|
### Изменено
|
||||||
|
- Включены `adaptiveStream` и `dynacast` в опциях комнаты. Оба флага в LiveKit
|
||||||
|
выключены по умолчанию, из-за чего каждый участник был подписан на полное
|
||||||
|
качество всех чужих треков, а каждый паблишер слал все слои симулкаста, даже
|
||||||
|
когда их никто не смотрит. Теперь качество подписки выбирается по фактическому
|
||||||
|
размеру плитки, а неотрисованные треки уходят в паузу. На локальном стенде
|
||||||
|
(9 участников, паблишеры 720p) входящий поток одного клиента упал с
|
||||||
|
11 110 до 778 кбит/с.
|
||||||
|
|
||||||
|
Вместе с этим начинает экономить уже написанный код, который до сих пор не
|
||||||
|
давал выигрыша: «скрыть остальных» не рендерит карусель (исходящий трафик
|
||||||
|
LiveKit 0.76 → 0.03 Мбит/с), пагинация сетки участников рендерит только
|
||||||
|
текущую страницу, а пауза чужого видео в свёрнутой вкладке работает лишь
|
||||||
|
при включённом `adaptiveStream`.
|
||||||
|
- Контейнеры больше не пересобирают окружение Python при запуске: во все
|
||||||
|
вызовы `uv run` в прод-путях (CMD образа, `command`/`entrypoint`/`healthcheck`
|
||||||
|
сервисов, миграции и seed в `install.sh`) добавлен `--no-sync`. Раньше
|
||||||
|
окружение, собранное на этапе build с `--no-dev`, при каждом старте
|
||||||
|
синхронизировалось заново и подтягивало dev-группу: ~26 МБ загрузок,
|
||||||
|
замедленный старт и ruff/mypy/pytest в рантайме. Healthcheck'и делали то же
|
||||||
|
самое каждые 15 секунд всю жизнь контейнера. Размер `/app/.venv` после
|
||||||
|
запуска: 574 → 456 МБ. Локальная разработка не затронута — там dev-группа
|
||||||
|
нужна и ставится как раньше.
|
||||||
|
|
||||||
## [0.0.12] — 2026-07-28
|
## [0.0.12] — 2026-07-28
|
||||||
|
|
||||||
Разблокировка backend под нагрузкой: вход в конференцию перестаёт отваливаться,
|
Разблокировка backend под нагрузкой: вход в конференцию перестаёт отваливаться,
|
||||||
|
|||||||
@@ -45,5 +45,12 @@ HEALTHCHECK --interval=10s --timeout=5s --retries=10 --start-period=15s \
|
|||||||
#
|
#
|
||||||
# `sh -c` нужен ради подстановки переменной (exec-форма её не делает),
|
# `sh -c` нужен ради подстановки переменной (exec-форма её не делает),
|
||||||
# `exec` — чтобы uvicorn получил PID 1 и корректно принимал SIGTERM.
|
# `exec` — чтобы uvicorn получил PID 1 и корректно принимал SIGTERM.
|
||||||
|
#
|
||||||
|
# `--no-sync`: окружение уже собрано выше (`uv sync --frozen --no-dev`), и
|
||||||
|
# пересобирать его в рантайме незачем. Без флага `uv run` перед каждым
|
||||||
|
# запуском заново синхронизирует venv И ПОДТЯГИВАЕТ dev-группу (ruff, mypy,
|
||||||
|
# pytest — ~30 МБ загрузок на каждый старт контейнера, dev-инструменты в
|
||||||
|
# проде и раздутый venv). То же касается healthcheck'ов в
|
||||||
|
# deploy/docker-compose.yml, которые дёргают `uv run` каждые 15 секунд.
|
||||||
CMD ["sh", "-c", \
|
CMD ["sh", "-c", \
|
||||||
"exec uv run uvicorn main:create_app --factory --host 0.0.0.0 --port 8000 --workers ${UVICORN_WORKERS:-2}"]
|
"exec uv run --no-sync uvicorn main:create_app --factory --host 0.0.0.0 --port 8000 --workers ${UVICORN_WORKERS:-2}"]
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ services:
|
|||||||
MEDIA_ROOT: ${MEDIA_ROOT:-/app/media}
|
MEDIA_ROOT: ${MEDIA_ROOT:-/app/media}
|
||||||
# Версия инстанса (релиз v0.0.1) — install.sh копирует значение
|
# Версия инстанса (релиз v0.0.1) — install.sh копирует значение
|
||||||
# из файла VERSION (корень репозитория) в .env; отдаётся в GET /api/health.
|
# из файла VERSION (корень репозитория) в .env; отдаётся в GET /api/health.
|
||||||
VIDCONF_VERSION: ${VIDCONF_VERSION:-0.0.12}
|
VIDCONF_VERSION: ${VIDCONF_VERSION:-0.0.13}
|
||||||
# Число процессов uvicorn (см. backend/Dockerfile). Дефолт 2 рассчитан
|
# Число процессов uvicorn (см. backend/Dockerfile). Дефолт 2 рассчитан
|
||||||
# на 4-ядерный сервер, где ядра делятся с LiveKit. Поднимая значение,
|
# на 4-ядерный сервер, где ядра делятся с LiveKit. Поднимая значение,
|
||||||
# проверьте бюджет соединений с БД: каждый воркер держит свой пул
|
# проверьте бюджет соединений с БД: каждый воркер держит свой пул
|
||||||
@@ -125,7 +125,13 @@ services:
|
|||||||
context: ../backend
|
context: ../backend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: ["uv", "run", "celery", "-A", "workers.celery_app", "worker", "-B",
|
# `--no-sync` во ВСЕХ вызовах `uv run` в этом файле: окружение собрано на
|
||||||
|
# этапе build образа (`uv sync --frozen --no-dev`, backend/Dockerfile), а
|
||||||
|
# без флага `uv run` синхронизирует venv заново при каждом запуске — и
|
||||||
|
# тянет dev-группу (ruff, mypy, pytest), которой в проде делать нечего.
|
||||||
|
# Для healthcheck'ов это особенно дорого: они дёргаются каждые 15 секунд
|
||||||
|
# всю жизнь контейнера.
|
||||||
|
command: ["uv", "run", "--no-sync", "celery", "-A", "workers.celery_app", "worker", "-B",
|
||||||
"-Q", "celery,summarize,notify", "--loglevel=info"]
|
"-Q", "celery,summarize,notify", "--loglevel=info"]
|
||||||
env_file:
|
env_file:
|
||||||
- ../.env
|
- ../.env
|
||||||
@@ -152,7 +158,7 @@ services:
|
|||||||
# нет HTTP-сервера на 8000. Проверяем воркер через `celery ... inspect
|
# нет HTTP-сервера на 8000. Проверяем воркер через `celery ... inspect
|
||||||
# ping`, как рекомендует документация Celery.
|
# ping`, как рекомендует документация Celery.
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "uv", "run", "celery", "-A", "workers.celery_app", "inspect", "ping", "--timeout", "5"]
|
test: ["CMD", "uv", "run", "--no-sync", "celery", "-A", "workers.celery_app", "inspect", "ping", "--timeout", "5"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
@@ -186,7 +192,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ../backend
|
context: ../backend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
entrypoint: ["uv", "run", "python", "/download-model.py"]
|
entrypoint: ["uv", "run", "--no-sync", "python", "/download-model.py"]
|
||||||
environment:
|
environment:
|
||||||
WHISPER_MODEL: ${WHISPER_MODEL:-small}
|
WHISPER_MODEL: ${WHISPER_MODEL:-small}
|
||||||
WHISPER_MODELS_ROOT: /models/whisper
|
WHISPER_MODELS_ROOT: /models/whisper
|
||||||
@@ -221,7 +227,7 @@ services:
|
|||||||
# `worker`, и `celery inspect ping` без `--destination` опросит ВЕСЬ
|
# `worker`, и `celery inspect ping` без `--destination` опросит ВЕСЬ
|
||||||
# кластер — упавший worker-transcriber остался бы "healthy", потому что
|
# кластер — упавший worker-transcriber остался бы "healthy", потому что
|
||||||
# ответил бы базовый worker.
|
# ответил бы базовый worker.
|
||||||
command: ["uv", "run", "celery", "-A", "workers.celery_app", "worker",
|
command: ["uv", "run", "--no-sync", "celery", "-A", "workers.celery_app", "worker",
|
||||||
"-Q", "transcription", "--pool=solo", "--concurrency=1",
|
"-Q", "transcription", "--pool=solo", "--concurrency=1",
|
||||||
"--hostname=worker-transcriber@localhost", "--loglevel=info"]
|
"--hostname=worker-transcriber@localhost", "--loglevel=info"]
|
||||||
env_file:
|
env_file:
|
||||||
@@ -252,7 +258,7 @@ services:
|
|||||||
# HTTP-эндпоинта нет — пинг celery, но именно этого узла (см. --hostname
|
# HTTP-эндпоинта нет — пинг celery, но именно этого узла (см. --hostname
|
||||||
# в command выше), а не первого ответившего в общем кластере.
|
# в command выше), а не первого ответившего в общем кластере.
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "uv", "run", "celery", "-A", "workers.celery_app", "inspect", "ping", "--timeout", "5", "--destination", "worker-transcriber@localhost"]
|
test: ["CMD", "uv", "run", "--no-sync", "celery", "-A", "workers.celery_app", "inspect", "ping", "--timeout", "5", "--destination", "worker-transcriber@localhost"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
@@ -277,7 +283,7 @@ services:
|
|||||||
args:
|
args:
|
||||||
WITH_GPU_EXTRA: "true"
|
WITH_GPU_EXTRA: "true"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: ["uv", "run", "celery", "-A", "workers.celery_app", "worker",
|
command: ["uv", "run", "--no-sync", "celery", "-A", "workers.celery_app", "worker",
|
||||||
"-Q", "transcription", "--pool=solo", "--concurrency=1",
|
"-Q", "transcription", "--pool=solo", "--concurrency=1",
|
||||||
"--hostname=worker-transcriber-gpu@localhost", "--loglevel=info"]
|
"--hostname=worker-transcriber-gpu@localhost", "--loglevel=info"]
|
||||||
env_file:
|
env_file:
|
||||||
@@ -310,7 +316,7 @@ services:
|
|||||||
whisper-model-init:
|
whisper-model-init:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "uv", "run", "celery", "-A", "workers.celery_app", "inspect", "ping", "--timeout", "5", "--destination", "worker-transcriber-gpu@localhost"]
|
test: ["CMD", "uv", "run", "--no-sync", "celery", "-A", "workers.celery_app", "inspect", "ping", "--timeout", "5", "--destination", "worker-transcriber-gpu@localhost"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ docker exec vidconf-postgres-1 pg_dump -U vidconf vidconf | gzip > db-$(date +%F
|
|||||||
```bash
|
```bash
|
||||||
gunzip -c db-2026-07-25.sql.gz | docker exec -i vidconf-postgres-1 psql -U vidconf vidconf
|
gunzip -c db-2026-07-25.sql.gz | docker exec -i vidconf-postgres-1 psql -U vidconf vidconf
|
||||||
# Догнать миграции, если бэкап снят на более старой версии кода:
|
# Догнать миграции, если бэкап снят на более старой версии кода:
|
||||||
docker compose -f deploy/docker-compose.yml --env-file .env run --rm backend uv run alembic upgrade head
|
docker compose -f deploy/docker-compose.yml --env-file .env run --rm backend uv run --no-sync alembic upgrade head
|
||||||
docker compose -f deploy/docker-compose.yml --env-file .env restart backend worker
|
docker compose -f deploy/docker-compose.yml --env-file .env restart backend worker
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ CPU-only — отдельного GPU-варианта профилей для
|
|||||||
|
|
||||||
Поведение:
|
Поведение:
|
||||||
- **Дефолт (Enter):** применяет матрицу выбранного пресета к настройкам БД
|
- **Дефолт (Enter):** применяет матрицу выбранного пресета к настройкам БД
|
||||||
(defs: `docker compose exec -T backend uv run python -m scripts.apply_preset_settings --force`)
|
(defs: `docker compose exec -T backend uv run --no-sync python -m scripts.apply_preset_settings --force`)
|
||||||
- **Отказ (`n`):** сохраняет ручные правки админа; переменные `BOOTSTRAP_*` в `.env`
|
- **Отказ (`n`):** сохраняет ручные правки админа; переменные `BOOTSTRAP_*` в `.env`
|
||||||
обновляются, но скрипт применения настроек НЕ запускается
|
обновляются, но скрипт применения настроек НЕ запускается
|
||||||
- **Флаг `--yes`:** автоматически применяет пресет без вопроса (для CI/CD)
|
- **Флаг `--yes`:** автоматически применяет пресет без вопроса (для CI/CD)
|
||||||
@@ -111,7 +111,7 @@ Grafana/Prometheus не поднимаются автоматически — с
|
|||||||
собирает фронтенд-SPA и вкомпилирует статику, `frontend/Dockerfile`).
|
собирает фронтенд-SPA и вкомпилирует статику, `frontend/Dockerfile`).
|
||||||
4. Поднимает `postgres`/`redis` (`up -d --wait`) и применяет **до старта
|
4. Поднимает `postgres`/`redis` (`up -d --wait`) и применяет **до старта
|
||||||
backend** миграции и seed одноразовыми контейнерами:
|
backend** миграции и seed одноразовыми контейнерами:
|
||||||
`docker compose run --rm backend uv run alembic upgrade head` +
|
`docker compose run --rm backend uv run --no-sync alembic upgrade head` +
|
||||||
`... python -m scripts.seed`. Порядок критичен: `backend.lifespan`
|
`... python -m scripts.seed`. Порядок критичен: `backend.lifespan`
|
||||||
бутстрапит `instance_settings` при каждом старте приложения, поэтому на
|
бутстрапит `instance_settings` при каждом старте приложения, поэтому на
|
||||||
чистой БД таблицы обязаны существовать до первого запуска backend — иначе
|
чистой БД таблицы обязаны существовать до первого запуска backend — иначе
|
||||||
@@ -122,9 +122,8 @@ Grafana/Prometheus не поднимаются автоматически — с
|
|||||||
настройки инстанса не перетираются).
|
настройки инстанса не перетираются).
|
||||||
5. Поднимает остальной стек: `docker compose <--profile ...> up -d --wait`
|
5. Поднимает остальной стек: `docker compose <--profile ...> up -d --wait`
|
||||||
(backend, worker, nginx с фронтом + сервисы активных профилей). Команда
|
(backend, worker, nginx с фронтом + сервисы активных профилей). Команда
|
||||||
идемпотентна и обёрнута в ретрай (до 3 попыток): первый старт backend/worker
|
идемпотентна и обёрнута в ретрай (до 3 попыток): на слабой/загруженной
|
||||||
включает `uv run` (синхронизация окружения + компиляция байткода), и на
|
машине healthcheck может не успеть за отведённые
|
||||||
слабой/загруженной машине healthcheck может не успеть за отведённые
|
|
||||||
retries — повтор лишь дожидается уже стартующих контейнеров.
|
retries — повтор лишь дожидается уже стартующих контейнеров.
|
||||||
6. Печатает сводку: URL фронтенда/бэкенда, учётные данные администратора,
|
6. Печатает сводку: URL фронтенда/бэкенда, учётные данные администратора,
|
||||||
команда для `--profile monitoring`.
|
команда для `--profile monitoring`.
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ services:
|
|||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# Без -B: beat уже запущен на базовом worker (см. правило выше).
|
# Без -B: beat уже запущен на базовом worker (см. правило выше).
|
||||||
command: ["uv", "run", "celery", "-A", "workers.celery_app", "worker",
|
command: ["uv", "run", "--no-sync", "celery", "-A", "workers.celery_app", "worker",
|
||||||
"-Q", "summarize", "--hostname=worker-summarize-%h@%h", "--loglevel=info"]
|
"-Q", "summarize", "--hostname=worker-summarize-%h@%h", "--loglevel=info"]
|
||||||
env_file:
|
env_file:
|
||||||
- ../.env
|
- ../.env
|
||||||
|
|||||||
@@ -187,6 +187,22 @@ export function RoomPage() {
|
|||||||
const { userChoices } = usePersistentUserChoices()
|
const { userChoices } = usePersistentUserChoices()
|
||||||
const roomOptions = useMemo<RoomOptions>(
|
const roomOptions = useMemo<RoomOptions>(
|
||||||
() => ({
|
() => ({
|
||||||
|
// Оба флага в LiveKit по умолчанию выключены, и без них каждый клиент
|
||||||
|
// подписан на полное качество всех чужих треков независимо от размера
|
||||||
|
// плитки, а каждый паблишер шлёт все слои симулкаста, даже если их никто
|
||||||
|
// не смотрит. На тесте 28.07.2026 (19 участников, ~8 камер) это дало
|
||||||
|
// устойчивые 140–169 Мбит/с исходящего трафика при пике 240, 662 события
|
||||||
|
// `remote bwe: channel congestion detected` и 146 переходов аллокатора
|
||||||
|
// STABLE → DEFICIENT — то есть видимый участникам лаг.
|
||||||
|
//
|
||||||
|
// adaptiveStream: подписка на слой по фактическому размеру плитки на
|
||||||
|
// экране + пауза треков, которые сейчас не отрисованы. Именно на нём
|
||||||
|
// начинает экономить уже написанный код: «скрыть остальных»
|
||||||
|
// (RoomStage) не рендерит карусель, а пагинация StageGrid рендерит
|
||||||
|
// только текущую страницу — неприаттаченные треки считаются невидимыми.
|
||||||
|
// dynacast: паблишер прекращает отдавать слои, на которые нет подписчиков.
|
||||||
|
adaptiveStream: true,
|
||||||
|
dynacast: true,
|
||||||
audioCaptureDefaults: { deviceId: userChoices.audioDeviceId || undefined },
|
audioCaptureDefaults: { deviceId: userChoices.audioDeviceId || undefined },
|
||||||
videoCaptureDefaults: { deviceId: userChoices.videoDeviceId || undefined },
|
videoCaptureDefaults: { deviceId: userChoices.videoDeviceId || undefined },
|
||||||
// Аудиовыход (колонки/наушники/bluetooth) — отдельный персист, не через
|
// Аудиовыход (колонки/наушники/bluetooth) — отдельный персист, не через
|
||||||
|
|||||||
13
install.sh
13
install.sh
@@ -526,13 +526,14 @@ docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --wait postgres r
|
|||||||
# exist" и healthcheck (--wait) никогда не проходит. `compose run` запускает
|
# exist" и healthcheck (--wait) никогда не проходит. `compose run` запускает
|
||||||
# одноразовый контейнер с нужной командой, не поднимая uvicorn/lifespan.
|
# одноразовый контейнер с нужной командой, не поднимая uvicorn/lifespan.
|
||||||
echo "[install] Применяю миграции Alembic и seed (админ/справочники) — до старта backend"
|
echo "[install] Применяю миграции Alembic и seed (админ/справочники) — до старта backend"
|
||||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm backend uv run alembic upgrade head
|
# `--no-sync`: окружение собрано в образе, повторная синхронизация в рантайме
|
||||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm backend uv run python -m scripts.seed
|
# только тянула бы dev-группу (см. комментарий в backend/Dockerfile).
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm backend uv run --no-sync alembic upgrade head
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" run --rm backend uv run --no-sync python -m scripts.seed
|
||||||
|
|
||||||
echo "[install] docker compose up -d --wait (backend/worker/nginx и остальные сервисы профиля)"
|
echo "[install] docker compose up -d --wait (backend/worker/nginx и остальные сервисы профиля)"
|
||||||
# Первый старт backend/worker включает `uv run` (синхронизация окружения +
|
# На слабой/загруженной машине healthcheck может не успеть пройти за отведённые
|
||||||
# компиляция байткода) — на слабой/загруженной машине healthcheck может не
|
# retries, и `--wait` вернёт "container is
|
||||||
# успеть пройти за отведённые retries, и `--wait` вернёт "container is
|
|
||||||
# unhealthy", хотя сервис через несколько секунд становится healthy. Команда
|
# unhealthy", хотя сервис через несколько секунд становится healthy. Команда
|
||||||
# идемпотентна, поэтому повторяем её несколько раз: повтор лишь дожидается
|
# идемпотентна, поэтому повторяем её несколько раз: повтор лишь дожидается
|
||||||
# уже стартующих контейнеров, ничего не пересоздавая.
|
# уже стартующих контейнеров, ничего не пересоздавая.
|
||||||
@@ -573,7 +574,7 @@ if [ "$FRESH_ENV" != "1" ]; then
|
|||||||
fi
|
fi
|
||||||
if [ "$APPLY_PRESET_SETTINGS" = "1" ]; then
|
if [ "$APPLY_PRESET_SETTINGS" = "1" ]; then
|
||||||
echo "[install] Применяю настройки модулей инстанса под пресет ${PRESET}"
|
echo "[install] Применяю настройки модулей инстанса под пресет ${PRESET}"
|
||||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T backend uv run python -m scripts.apply_preset_settings --force
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T backend uv run --no-sync python -m scripts.apply_preset_settings --force
|
||||||
else
|
else
|
||||||
echo "[install] Настройки модулей инстанса НЕ изменены — сохранены ручные правки администратора"
|
echo "[install] Настройки модулей инстанса НЕ изменены — сохранены ручные правки администратора"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user