tasks: заведены шесть задач из урожая ревью и переименования образца конфига

- пять из урожая change 2026-08-11-fix-http-handler-tests, тег review-2026-08-11;
  утечка имени файла в журнал поставлена первой строкой очереди
- опечатка transcibe дописана в json-api-for-spa: текст ошибки — часть
  необратимого контракта, и в одиночку он не правится
This commit is contained in:
av
2026-08-11 08:59:45 +03:00
parent 1bd6d03188
commit 2333e80633
8 changed files with 300 additions and 4 deletions
@@ -0,0 +1,61 @@
# 🐞 Убирать записанный файл, когда приём отказал на середине
- **Тип:** fix
- **Категория:** Очередь
- **Зачем:** Отказ чтения метаданных и отказ записи на диск оставляют файл в каталоге хранения без задачи и без учёта: сопоставить его не с чем, удалять приходится руками.
- **Теги:** review-2026-08-11
Приём пишет файл на диск, потом спрашивает у источника метаданных длительность,
потом заводит запись в учёте и задачу. Уборка при отказе есть **только на
последнем шаге**: отказ `fileRepo.Create` зовёт `os.Remove`, а отказы записи на
диск и чтения метаданных возвращают ошибку, оставляя файл лежать.
Сопоставить такой файл не с чем: записи в `files` под него нет, задачи нет,
имя — случайный идентификатор. На сервере это `data/files`, где лежат голосовые
сообщения живых людей, а проект по паспорту «не хранит записи как архив».
Найдено проходом `review-specs` ревью дизайна change
`2026-08-11-fix-http-handler-tests`; отчёт триажа —
`openspec/changes/archive/2026-08-11-fix-http-handler-tests/review/triage.md`.
Вынесено сюда решением человека на контрольной точке.
## Воспроизведение
Асимметрия видна в самом коде:
```
sed -n '110,160p' internal/service/transcribe.go
```
Ветка `fileRepo.Create` (строки 152–157) содержит `os.Remove(storageFilePath)` с
комментарием «Удаляем файл если не удалось создать запись в БД». Ветки
`io.Copy`, `dst.Close` и `metaviewer.GetInfo` (строки 116–133) возвращают ошибку
без уборки, хотя файл к этому моменту уже создан.
Прогоном: `TestCreateTranscribeJob_MetaViewerFailure` в
`internal/controller/http/transcribe_test.go` доводит приём до этой ветки —
после него в каталоге хранения лежит файл, а `countJobs` равен нулю.
## Затрагивает
- `internal/service/transcribe.go`, функция `createTranscribeJob` — три ветки
отказа между созданием файла и заведением записи в учёте;
- `internal/controller/http/transcribe_test.go` — случай отказа метаданных
получает проверку на отсутствие файла;
- раскладка `data/files` не меняется: имена и формат прежние.
## Критерии приёмки
- Отказ чтения метаданных не оставляет файла в каталоге хранения. Оракул — тест
на подставном источнике, возвращающем ошибку: каталог пуст после запроса.
- Отказ записи на диск на середине не оставляет частично записанного файла.
Оракул — тест с источником данных, обрывающимся на середине чтения.
- Уборка сама не заслоняет исходную ошибку: отправитель по-прежнему получает
отказ, а причина уезжает в журнал. Оракул — тот же тест, код ответа и запись в
перехваченном журнале.
## Рамки
Уборка файлов, осиротевших **до** этой правки, сюда не входит: их надо найти
сверкой каталога с учётом, и это отдельная работа с боевыми данными.