- 13 конвенций по осям arch / lang / stack / common; репозитории берут оттуда копии в свой docs/conventions/ и коммитят их у себя - conv — синхронизация копий: add / status / diff / pull / push, локальные регионы исключены из сравнения, поэтому расхождение не даёт шума
51 lines
3.0 KiB
Markdown
51 lines
3.0 KiB
Markdown
---
|
|
status: рекомендуемая
|
|
extends: arch/db-identifiers.md
|
|
---
|
|
|
|
# Идентификаторы: реализация на Go
|
|
|
|
Как `arch/db-identifiers.md` выглядит в Go-приложении, выбравшем ULID.
|
|
|
|
## Единая точка — `internal/ident`
|
|
|
|
- `ident.NewID()` — генерация. **PK сущности** генерируется в `Create`-методах
|
|
слоя `store`. Прочие идентификаторы (батч, задание, корреляционный ключ)
|
|
генерируются там, где начинается операция, — но тоже только через `ident`.
|
|
- `ident.NewIDAt(t)` — генерация с заданным временем, для бэкфилла в
|
|
Go-миграциях: сортировка id тогда сохраняет историческую хронологию, а не
|
|
момент прогона миграции.
|
|
- `ident.Parse()` — разбор и нормализация; зовётся на **входных границах**
|
|
(HTTP-роут, форма, callback бота), до обращения к store.
|
|
- Других генераторов и парсеров id в коде нет. Это то самое «единая точка»
|
|
из базовой конвенции; без него нормализация регистра неизбежно
|
|
где-нибудь пропускается.
|
|
|
|
## Типы
|
|
|
|
В структурах store и домена id — обычный `string`. Отдельный тип `ID`
|
|
заводим, только если появится вторая семья идентификаторов, которую можно
|
|
перепутать; до этого он даёт конверсии без выгоды. От перепутывания двух id
|
|
одной семьи в сигнатуре он всё равно не спасает — там помогают имена
|
|
параметров.
|
|
|
|
## Невалидный id на границе
|
|
|
|
Разбор не удался — дальше зависит от того, откуда id пришёл:
|
|
|
|
- **из пути или query URL** — сразу 404, без обращения к store и без
|
|
фабрикации доменной ошибки: снаружи это неотличимо от несуществующей
|
|
записи, и хорошо;
|
|
- **из собственной формы или callback-данных кнопки** — 400 либо понятное
|
|
сообщение («кнопка устарела»): это баг интерфейса или протухший экран, и
|
|
под «не найдено» его маскировать нельзя.
|
|
|
|
Транспорт не создаёт доменные sentinel'ы, чтобы тут же их сматчить, — это
|
|
инверсия правила «трансляция у источника» из `lang/go/errors.md`.
|
|
|
|
<!-- local:механизировано -->
|
|
<!-- /local -->
|
|
|
|
<!-- local:отступления -->
|
|
<!-- /local -->
|