Инструкции для Claude, конфиг линтера, актуализация README
CLAUDE.md описывает конвейер задач, подвохи конфига и правило про четыре списка колонок в репозитории sqlite. .golangci.yml включает стандартный набор плюс errorlint; осознанные непроверенные вызовы вынесены в исключения. README приведён к коду: эндпоинты /api/audio и /api/status/:id, состояния задач, структура internal/, фактические колонки таблиц.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# 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.
|
||||
|
||||
## Команды
|
||||
|
||||
```bash
|
||||
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_`.
|
||||
Reference in New Issue
Block a user