Files
transcriber/CLAUDE.md
T
av a4646c0930 Инструкции для Claude, конфиг линтера, актуализация README
CLAUDE.md описывает конвейер задач, подвохи конфига и правило про четыре
списка колонок в репозитории sqlite.

.golangci.yml включает стандартный набор плюс errorlint; осознанные
непроверенные вызовы вынесены в исключения.

README приведён к коду: эндпоинты /api/audio и /api/status/:id, состояния
задач, структура internal/, фактические колонки таблиц.
2026-08-10 20:24:30 +03:00

5.9 KiB
Raw Blame History

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: createdconvertedtranscribedone / 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_.