docs(63): правки по двум холодным ревью реализации

- Зачем:
  - линия дефектов нашла три неверных утверждения и мёртвый замер, линия
    уместности — три пересказа уже сказанного.
- Что:
  - «тип колонки не решает, какое число ляжет» сужено до правды: разбор
    отдаёт готовое число, а пояс приёмника решал бы судьбу строки.
  - замер до правки типов помечен как неповторяемый на нынешнем стенде.
  - правило о поясе сервера привязано к местам, где линза что-то решает:
    матвью приёма пояс не называет, и это не нарушение.
  - убраны: пересказ механики в ADR 0005, четыре строки учебного
    комментария, утверждение о порядке файлов и «секунды от начала эпохи»
    у миллисекундной метки.
- Проверка:
  - make lint, make typecheck, make test (408 тестов)
  - make clean && make up && make check-clickhouse — 9 из 9

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-08 19:44:53 +03:00
co-authored by Claude Opus 5
parent d67e697821
commit 359570ec65
5 changed files with 25 additions and 24 deletions
+12 -8
View File
@@ -153,11 +153,12 @@ Greenplum, чтобы словарь был общим у двух хранил
какие сутки оно попадёт.
**Линза называется явно — в типе колонки либо в вызове функции.** Третий
источник, умолчание сервера, в коде не виден и меняется снаружи, поэтому в DDL
и запросах его не остаётся. Прописать этот пояс своей рукой — `<timezone>` в
конфигурации ноды или `TZ` контейнеру — было бы той же болезнью с другим
умолчанием, и вдобавок отняло бы проверку: когда линза названа в типах и в
разборе, пояс сервера на данные не влияет нигде, и в этом можно убедиться,
источник, умолчание сервера, в коде не виден и меняется снаружи, поэтому там,
где линза что-то решает — в объявлении хранимой колонки и в выражении,
считающем дату, — его не остаётся. Прописать этот пояс своей рукой —
`<timezone>` в конфигурации ноды или `TZ` контейнеру — было бы той же болезнью
с другим умолчанием, и вдобавок отняло бы проверку: когда линза названа в типах
и в разборе, пояс сервера на данные не влияет нигде, и в этом можно убедиться,
поменяв его. Правило стоит на источнике пояса, а не на функции:
`toDate` по колонке, чей тип пояс несёт, законен и имени не требует — так и
работают ключи партиций `toDate(_load_ts)` у сырья и у таблицы ошибок. Имя
@@ -182,8 +183,9 @@ UTC+4), и пересчёт идёт один раз при наполнении
метку или свести её к дате. На записи — превратить строку в число: суффикс `Z`
на проводе зоны не даёт, маска разбора съедает его буквой, и
`parseDateTimeOrNull` без третьего аргумента трактует показания часов по поясу
сессии, а тот по умолчанию серверный. Тип колонки тут не помогает: он про то,
как число читают, а не про то, какое ляжет. Механика и выбор функции — [ADR
сессии, а тот по умолчанию серверный. Тип колонки тут не помогает: разбор
отдаёт готовое число, и колонка кладёт его как есть — пояс приёмника решал бы
судьбу строки, а не числа. Механика и выбор функции — [ADR
0005](../adr/0005-event-ingestion.md).
**День берётся из `EventDate`.** Дата в поясе счётчика уже посчитана
@@ -463,7 +465,9 @@ ODS. Второе: матвью приёма создаётся последне
- `toDate` берёт пояс у типа своего аргумента. Из одного момента:
по `DateTime('UTC')``2026-05-31`, по `DateTime('Europe/Samara')`
`2026-06-01`. Отсюда форма правила: имя пояса нужно там, где его не несёт тип.
- У колонки без объявленного пояса глаз и `GROUP BY` расходятся. Событие
- У колонки без объявленного пояса глаз и `GROUP BY` расходятся. Замер снят до
правки типов и на нынешнем стенде не повторяется — колонка уже с поясом.
Событие
`WatchID = 113504893317`, `EventDate` = `2026-06-05`: без настроек колонка
показана `2026-06-04 20:58:56`, под `session_timezone = 'Europe/Samara'`
`2026-06-05 00:58:56`, а `toDate(UTCEventTime)` в обоих случаях