docs(opus): ответы №3 (граница lib/GenModifier, pre-check в core, частичный inverse)
This commit is contained in:
@@ -191,3 +191,58 @@ idle? нет → wait, re-read
|
|||||||
иначе → reconcile (полный payload)
|
иначе → 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