доменные ошибки сравниваются через errors.As, отказ Close не теряется
- признаки «работы нет» и «задача не найдена» узнаются по смыслу, а не приведением типа: обёртка `%w` на пути больше не превращает пустой прогон воркера в отказ раз в секунду - отказ закрытия соединения с распознавателем доходит до вызывающего (`errors.Join`) либо до журнала; у `errcheck` включён `check-blank`, иначе критерий принимал реализацию, выбрасывающую отказ в пустоту - заведены первые тесты пакета worker и capability `pipeline`; долг из четырёх замечаний линтера закрыт, гейт зелёный целиком
This commit is contained in:
@@ -22,6 +22,7 @@ SpeechKit, Yandex Object Storage и `ffmpeg`. Мерить нужно то, чт
|
||||
|
||||
| Дата | Запись | О чём |
|
||||
| --- | --- | --- |
|
||||
| 2026-08-11 | [gRPC-клиент SpeechKit: когда закрытие вообще может отказать](grpc-client-close.md) | Ленивое соединение и два исхода `Close` в grpc v1.74.2 |
|
||||
| 2026-08-11 | [Фреймворк приложения: Svelte, Vue и React на одном экране](spa-framework.md) | Размер собранной статики, цена шага сборки, что у трёх кандидатов одинаково |
|
||||
| 2026-08-11 | [Очередь задач: своя таблица против готовой библиотеки](job-queue.md) | Цена River и goqite в пакетах, захват одним запросом, чего нет для PocketBase |
|
||||
| 2026-08-11 | [PocketBase: что даёт панель администратора](pocketbase.md) | Записи, пользователи и файлы в панели версии 0.39.10 |
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# 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` надо перечитать, а не считать его прежним.
|
||||
Reference in New Issue
Block a user