errors

package
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ReasonInvalidResourceID — sync-формат: malformed own-id, отвергнутый
	// первым стейтментом RPC.
	ReasonInvalidResourceID = Reason{/* contains filtered or unexported fields */}

	// ReasonResourceNotFound — direct-read: own-owned id корректен, строки в
	// своей БД нет.
	ReasonResourceNotFound = Reason{/* contains filtered or unexported fields */}

	// ReasonPeerResourceMissing — peer-validate: чужой id не существует у
	// владельца. Код — FAILED_PRECONDITION: консумер здесь не «не нашёл своё»,
	// а «предусловие на чужой ресурс не выполнено».
	ReasonPeerResourceMissing = Reason{/* contains filtered or unexported fields */}

	// ReasonPeerResourceState — peer-validate: чужой ресурс есть, состояние не
	// позволяет.
	ReasonPeerResourceState = Reason{/* contains filtered or unexported fields */}

	// ReasonPeerUnavailable — peer-validate: владелец недоступен. Fail-closed
	// для мутаций — непроверяемое предусловие не считается выполненным.
	ReasonPeerUnavailable = Reason{/* contains filtered or unexported fields */}
)

Пять полос закрытого словаря. Шестой нет и не может быть заведена снаружи; добавление шестой здесь роняет TestLaneDictionaryIsClosedAtFive, который требует объявить её контрактом, а не просто вписать значение.

Каждое значение — конструктор ошибок своей полосы: `ReasonX.Errf(...)`. Отдельных функций-конструкторов на полосу нет намеренно — три из пяти полос сегодня не имеют производителя в дереве, и такие функции были бы мёртвым кодом (ban #11), тогда как сам ЗАКРЫТЫЙ НАБОР мёртвым не бывает: он и есть то, что запрещает шестую.

#nosec G101 -- ВСЕ ПЯТЬ токенов ниже суть МАШИННЫЙ ПРИЗНАК ПОЛОСЫ ОТКАЗА, уезжающий клиенту в деталях ответа, а не секрет. Эвристика статического анализа ключуется на форме имени — заглавные с подчёркиваниями рядом со строковым литералом — и не различает токен публичного контракта от учётных данных. Обоснование стоит здесь, у ГРУППЫ, а не построчно: предмет у всех пяти один, и построчные пометки закрывали бы по одной, оставляя следующую находкой при каждом добавлении полосы.

Functions

This section is empty.

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder — строитель gRPC-статуса с деталями.

func Aborted

func Aborted(msg string) *Builder

Aborted создает ошибку 409 (операция прервана, требует повтора).

func AlreadyExists

func AlreadyExists(k, id string) *Builder

AlreadyExists создает ошибку 409.

func FailedPrecondition

func FailedPrecondition(msg string) *Builder

FailedPrecondition создает ошибку 400 (предусловие не выполнено).

func Internal

func Internal(msg string) *Builder

Internal создает ошибку 500.

func InvalidArgument

func InvalidArgument() *Builder

InvalidArgument создает ошибку 400, к которой можно добавить FieldViolation.

func NotFound

func NotFound(kind, id string) *Builder

NotFound создает ошибку 404 с ResourceInfo detail.

Текст сообщения: `<Kind> '<id>' was not found`. Используется resource-manager (Cloud, Folder, Organization).

func Unavailable

func Unavailable(msg string) *Builder

Unavailable создает ошибку 503.

func (*Builder) AddFieldViolation

func (b *Builder) AddFieldViolation(field, desc string) *Builder

AddFieldViolation добавляет нарушение поля к BadRequest details.

func (*Builder) Err

func (b *Builder) Err() error

Err собирает итоговую ошибку с деталями (BadRequest, опционально LocalizedMessage).

LocalizedMessage добавляется ТОЛЬКО если был вызван WithLocale("<locale>") с непустым locale. По умолчанию Kachō возвращает только BadRequest — осознанное решение (более structured, machine-readable).

func (*Builder) WithLocale

func (b *Builder) WithLocale(locale string) *Builder

WithLocale устанавливает locale для LocalizedMessage detail. При Err() добавится detail вида:

{ "@type": "type.googleapis.com/google.rpc.LocalizedMessage", "locale": "<locale>", "message": "<status.message>" }

Если locale пустой — LocalizedMessage не добавляется.

type PeerRef

type PeerRef struct {
	Service      string
	ResourceType string
	ResourceID   string
}

PeerRef — координата ресурса, о котором отказ.

Service — имя сервиса-источника отказа («vpc»), из которого собирается ErrorInfo.domain вида "<service>.kacho.cloud".

ResourceID пуст там, где полоса намеренно не подтверждает существование чужого ресурса (анти-oracle). Пустое значение НЕ едет в метаданные пустой строкой: ключ с пустым значением читается как «идентификатор известен и пуст», то есть сообщает ровно то, что скрытие и должно было закрыть.

type Reason

type Reason struct {
	// contains filtered or unexported fields
}

Reason — машинный признак полосы резолва, по которому клиент отличает «я не нашёл СВОЁ» от «предусловие на ЧУЖОЙ ресурс не выполнено», не разбирая прозу сообщения (api-conventions.md §By-lane code-split).

Почему тип, а не строка

Токен, переданный строкой, выразим любой: шестая полоса заводится опечаткой и доезжает до клиента молча, потому что клиент ключуется на равенство и просто не совпадёт — то есть отказ будет выглядеть как отсутствие признака. Поля здесь неэкспортируемые, поэтому за пределами пакета собрать значение с произвольным токеном НЕЛЬЗЯ: словарь закрыт компилятором, а не соглашением.

Почему код лежит ВНУТРИ полосы

Токен и код — две половины одного утверждения о полосе. Разъехавшись, они дают худший из возможных исходов: ответ, который машинно заявляет одну полосу, а кодом — другую. Держать их вместе значит сделать расхождение невыразимым, а не обнаруживаемым. Отсюда же следует, что смена канона полосы — правка ОДНОЙ строки здесь, а не тринадцати мест в сервисах.

func AllReasons

func AllReasons() []Reason

AllReasons возвращает словарь полос целиком. Нужен проверкам, утверждающим свойство НАБОРА (закрытость, отсутствие дублей), — без него они перечисляли бы полосы вручную и молчали бы ровно о той, которую забыли дописать.

func (Reason) Code

func (r Reason) Code() codes.Code

Code — gRPC-код полосы.

func (Reason) Errf

func (r Reason) Errf(ref PeerRef, format string, a ...any) error

Errf собирает отказ этой полосы: код берётся у полосы, проза — у вызывающего, машинный признак уезжает в details.

Проза НЕ выводится из полосы и не дополняется ею. Тексты — часть контракта Kachō и принадлежат вызывающему; полоса добавляет к сказанному только машинный признак, по которому клиент отличает «повтори позже» от «исправь ввод», не парся сообщение. Детали не влияют на HTTP-статус края (grpc-gateway отображает по КОДУ), поэтому постановка признака ничего не ломает у REST-клиента.

Необъявленная полоса (нулевое значение) отдаёт INTERNAL без деталей: отказ, у которого нет полосы, не вправе притвориться полосой контракта.

func (Reason) IsDeclared

func (r Reason) IsDeclared() bool

IsDeclared отличает полосу словаря от нулевого значения типа. Нулевое значение собрать можно (`var r Reason`) — Go этого не запрещает; значимо то, что оно НЕ выдаёт себя за полосу контракта.

func (Reason) String

func (r Reason) String() string

String — реализация fmt.Stringer, чтобы полоса читалась в логах именем, а не раскладкой структуры.

func (Reason) Token

func (r Reason) Token() string

Token — машинный признак полосы, как он уезжает в google.rpc.ErrorInfo.reason.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL