Решает развилку #105: где живут справочники ClickHouse и нужно ли одно правило
для всех.
Решение
Справочные данные — самостоятельная зона dic вне цепочки STG → ODS → DDS → DM.
Читать её вправе любой слой, писать — никто, кроме владельца источника. dds.products переехал в dic.products.
Веер строился до оценки и включал все варианты, названные в тикете, плюс три,
оспаривающие саму рамку «база выражает принадлежность». Отвергнутые записаны с
причинами в ADR 0012.
Устройство
Словарь читает не файл, а подложку dic.products_file на движке File —
намеренное усложнение ради урока: в бою источник словаря приезжает процессом.
Историзацию и представление «последняя загрузка» из промышленного образца не
брали: история каталога — это git.
Источник объявлен формой query, а не table: словарь приводит цену из целых
копеек каталога в Decimal(18, 2), то есть нормализует на входе. Разрыв с productPrice события, где цена уже в целых рублях, остаётся намеренным — на
нём стоит урок про Float64.
Проверено на собранном заново стенде
make clean && make up — зелено; make smoke — 20 проверок, 0 ошибок; make lint — чисто.
Решает развилку #105: где живут справочники ClickHouse и нужно ли одно правило
для всех.
## Решение
Справочные данные — самостоятельная зона `dic` вне цепочки STG → ODS → DDS → DM.
Читать её вправе любой слой, писать — никто, кроме владельца источника.
`dds.products` переехал в `dic.products`.
Веер строился до оценки и включал все варианты, названные в тикете, плюс три,
оспаривающие саму рамку «база выражает принадлежность». Отвергнутые записаны с
причинами в [ADR 0012](../src/branch/feat/105-dictionary-home/docs/adr/0012-dictionary-home.md).
## Устройство
Словарь читает не файл, а подложку `dic.products_file` на движке `File` —
намеренное усложнение ради урока: в бою источник словаря приезжает процессом.
Историзацию и представление «последняя загрузка» из промышленного образца не
брали: история каталога — это git.
Источник объявлен формой `query`, а не `table`: словарь приводит цену из целых
копеек каталога в `Decimal(18, 2)`, то есть нормализует на входе. Разрыв с
`productPrice` события, где цена уже в целых рублях, остаётся намеренным — на
нём стоит урок про `Float64`.
## Проверено на собранном заново стенде
- `make clean && make up` — зелено; `make smoke` — 20 проверок, 0 ошибок;
`make lint` — чисто.
- Словарь `LOADED`, 180 строк; цена `Decimal(18, 2)`, на копейках `188990 → 1889.90`.
- `bi` читает словарь `dictGet`-ом со второй ноды, `analyst` — подложку
соединением; база `dds` пуста.
- Подложка перечитывает файл на каждом запросе, словарь обновляется сам внутри
окна `LIFETIME` — замер поймал изменение через 116 секунд.
- Минимальное право на движок замерено тремя пользователями: достаточно
`GRANT FILE ON *.*`, хотя текст отказа называет `TABLE ENGINE ON File`.
## Побочно
Замер вскрыл, что правка файлов настройки ClickHouse не доезжает до живого
контейнера — заведено отдельным багом #106, в этот PR не входит.
Closes #105
Зачем: место словаря в dds было унаследовано от первого объекта, а не решено.
Справочник читают несколько слоёв, а производит его в хранилище ни один —
прописка внутри одного из потребителей приписывала DDS владение, которого у
него нет.
Что: заведена база dic вне цепочки STG → ODS → DDS → DM, dds.products переехал
в dic.products. Под словарём появилась подложка dic.products_file на движке
File — намеренное усложнение ради урока: в бою источник словаря приезжает
процессом, а не лежит файлом у сервера. Источник объявлен формой query и
приводит цену из целых копеек каталога в Decimal(18, 2), как у денег бэкенда.
Обновление — окном LIFETIME(MIN 60 MAX 90) вместо ручной перезагрузки, ценой
заявленной неатомарности между нодами. У словаря свой беспарольный
пользователь dict с единственным правом на чтение dic. Суффикс _file добавлен
в конвенцию имён ADR 0006. Решение, отвергнутые варианты и условия пересмотра
— ADR 0012.
Проверка: make clean && make up на собранном заново стенде — зелено, make smoke
20 проверок и 0 ошибок, make lint чисто. Словарь LOADED со 180 строками, цена
Decimal(18, 2) и точна на копейках: 188990 → 1889.90. Пользователь bi читает
словарь dictGet-ом со второй ноды, analyst — подложку соединением, база dds
пуста. Минимальное право на движок замерено тремя пользователями: достаточно
GRANT FILE ON *.*, хотя отказ называет TABLE ENGINE ON File.
Closes#105
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем: каждое утверждение о словаре было записано трижды — в доке хранилища, в
комментариях DDL и в ADR 0012. Правка поведения стоила бы трёх согласованных
правок, а расхождение между копиями обнаружилось бы не сразу. Дока хранилища —
карта, а не пересказ реализации.
Что: раздел «Справочники» сведён к своему уровню — правило принадлежности зоны,
топология на кластере, единицы денег и указатели. Механика (движок, форма пути,
пользователь, окно обновления) осталась только в sql/ddl/05-dic-catalog.sql,
рядом с кодом, который она объясняет. Блок «Что проверено» отправлен к замерам
ADR 0012 вместо их пересказа — так же, как он уже поступает с ADR 0005.
Проверка: минус 30 строк; ссылок на убранный подзаголовок в репозитории нет,
три относительные ссылки нового текста разрешаются в существующие файлы.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем: горячее ревью поймало ошибку в трёх местах сразу. Было записано, что
после правки каталога ноды расходятся до тридцати секунд — число взято из
ширины окна LIFETIME(MIN 60 MAX 90). Ширина тут ни при чём: каждая нода ждёт
правки от нуля до верхней границы окна, фазы у них независимы, поэтому
расходиться они могут почти на все полторы минуты.
Что: исправлены ADR 0012, опорная точка мастер-спеки и комментарий DDL. Заодно
уточнено, что LIFETIME(0) неатомарность не предотвращал, а сжимал до разброса
исполнения SYSTEM RELOAD DICTIONARY ON CLUSTER, и что витрина выручки пока
спроектирована, а не построена.
Проверка: рассуждением, замером не подтверждалось — прежнее число тоже было
выведено, а не измерено. Замер в ADR (116 секунд на окне MIN 60 MAX 120)
относится к другому утверждению: что словарь обновляется сам.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Зачем: ревью в три линии нашло настоящий дефект. Девятая проверка кластера
звала dictGet('dds.products', …) — объекта после переноса не существует, и
make check-clickhouse падал. Промах вырос из недосчёта: упоминания dds.products
я искал с фильтром по расширениям, .sh туда не попал, и в ADR уехало «четыре
упоминания» вместо семи.
Что: проверка переведена на dic.products и сверяет цену, умножив её обратно на
сто, — так утверждается ещё и точность приведения к Decimal. Раздел 3
мастер-спеки и список пользователей README догнали перенос: оба описывали
отменённое устройство. В ADR 0012 добавлено условие пересмотра для дома — для
него его не было, хотя ради дома тикет и заводился; недосчёт записан в
«Что проверено» как урок. Разнобой обозначений сведён: карта таблиц в доке
хранилища перешла на имена баз строчными, таблица мастер-спеки — на заголовок
«Где», зону всюду зовут зоной, а не слоем. Термин «Справочник» переписан без
метафоры и уложен в формат глоссария. Вычтено лишнее: комментарии DDL
сократились вдвое, из ADR 0006 и 0007 убраны самооправдание и дублирующие
абзацы, отраслевой образец получил честную оговорку о непроверяемости.
Проверка: make config-test, make lint, make smoke и make check-clickhouse —
все зелёные, десять проверок кластера из десяти.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ddmitry
merged commit 7b89ccb529 into main2026-08-20 12:26:41 +03:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Решает развилку #105: где живут справочники ClickHouse и нужно ли одно правило
для всех.
Решение
Справочные данные — самостоятельная зона
dicвне цепочки STG → ODS → DDS → DM.Читать её вправе любой слой, писать — никто, кроме владельца источника.
dds.productsпереехал вdic.products.Веер строился до оценки и включал все варианты, названные в тикете, плюс три,
оспаривающие саму рамку «база выражает принадлежность». Отвергнутые записаны с
причинами в ADR 0012.
Устройство
Словарь читает не файл, а подложку
dic.products_fileна движкеFile—намеренное усложнение ради урока: в бою источник словаря приезжает процессом.
Историзацию и представление «последняя загрузка» из промышленного образца не
брали: история каталога — это git.
Источник объявлен формой
query, а неtable: словарь приводит цену из целыхкопеек каталога в
Decimal(18, 2), то есть нормализует на входе. Разрыв сproductPriceсобытия, где цена уже в целых рублях, остаётся намеренным — нанём стоит урок про
Float64.Проверено на собранном заново стенде
make clean && make up— зелено;make smoke— 20 проверок, 0 ошибок;make lint— чисто.LOADED, 180 строк; ценаDecimal(18, 2), на копейках188990 → 1889.90.biчитает словарьdictGet-ом со второй ноды,analyst— подложкусоединением; база
ddsпуста.окна
LIFETIME— замер поймал изменение через 116 секунд.GRANT FILE ON *.*, хотя текст отказа называетTABLE ENGINE ON File.Побочно
Замер вскрыл, что правка файлов настройки ClickHouse не доезжает до живого
контейнера — заведено отдельным багом #106, в этот PR не входит.
Closes #105
Зачем: ревью в три линии нашло настоящий дефект. Девятая проверка кластера звала dictGet('dds.products', …) — объекта после переноса не существует, и make check-clickhouse падал. Промах вырос из недосчёта: упоминания dds.products я искал с фильтром по расширениям, .sh туда не попал, и в ADR уехало «четыре упоминания» вместо семи. Что: проверка переведена на dic.products и сверяет цену, умножив её обратно на сто, — так утверждается ещё и точность приведения к Decimal. Раздел 3 мастер-спеки и список пользователей README догнали перенос: оба описывали отменённое устройство. В ADR 0012 добавлено условие пересмотра для дома — для него его не было, хотя ради дома тикет и заводился; недосчёт записан в «Что проверено» как урок. Разнобой обозначений сведён: карта таблиц в доке хранилища перешла на имена баз строчными, таблица мастер-спеки — на заголовок «Где», зону всюду зовут зоной, а не слоем. Термин «Справочник» переписан без метафоры и уложен в формат глоссария. Вычтено лишнее: комментарии DDL сократились вдвое, из ADR 0006 и 0007 убраны самооправдание и дублирующие абзацы, отраслевой образец получил честную оговорку о непроверяемости. Проверка: make config-test, make lint, make smoke и make check-clickhouse — все зелёные, десять проверок кластера из десяти. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>