feat(airflow): пульт мира — работники, выключатель, контейнер #83

Merged
ddmitry merged 2 commits from feat/79-world-control into main 2026-08-13 15:09:21 +03:00
4 changed files with 17 additions and 12 deletions
Showing only changes of commit 292302e161 - Show all commits
+4 -1
View File
@@ -50,7 +50,10 @@ make check-services
Дальше, в рабочей петле, обычно хватает `make smoke`.
`.env.example` — образец обязательной локальной настройки. В нём живут имя
экземпляра, внешние порты, учебные учётные данные и ключи. `compose.yaml` не
экземпляра, внешние порты, учебные учётные данные и ключи. Одно значение образца
верно не везде — `DOCKER_GID`: у группы `docker` на каждой машине свой номер, и
свой подскажет `getent group docker`. Пока он не сойдётся, стенд работает весь,
кроме пульта мира — о нём ниже. `compose.yaml` не
дублирует их умолчаниями: если значения нет в `.env`, Compose сразу предложит
скопировать образец. Внутренние адреса, имена топиков и версии образов описывают
сам стенд, поэтому записаны литералами в `compose.yaml` и Dockerfile.
+1
View File
@@ -376,6 +376,7 @@ services:
group_add:
- ${DOCKER_GID:?Скопируйте .env.example в .env}
# Тома перечислены заново: список службы общий не дополняет, а заменяет.
# Появится новый том у остальных служб Airflow — добавьте и сюда.
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./dags:/opt/airflow/dags:ro
+9 -11
View File
@@ -28,8 +28,7 @@ from airflow.sdk import Param, Variable, dag, get_current_context, task
# Факты стенда — образ генератора, сеть, адрес брокера, топик и размер
# стартового мира — приходят окружением, и называет их compose: тот же, что
# называет их разовой службе генератора. Генератор для пульта — отдельная и
# заменяемая сущность, и знает о нём даг ровно то, что здесь перечислено.
# называет их разовой службе генератора.
GENERATOR_IMAGE = os.environ["GENERATOR_IMAGE"]
STAND_NETWORK = os.environ["STAND_NETWORK"]
GENERATOR_ENVIRONMENT = {
@@ -41,11 +40,10 @@ STARTING_DAYS = int(os.environ["WORLD_STARTING_DAYS"])
# Позиция на оси: номер первого несыгранного дня. Переменной нет — мир в
# стартовом состоянии, и играть надо сразу за ним.
#
# Позиция именно ставится, а не увеличивается на единицу. Наложись один прогон
# на другой, худшее при таком правиле — сыгранный дважды день: номера событий
# детерминированы, и повтор схлопнет ReplacingMergeTree. Увеличение в том же
# случае молча съело бы день, и в мире осталась бы дыра, которой никто не
# заметит.
# Позиция ставится, а не увеличивается. Наложись один прогон на другой, худшее
# при таком правиле — сыгранный дважды день, а повтор схлопнет
# ReplacingMergeTree. Увеличение молча съело бы день, и в мире осталась бы
# дыра, которой никто не заметит.
WORLD_POSITION = "world_position"
# Тик выключателя. Каденцию задаёт не он, а сама длина живого дня — около
@@ -75,10 +73,9 @@ def _play(task_id: str, command: list[str]) -> DockerOperator:
command=command,
network_mode=STAND_NETWORK,
environment=GENERATOR_ENVIRONMENT,
# Контейнер убирается за собой в любом исходе — вопреки имени
# значения: оператор сносит его в `finally`. Терять при этом нечего,
# вывод генератора он уже перелил в журнал задачи.
auto_remove="success",
# Контейнер убирается в любом исходе: вывод генератора оператор уже
# перелил в журнал задачи, а мёртвые контейнеры копить незачем.
auto_remove="force",
# По умолчанию оператор монтирует контейнеру временный каталог. Здесь
# это ловушка: путь он заводит внутри Airflow, а монтирует демон с
# хоста, где такого пути нет. Генератору временный каталог не нужен.
@@ -157,6 +154,7 @@ def world_live_day():
dag_id="world_live",
schedule=LIVE_TICK,
start_date=START_DATE,
catchup=False,
is_paused_upon_creation=True,
max_active_runs=1,
tags=TAGS,
+3
View File
@@ -4,6 +4,9 @@ USER root
# Официальный провайдер Kafka использует тот же confluent-kafka. Пробникам
# не нужны его подключения и обёртки, поэтому в образ добавлен сам клиент.
#
# Провайдера docker, которым пульт мира зовёт генератор, ставить не нужно:
# база несёт его сама — 4.5.7 к Airflow 3.3.0, замер 13 августа 2026 года.
RUN uv pip install --python /home/airflow/.local/bin/python --no-cache \
"clickhouse-connect==1.6.0" \
"confluent-kafka==2.15.0" \