5.1 KiB
2026-07-07 — Opus answers: duplicate/exist fix strategy
Контекст
Промпт из /home/naeel/tf_provider/prompt_for_opus_duplicate.md
После mutex (v5.0.63) pg_user_5 упал: «Операция вернула duplicate/exist, но объект не найден в state_out»
Корень всех проблем
Код путает два разных случая «не-found»:
known && !found— список в state_out ЕСТЬ, объекта нет → реальная несогласованность!known— списка в state_out НЕТ вообще (PostgreSQL, Kafka) → проверить невозможно
Сейчас !known трактуется как несогласованность → ошибка.
Вопрос 1 (ПРИОРИТЕТ) — ДА, доверять API при !known
Где: templates.go → генерится во все subresource Create
Фикс: усыновлять при found || !known, ошибку только для known && !found:
if adoptExistingOnCreate && resources_core.IsSubresourceAlreadyExistsError(createErr) {
found, known := false, false
if targetValue != "" {
var checkErr error
found, known, checkErr = resources_core.FindSubresourceInStateOut(ctx, r.client, instanceUID, listKey, idKey, targetValue)
if checkErr != nil {
resp.Diagnostics.AddError("Ошибка клиента", checkErr.Error())
return
}
}
// found → подтверждено в state_out
// !known → списка в state_out нет (PG/Kafka) → доверяем API
// known&&!found → реальная несогласованность
if found || !known {
plan.ID = types.StringValue(resources_core.BuildSubresourceID(instanceUID, "{{.SubName}}", idParams))
resp.Diagnostics.AddWarning("Подресурс усыновлён", "API вернул already exists; объект принят в state: "+targetValue)
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
return
}
resp.Diagnostics.AddError("Нарушена консистентность", "API вернул duplicate/exist, но объект подтверждённо отсутствует в state_out: "+targetValue)
return
}
Вопрос 2 — ДА, нужен явный маппинг из метаданных
Где: subresource_guard.go — SubresourceListKey (эвристика name+"s") и SubresourceIdentityKey (special-map на 2 сервиса)
Доказательство: Kafka — реальные ключи kafkaUsers/kafkaTopics, эвристика даёт users/topics → known=false даже когда данные есть.
Фикс: генератор должен эмитить явные listKey/idKey как константы из метаданных. Для сервисов без ключа в state_out (PostgreSQL) — эмитить listKey="" → FindSubresourceInStateOut → known=false → работает путь «доверять API» из Вопроса 1.
Вопрос 3 — НЕТ, list-эндпоинтов не существует
Проверено по API-метаданным (svc 90):
- Операции: create(19), delete(20), resume(114), suspend(115), recovery(47), modify(48), restart(54)
- Subresource: create_user(241), delete_user(244), create_database(245), delete_database(246)
- Ни одной
list_*/get_*/show_*
Перечислить подресурсы через API невозможно. Единственный источник — state_out, а у PG его нет.
Вывод: стратегия «доверять API» (Вопрос 1) — единственно возможная.
Вопрос 4 — Частично; текст ОК, нужен HTTP 409
Где: subresource_guard.go — IsSubresourceAlreadyExistsError
role "pg_user_5" already exists→ ловится ✅already exist(без s), голыйexist→ НЕ ловится- Главная дыра: HTTP 409 без текста → НЕ ловится
Фикс:
markers := []string{"уже существует", "already exists", "already exist", "duplicate", "conflict", " exist"}
Плюс проверка HTTP 409 (требует проброса статус-кода из клиента).
Приоритет реализации
- Вопрос 1 — чинит
pg_user_5сразу - Вопрос 2 — чинит Kafka и остальные
- Вопрос 4 — устойчивость к формулировкам
- Вопрос 3 — документировать как «невозможно, дизайн-решение»
Всё правится в шаблоне templates.go и subresource_guard.go. Сгенерированные файлы НЕ править — перегенерировать.
Дата: 2026-07-07 Статус: анализ завершён, правки НЕ внесены