Files
transcriber/docs/database.md
T
av 4d1c2bf44c Канон документов, каталог задач и OpenSpec
docs/ по канону 12: паспорт с целью проекта, архитектура сегодняшнего
устройства, схема хранилища, модель угроз, конвенции кода, журнал ревью.
Конвенции перенесены из jellybit; места, где код им не следует, помечены
строкой «Расхождение» как объявленный долг.

tasks/ с роадмапом: две достигнутые цели, две запланированные (веб и
многопользовательский режим), два направления (все форматы, долгие
записи) и пять задач в беклоге.

openspec/config.yaml — маршрутизатор с адресами документов, спек пока нет.

CLAUDE.md переписан по форме канона: инварианты с severity, семантика
гейта, запреты с путями. Taskfile получил task gate.
2026-08-10 21:19:07 +03:00

7.2 KiB
Raw Blame History

Схема хранилища

СУБД, миграции, правило времени и идентификаторов.

СУБД — SQLite, драйвер mattn/go-sqlite3 (нужен CGO). Запросы строит doug-martin/goqu с диалектом sqlite3. Миграции — pressly/goose, каталог migrations/, вшит в бинарник через //go:embed migrations/*.sql в main.go и накатывается при старте. Новый файл достаточно положить в каталог.

Идентификаторы — UUID v4 строкой.

Время — локальная зона процесса, UTC не навязан. Колонки created_at и updated_at проставляет приложение, а не СУБД; умолчание CURRENT_TIMESTAMP стоит только у files.created_at.

Того, что единой точки генерации идентификатора и времени нет, здесь не повторяем: перечень единых точек и их отсутствий держит architecture.md, «Единые точки проекта».

Переход на PocketBase запланирован, но не начат — здесь описано сегодняшнее состояние. Открытые вопросы перехода — в architecture.md, раздел «Открытые вопросы».

Таблицы

files

Один файл на одну физическую копию: исходник, результат конвертации и копия в Object Storage — три разные записи.

Колонка Тип Что
id TEXT PK UUID файла
storage TEXT local или s3
file_name TEXT Имя в хранилище: UUID с расширением
size INTEGER Размер в байтах
created_at DATETIME Умолчание CURRENT_TIMESTAMP

transcribe_jobs

Задача расшифровки и она же очередь.

Колонка Тип Что
id TEXT PK UUID задачи
state TEXT created, converted, transcribe, done, failed
source TEXT api, telegram, unknown; умолчание unknown
file_id TEXT FK → files.id Текущий файл задачи: шаг конвейера переставляет ссылку на свой результат
delay_time DATETIME Не брать задачу раньше этого времени
acquisition_id TEXT Кто захватил задачу
acquire_time DATETIME Когда захватил; по нему считается протухание
recognition_op_id TEXT Идентификатор операции в Yandex Cloud
transcription_text TEXT Результат распознавания
is_error BOOLEAN Задача с 1 из выборки исключена навсегда
error_text TEXT Текст ошибки, машинный
tg_chat_id INTEGER Куда отправить результат
tg_reply_message_id INTEGER С каким сообщением связать
created_at, updated_at DATETIME Проставляет приложение

Индексов, кроме первичных ключей, нет. Выборка воркера идёт полным перебором по state, is_error, delay_time и acquire_time.

Представление данных

Чем физически лежит запись и что происходит при чтении и записи.

  • Расшифровка лежит целиком в колонке transcription_text одной строкой. Запись длиной в час даёт десятки килобайт в одной ячейке; читается она целиком при каждом GetByID и при каждом захвате задачи воркером.
  • Аудио в базе не лежит. На диске — каталог data/files, плоский, имя файла равно UUID с расширением. Ни файлы, ни объекты в Object Storage не удаляются после завершения задачи: каталог и бакет растут неограниченно.
  • Захват задачи — два запроса подряд, не транзакция. Сперва UPDATE … WHERE id = (SELECT … LIMIT 1) проставляет acquisition_id, затем отдельный SELECT … WHERE acquisition_id = ? читает строку. Репозиторий сверяет число затронутых строк с ожидаемым, но между запросами задачу может перехватить другой воркер с тем же значением — на одном процессе это не наблюдалось.
  • Список колонок задан не одним местом — четырьмя запросами файла internal/adapter/repo/sqlite/transcript_job_repo.go. Правило правки всех четырёх и его severity — инвариант в CLAUDE.md, «Инварианты».

Настройки с числовым значением

Настройка Значение Где
Срок захвата, конвертация и распознавание 1 час service/transcribe.go, вызовы findJob
Срок захвата, проверка операции 24 часа там же
Пауза воркера между попытками 1 секунда controller/worker/worker.go
Задержка перед первой проверкой операции 10 секунд service/transcribe.go
Задержка между проверками операции 5 секунд там же
Предел длины сообщения Telegram 4000 символов adapter/telegram/sender.go
Память под multipart-загрузку 32 МиБ main.go, router.MaxMultipartMemory
Таймаут мягкой остановки 5 секунд конфиг, [server] shutdown_timeout
Таймаут жёсткой остановки 20 секунд конфиг, [server] force_shutdown_timeout
Таймаут обновлений Telegram 10 секунд конфиг, [telegram] update_timeout
Качество кодирования vorbis -q:a 4 adapter/converter/ffmpeg/ffmpeg.go

Чего среди настроек нет: режим журналирования SQLite не задан (значение по умолчанию, не WAL), таймаут занятости не задан, размер пула соединений не задан, срока хранения файлов и объектов нет вовсе. Таймаутов у обращений к Telegram, S3 и SpeechKit тоже нет — ни одного.