docs(ui): уточнены подсказки и сообщения учебного стенда

Зачем: до запуска менти должен понимать действие параметров, а после
ошибки проверки — где искать причину.

Что: уточнены тексты Airflow, самопроверки, DQ и run-dag.sh, подписи
Superset и Grafana. Логика, запросы, метрики и идентификаторы сохранены.

Проверка: make lint, git diff --check, bash -n; разбор YAML/JSON,
сравнение структуры Python и конфигурации, искусственные примеры ошибок.
Airflow и Grafana проверены через локальные API, Superset — по YAML.
Визуальная проверка интерфейсов не выполнена: браузер недоступен.
This commit is contained in:
ddadmin committed 2026-09-13 16:41:53 -04:00
1 parent 431fed72ad
commit d15f4fe4d8
12 files changed
+145 -71

No files matched your search

+29 -27
View File
@@ -146,25 +146,25 @@ def _ingest_orders() -> TriggerDagRunOperator:
type="integer",
minimum=1,
maximum=7,
title="Сколько дней прожить",
title="Число модельных дней для генерации",
# description_md рендерится подсказкой прямо в форме запуска
# (params.rst, Airflow 3.3), чтобы правило было видно сразу.
description_md=(
"Форма задает только число дней. Номер первого несыгранного "
"дня шаговый даг берёт из переменной `world_position` (Admin → "
"Variables). Поля Logical date и Run ID нужны самому Airflow "
"и на выбор дня не влияют."
"Создать данные за следующие 1–7 модельных дней; по умолчанию "
"за один день. События отправляются без пауз. Номер первого дня "
"берется из `world_position` (Admin → Variables). Поля Logical "
"date и Run ID не меняют выбор дня. После завершения запустите "
"`etl_pipeline`, чтобы обновить DDS и витрины DM."
),
)
},
)
def world_next_day():
"""Прожить следующие дни пачкой, без пауз.
"""Создать данные за следующие модельные дни без пауз между событиями.
Запускается руками. День по умолчанию один, но разгон вперёд идёт одним
нажимом, а не десятью: сколько дней играть — параметр запуска. Первый
день шаговый даг берёт из `world_position`. Логическая дата прогона на выбор
дня не влияет.
Параметр `days` задает число дней: от 1 до 7, по умолчанию 1. Первый день
берется из `world_position`. После загрузки событий и слепков заказов
запустите `etl_pipeline` вручную, чтобы обновить DDS и витрины DM.
"""
@task
@@ -174,7 +174,10 @@ def world_next_day():
position = first_day + days
Variable.set(WORLD_POSITION, str(position))
logging.info(
"дни %s–%s сыграны; новая позиция — %s", first_day, position - 1, position
"данные за модельные дни %s–%s отправлены; world_position=%s",
first_day,
position - 1,
position,
)
first_day = first_unplayed_day()
@@ -210,20 +213,23 @@ def world_next_day():
tags=TAGS,
)
def world_live_day():
"""Прожить следующий день в темпе модельного времени.
"""Постепенно отправить события за следующий модельный день.
Ускорение ×60: модельные сутки укладываются примерно в двадцать четыре
реальные минуты, и суточная волна разворачивается на глазах. Запускается
руками; чтобы мир жил так день за днём сам, есть выключатель `world_live`.
Следующий день шаговый даг берёт из `world_position`. Логическая дата прогона
на выбор дня не влияет.
При ускорении ×60 отправка занимает около 24 реальных минут. Номер дня
берется из `world_position`; Logical date его не меняет. Затем даг
отправляет слепок заказов и ждет его загрузки и завершения `etl_pipeline`.
Для автоматического запуска следующих дней снимите с паузы `world_live`.
"""
@task
def remember_played(first_day: int) -> None:
"""Позиция ставится по сыгранному дню и только по успеху."""
Variable.set(WORLD_POSITION, str(first_day + 1))
logging.info("сыгран день %s; новая позиция — %s", first_day, first_day + 1)
logging.info(
"данные за модельный день %s отправлены; world_position=%s",
first_day,
first_day + 1,
)
first_day = first_unplayed_day()
played = _generator("play_day", ["live", "--day", PLAYED_DAY])
@@ -254,16 +260,12 @@ def world_live_day():
tags=TAGS,
)
def world_live():
"""Выключатель: пока включён, мир живёт день за днём.
"""Автоматически запускать модельные дни, пока даг снят с паузы.
Своей работы у выключателя нет — он дёргает `world_live_day` и ждёт конца.
Ожидание тут несущая конструкция, а не вежливость: без него тик шёл бы
независимо от хода дня, лишние прогоны скопились бы очередью, и мир потом
промчался бы по ней без всякого темпа.
Ждём триггером, а не сенсором: оператор опрашивает тот прогон, который сам
и создал, и ссылка на дочерний прогон видна прямо отсюда. Упал день —
краснеет и выключатель.
Запускает `world_live_day` и ждет его завершения. Пауза останавливает
запуск следующих дней; уже запущенный день завершится. Если он завершился
с ошибкой, этот даг тоже завершится с ошибкой: откройте дочерний запуск
и журнал неуспешной задачи.
"""
TriggerDagRunOperator(
task_id="trigger_live_day",