docs(review): добавлен P0-баг — потеря данных при двойном STG-запуске

- Зачем:
  - обнаружена проблема: ODS batch resolver берёт только последний batch,
    транзакционные данные промежуточных STG-запусков теряются навсегда.
- Что:
  - добавлен P0 в architecture_review.md с описанием сценария и решения.
  - обновлена сводная таблица трудозатрат.
- Проверка:
  - cat docs/internal/architecture_review.md | grep -A5 "batch resolver теряет".
This commit is contained in:
2026-03-01 17:52:59 +03:00
parent 768334453f
commit faf410b4e8
+12 -1
View File
@@ -53,6 +53,16 @@ GP-специфичная best practice, которую забывают даж
### P0: Фактическая ошибка (исправить до показа студентам) ### P0: Фактическая ошибка (исправить до показа студентам)
- [ ] **ODS batch resolver теряет данные при двух STG-запусках подряд**
- Сценарий: STG run_1 загружает день N, STG run_2 загружает день N+1, затем ODS запускается
- `_resolve_stg_batch_id()` выбирает только последний согласованный batch (`run_2`)
- Все ODS load-скрипты фильтруют `WHERE batch_id = 'run_2'` → данные `run_1` навсегда пропущены
- **Справочники** (airports, airplanes, routes, seats): проблемы нет — full snapshot, `run_2` содержит всё
- **Транзакционные таблицы** (bookings, tickets, flights, segments, boarding_passes): **потеря данных** — инкрементальные записи `run_1` никогда не попадут в ODS
- Корень проблемы: batch resolver проектировался для согласованности справочников (INTERSECT), но тот же single-batch фильтр применяется к транзакционным таблицам, где нужны **все необработанные** batch-и
- **Нужно**: разделить логику — для транзакционных таблиц загружать все batch-и с `_load_ts > MAX(_load_ts в ODS)` (аналог HWM из DM), для справочников — по-прежнему последний согласованный
- Файлы: `airflow/dags/bookings_to_gp_ods.py`, `sql/ods/bookings_load.sql`, `sql/ods/tickets_load.sql`, `sql/ods/flights_load.sql`, `sql/ods/segments_load.sql`, `sql/ods/boarding_passes_load.sql`
- [x] **Противоречие в distribution key для airport_traffic** - [x] **Противоречие в distribution key для airport_traffic**
- `bookings_dm_design.md` (строка 182): `DISTRIBUTED BY (traffic_date)` - `bookings_dm_design.md` (строка 182): `DISTRIBUTED BY (traffic_date)`
- `sales_report_ddl.sql`: явно объясняет, почему distribution by date — антипаттерн - `sales_report_ddl.sql`: явно объясняет, почему distribution by date — антипаттерн
@@ -143,7 +153,8 @@ GP-специфичная best practice, которую забывают даж
| Приоритет | Действие | Оценка | Ключевые файлы | | Приоритет | Действие | Оценка | Ключевые файлы |
|-----------|----------|--------|----------------| |-----------|----------|--------|----------------|
| **P0** | Исправить distribution key в airport_traffic | 5 мин | `docs/internal/bookings_dm_design.md` | | **P0** | ODS batch resolver: разделить логику для справочников и транзакций | 2-3 часа | ODS DAG + 5 транзакционных load-скриптов |
| ~~P0~~ | ~~Исправить distribution key в airport_traffic~~ | ~~5 мин~~ | ~~done~~ |
| **P1** | Добавить 7 точечных комментариев | 30-40 мин | 6-7 файлов (DDL, load, DAG) | | **P1** | Добавить 7 точечных комментариев | 30-40 мин | 6-7 файлов (DDL, load, DAG) |
| **P2** | Рефакторинг hashdiff → TEMP TABLE | 1 час | `sql/dds/dim_routes_load.sql` | | **P2** | Рефакторинг hashdiff → TEMP TABLE | 1 час | `sql/dds/dim_routes_load.sql` |
| **P2** | Переименовать STG поля в канон + заметка | 1-2 часа | 27 STG SQL + ODS load + naming_conventions.md | | **P2** | Переименовать STG поля в канон + заметка | 1-2 часа | 27 STG SQL + ODS load + naming_conventions.md |