feat(generator): глагол next-day — следующий модельный день от слепка
- Зачем:
- режим кормления стенда порциями: менти триггерит «следующий день»,
видит полный цикл DWH за один шаг (задача 13, вариант 2 — генерация
от слепка T_end).
- Что:
- новый ограниченный режим next-day: восстановление мира из state,
генерация ровно [T_end, T_end+24h), публикация данные -> state ->
манифест (манифест — точка фиксации, автоотката нет).
- операция next-day в DAG generator_control: своя предпроверка границы
вместо clean-guard, идемпотентность через параметр expected_t_end.
- цепочка границ — накопительное поле boundaries в манифесте, старый
формат читается как [T0, T_end]; импорт не изменён.
- новая проверка цепочки (make generated-history-chain-check): непарные
счётчики и однородность по каждой границе, явный статус нулевого
стыка, хвост за границей по всем четырём топикам, литералы в UTC
с микросекундами.
- документация OPERATIONS.md: глагол, предпроверка, восстановление
после сбоя, ограничение retention; в задаче 13 — решения двух слепых
ревью постановки и кода с аргументами отклонений.
- Проверка:
- make test: 204 теста генератора + 31 контракт корня, зелёные.
- make generated-history-chain-check: зелёный, 2 внутренние границы,
непарные счётчики нулевые; учебный цикл: DM 322 -> 10026 -> 19196
за два next-day подряд.
- make generated-history-runtime-check (регрессия задачи 20): зелёный.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,14 +30,15 @@ def test_trigger_form_has_expected_param_enums():
|
||||
"""Форма запуска ограничивает операции и профили."""
|
||||
text = DAG_PATH.read_text(encoding="utf-8")
|
||||
|
||||
assert 'enum=["backfill", "import", "check"]' in text
|
||||
assert 'enum=["backfill", "import", "next-day", "check"]' in text
|
||||
assert "enum=sorted(PROFILES)" in text
|
||||
assert '"duration": Param(' in text
|
||||
assert '"artifact_path": Param(' in text
|
||||
assert '"expected_t_end": Param(' in text
|
||||
|
||||
|
||||
def test_dag_branches_and_waits_for_etl_completion():
|
||||
"""Backfill/import запускают ETL и ждут его завершения перед check."""
|
||||
"""Backfill/import/next-day запускают ETL и ждут завершения перед check."""
|
||||
text = DAG_PATH.read_text(encoding="utf-8")
|
||||
|
||||
assert "BranchPythonOperator" in text
|
||||
@@ -48,6 +49,23 @@ def test_dag_branches_and_waits_for_etl_completion():
|
||||
assert 'failed_states=["failed"]' in text
|
||||
|
||||
|
||||
def test_next_day_has_own_boundary_precheck_and_serial_execution():
|
||||
"""Next-day не использует clean-guard и не допускает параллельных запусков."""
|
||||
text = DAG_PATH.read_text(encoding="utf-8")
|
||||
|
||||
assert "schedule=None" in text
|
||||
assert "max_active_runs=1" in text
|
||||
assert 'return "check_etl_not_paused_before_next_day"' in text
|
||||
assert "assert_next_day_snapshot" in text
|
||||
assert "assert_expected_t_end" in text
|
||||
next_day_precheck = text.split("def precheck_next_day", maxsplit=1)[1].split(
|
||||
"\ndef ", maxsplit=1
|
||||
)[0]
|
||||
assert "assert_stand_clean" not in next_day_precheck
|
||||
assert "assert_live_generator_not_running" in next_day_precheck
|
||||
assert "run_next_day" in text
|
||||
|
||||
|
||||
def test_generator_control_prechecks_etl_dag_not_paused_before_waiting():
|
||||
"""Пульт проверяет паузу etl_pipeline до долгого ожидания."""
|
||||
text = DAG_PATH.read_text(encoding="utf-8")
|
||||
@@ -62,8 +80,10 @@ def test_generator_control_prechecks_etl_dag_not_paused_before_waiting():
|
||||
assert "fail_when_dag_is_paused" in text
|
||||
assert 'return "check_etl_not_paused_before_backfill"' in text
|
||||
assert 'return "check_etl_not_paused_before_import"' in text
|
||||
assert 'return "check_etl_not_paused_before_next_day"' in text
|
||||
assert "check_etl_not_paused_before_backfill >> precheck_backfill_task" in text
|
||||
assert "check_etl_not_paused_before_import >> precheck_import_task" in text
|
||||
assert "check_etl_not_paused_before_next_day >> precheck_next_day_task" in text
|
||||
assert text.index("check_etl_not_paused_before_backfill >> precheck_backfill_task") < text.index(
|
||||
"precheck_backfill_task >> backfill_task"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user