CLAUDE.md описывает конвейер задач, подвохи конфига и правило про четыре списка колонок в репозитории sqlite. .golangci.yml включает стандартный набор плюс errorlint; осознанные непроверенные вызовы вынесены в исключения. README приведён к коду: эндпоинты /api/audio и /api/status/:id, состояния задач, структура internal/, фактические колонки таблиц.
5.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Проект и общение по нему ведём по-русски.
Что это
Сервис расшифровки аудио. Два входа — Telegram-бот и HTTP API, один общий конвейер обработки. Распознавание асинхронное, через Yandex SpeechKit; файл едет в Yandex Object Storage, оттуда его забирает SpeechKit.
Команды
go build ./... # нужен CGO: mattn/go-sqlite3
go test ./...
go vet ./...
gofmt -l .
golangci-lint run
go run . -c config.toml # флаг -c или --config, по умолчанию config.toml
task image # docker-образ, тег из $BUILD_ID (по умолчанию dev)
golangci-lint run на чистом master даёт 4 замечания в существующем коде (два
непроверенных Close, два сравнения ошибок через приведение типа вместо
errors.As). Их пока не чинили — новые замечания отличай от этих.
Деплой запускается не отсюда, а из pet-project-server: inv pl -- transcriber.
Плейбук сам зовёт task image по контракту роли app_image, образ едет на сервер
через docker save/load, реестр не участвует.
lefthook на pre-commit гоняет gitleaks git --staged.
Конфиг
config.toml в gitignore, образец — config.dist.toml. Разбирается в
internal/config; значения по умолчанию заданы в defaultConfig(), файл их
перекрывает. Правишь поле — правь оба места.
Два подвоха:
- Ключ белого списка пользователей Telegram называется
users_while_list(опечатка в теге toml), лежит в секции[server], и вconfig.dist.tomlего нет вообще. Без него бот отвечает отказом всем. - Список сверяется с
update.Message.From.String()из tgbotapi — это@usernameлибо имя с фамилией, а не числовой id.
Конвейер задач
Состояния TranscribeJob: created → converted → transcribe → done / failed
(константы в internal/entity/job.go).
Три воркера в main.go крутят по одному шагу каждый, опрашивая базу раз в секунду:
conversion_worker (created → converted, ffmpeg в ogg), transcribe_worker
(converted → transcribe, заливка в S3 и старт распознавания), check_worker
(transcribe → done/failed, опрос операции Yandex).
Задача захватывается через FindAndAcquire: один UPDATE проставляет
acquisition_id, дальше строка читается по нему. Задача с истёкшим acquire_time
достаётся заново — час для конвертации и распознавания, сутки для проверки.
delay_time откладывает следующую попытку.
contract.NoopJobError — не ошибка, а «задач в этом состоянии нет». Воркер такой
случай не логирует и не считает в метрику. Возвращая ошибку из шага конвейера, не
теряй эту семантику.
Ошибку, после которой задачу нет смысла повторять, оформляй через failJob: он
переводит задачу в failed и сам шлёт человеку понятный текст в Telegram. Возврат
обычной ошибки оставляет задачу в текущем состоянии на повтор.
Слои
internal/entity — модели, internal/contract — интерфейсы и типы ошибок,
internal/service — конвейер, internal/controller/{http,tg,worker} — входы,
internal/adapter/* — реализации contract (ffmpeg, yandex, telegram, sqlite).
Сервис зависит только от интерфейсов contract; конкретные адаптеры собираются
в main.go.
База
Миграции goose в migrations/, вшиты в бинарник через //go:embed migrations/*.sql
в main.go и накатываются при старте. Новый файл достаточно положить в каталог,
регистрировать нигде не надо. Диалект — sqlite3.
Добавляя колонку, правь четыре места: миграцию, структуру в internal/entity,
и в internal/adapter/repo/sqlite — списки колонок в Create, Save, GetByID и
FindAndAcquire. Списки продублированы, компилятор расхождение не поймает.
Конвенции
- Коммиты прямо в
master, без веток и PR. - В сообщении коммита не ставить трейлер
Co-Authored-By. - Логи —
log/slog, структурные пары ключ-значение, логгер прокидывается конструктором.log.Printfвinternal/controller/http/transcribe.go— остаток, на него не равняться. - Текст, который увидит пользователь Telegram, — по-русски. Логи и комментарии в коде — как в соседних файлах.
- Метрики Prometheus объявляются в
internal/metricsс префиксомtranscriber_.