# gRPC-клиент SpeechKit: когда закрытие вообще может отказать

Отвечает на вопрос, возникший по ходу задачи `errors-as-instead-of-typecast`: что
означает отказ `Close` у клиента SpeechKit и стоит ли писать его в журнал.
Наблюдение понадобилось потому, что первая редакция кода и обоснования описывала
этот отказ неверно — как признак недоступности Yandex.

## Как снималось

Не замером, а **чтением исходников** зависимости, зафиксированной в `go.mod`:
`google.golang.org/grpc` версии **v1.74.2**. Смотрел два места в
`clientconn.go` — конструктор клиента и метод `Close`. К Yandex ни разу не
обратился: ни на живых ключах, ни на тестовых.

## Что выяснилось

- **`grpc.NewClient` соединения не открывает.** Клиент создаётся в состоянии
  ожидания, сеть трогается при первом вызове (`clientconn.go:145`). То есть на
  пути отказа конструктора — когда первый клиент создан, а второй нет — закрывать
  ещё нечего.
- **`(*ClientConn).Close` возвращает ровно два исхода** (`clientconn.go:1142-1156`):
  `nil` либо `ErrClientConnClosing` — `codes.Canceled`, «grpc: the client
  connection is closing» (`clientconn.go:67`). Второй наступает **только при
  повторном закрытии** уже закрытого клиента.

## Что из этого следует для нас

Отказ `Close` в этом проекте означает **нашу ошибку — закрыли дважды**, а не сбой
или недоступность Yandex. Поэтому запись в журнале при остановке процесса
адресует владельца к нашему коду; так она и сформулирована.

Обработка отказа при этом оставлена в обоих местах, хотя сегодня он практически
недостижим: она стоит одну строку и переживёт смену клиента, а её отсутствие
пришлось бы обосновывать заново каждому читателю. Решение и его цена —
[ADR](../adr/ADR-2026-08-11-errcheck-check-blank.md), обоснование целиком — в
архивном
[design.md](../../openspec/changes/archive/2026-08-11-errors-as-instead-of-typecast/design.md),
Решение 2.

**Наблюдение привязано к версии.** Сменится мажорная версия `grpc` — перечень
исходов `Close` надо перечитать, а не считать его прежним.
