docs(opus): ответы №3 (граница lib/GenModifier, pre-check в core, частичный inverse)
This commit is contained in:
@@ -191,3 +191,58 @@ idle? нет → wait, re-read
|
||||
иначе → reconcile (полный payload)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Ответы Opus №3 (сверка с фактическим кодом, расхождения + сомнения)
|
||||
|
||||
## Факт №1: контракт — в lib, поведение — в GenModifier
|
||||
|
||||
Подтверждено: `delete_strategy`/`idempotency`/`delete_params` добавляются в
|
||||
**`lib.OperationSpec`** (`TOOLS/lib/types.go`), resource-generator получает через алиас
|
||||
(`types.go:19`). Ссылка «types.go:39» была неточной — канон в lib.
|
||||
|
||||
Граница:
|
||||
| Где | Что |
|
||||
|---|---|
|
||||
| `lib.OperationSpec` / `lib.ParamSpec` | всё из YAML, видно обоим генераторам |
|
||||
| `GenModifier` (локально) | производные для шаблона, флаги `Needs*`, готовый inverse-список |
|
||||
|
||||
Правило: парсится из YAML → lib; вычисляется загрузчиком для шаблона → GenModifier.
|
||||
|
||||
## Факт №2: pre-check — в `core` (вариант A), экспортировать сравнение
|
||||
|
||||
`normalizeUniversalValueV6` приватная и требует `universalCfsParam` — в `resources_core`
|
||||
этих данных нет. Pre-check делать **в `core`**, не в resources_core и не в шаблоне.
|
||||
|
||||
Конкретно — экспортированный метод в `core`, вызывается из `operation_run_bycode.go`
|
||||
сразу после `fetchOperationCfsParams`:
|
||||
```go
|
||||
func (c *UniversalClient) modifierDesiredEqualsCurrent(
|
||||
desired map[string]string, cfsParams []universalCfsParam) bool
|
||||
```
|
||||
Сравнение: нормализовать обе стороны через `normalizeUniversalValueV6`; для
|
||||
map-fixed/array-map-fixed — JSON-эквивалентность. Но `JSONStringsEquivalent` лежит в
|
||||
`resources_core` → импорт в `core` даст **цикл**. Вынести JSON-эквивалентность в
|
||||
нейтральный пакет (`core/jsonutil` или в сам `core`) и переиспользовать в обоих местах.
|
||||
|
||||
Вариант C (только `JSONStringsEquivalent` без нормализации) — **отклонён** (ложный diff
|
||||
`true`/`1`).
|
||||
|
||||
Управление: `RunInstanceOperationUniversalByCode` получает флаг `idempotent` (из
|
||||
`GenModifier.Idempotency` → шаблон → параметр вызова); idle-гейт выше pre-check.
|
||||
|
||||
## Дополнительные сомнения (ответы)
|
||||
|
||||
1. **Idempotency и полный payload НЕ конфликтуют** (разные уровни). Бинарно на весь
|
||||
модификатор: `ALL == ALL` → skip целиком; любое расхождение → полный payload.
|
||||
Полудельты нет.
|
||||
2. **Частичный inverse — допустим и правилен.** `delete_params` покрывает только
|
||||
обратимые поля; необратимые/constraint просто не входят. Fail-fast смягчить:
|
||||
ошибка не «inverse обязан покрыть всё», а «код в delete_params обязан существовать
|
||||
в params и value удовлетворять constraint». Delete при inverse = modify с
|
||||
delete_params + досылка live остальных (полный payload).
|
||||
3. **`noop_warn` дефолт — оставить, но критичные — вручную `error`.** Дефолт мягкий
|
||||
(`noop_warn`, всегда с `AddWarning`), а необратимые (`ip_space`) автор спеки явно
|
||||
помечает `delete_strategy: error` в YAML. Генератор сам не решает обратимо/необратимо.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user