Добавил документацию и описание репозитория

This commit is contained in:
2026-06-13 17:10:53 +03:00
parent 82a81c16af
commit 5b53f4e8e8
12 changed files with 647 additions and 0 deletions
@@ -0,0 +1,53 @@
# Go и доставка одним бинарём
- Дата: 2026-06-13
## Контекст
Jellybit — новый сервис, который будет жить на домашнем медиа-сервере
umbar. Нужно выбрать язык и способ доставки. Силы и ограничения:
- Это домашняя лаборатория, хочется максимально простой доставки: собрал
здесь — скопировал готовый артефакт на сервер, без рантайма и лишних
зависимостей на самой машине.
- В umbar уже устоялось разделение: Python+uv используется вместе с
Ansible (инфраструктура), а не для прикладных сервисов.
- У автора уже есть несколько сервисов на Go — это знакомый и привычный
стек именно под сервисы.
- Сервису нужны: клиент qBittorrent, обращения к LLM, опц. клиенты
TMDB/TVDB, разбор имён релизов.
## Рассмотренные варианты
- **Go** — один статический бинарь (`CGO_ENABLED=0`), копируется на
сервер; минимальный docker-образ. Знакомый стек. Минус: нет хорошего
аналога питоновского `guessit` для разбора имён релизов.
- **Python + uv** — богатая экосистема распознавания (`guessit`), но
тянет рантайм и зависимости на сервер; в проекте уже занят инфра-ролью
при Ansible. Смешивать прикладной сервис с инфра-тулингом не хочется.
- **TypeScript / Node** — экосистема есть, но рантайм на сервере и не
основной стек автора для сервисов.
## Решение
Пишем jellybit на **Go**, доставляем одним статическим бинарём: сборка в
этом репозитории → готовый артефакт с нужной обвязкой копируется на
umbar. На сервере не нужны ни рантайм, ни менеджер пакетов.
Причина: при домашней лаборатории решающее — простота доставки и
знакомство со стеком, а не богатство библиотек распознавания. Слабость Go
в разборе имён релизов закрываем дешёвым `go-ptn` плюс основной разбор всё
равно делает LLM; при нехватке точности `guessit` можно завернуть лёгким
сервисом-спутником рядом с бинарём (тоже один файл). Python остаётся за
инфраструктурой (umbar, Ansible).
## Последствия
- `+` Доставка тривиальна: один файл, без рантайма и зависимостей на
сервере; минимальный docker-образ.
- `+` Стек знаком автору, переиспользуется опыт других Go-сервисов.
- `+` Чёткая граница: Go — прикладные сервисы, Python+uv — инфра.
- `-` Нет первоклассного `guessit`; точность пред-парса ниже. Митигация:
`go-ptn` + LLM, при необходимости — guessit-спутник.
- `-` Часть клиентов (например, TVDB v4) придётся писать руками — зрелых
готовых библиотек меньше, чем в Python.
+59
View File
@@ -0,0 +1,59 @@
# Architecture Decision Records (ADR)
Журнал значимых архитектурных решений по jellybit. Одна запись — одно
решение. ADR пишем **постфактум**, когда решение принято и зафиксировано
в коде/проекте: идеи и неподтверждённые планы живут в `docs/drafts`, а не
в ADR. Записи **неизменяемы**: передумали → не правим старую, заводим
новую и помечаем старую.
Главная ценность записи — сохранить **почему**: намерение и причинность.
Это важнее аккуратности оформления и полноты остальных секций.
Формат и процесс унаследованы от соседнего проекта umbar.
## Когда заводить ADR
- Выбор технологии или инструмента.
- Структурные решения (хранилище, организация компонентов, протоколы).
- Решения с долгосрочными последствиями или дорогим откатом.
- **Намеренный отказ** от очевидного подхода — чтобы потом не
переоткрывать «а почему мы не сделали X».
Не заводить для рутины (бамп версии зависимости, добавление эндпоинта по
накатанной схеме) и того, что и так видно из кода и git.
## Соглашения
- **Имя файла = идентификатор:** `ADR-ГГГГ-ММ-ДД-kebab-slug.md`.
Идентификатор — имя без `.md`. Slug — латиницей.
- **Дата** — когда решение реально принято.
- Несколько ADR за один день различаются по slug.
- **Заголовок в файле:** `# Человеческий заголовок` (без даты и ID — они
в имени файла и в строке «Дата»).
- Секция **«Рассмотренные варианты» — опциональна**: оставляй её, только
если альтернативы реально рассматривались.
- Шаблон новой записи — [`template.md`](template.md).
## Статусы
Активная запись статуса **не имеет**. Статус появляется, только когда
запись теряет силу, и значений всего два:
- `заменено на ADR-ГГГГ-ММ-ДД-slug` — решение пересмотрено новой ADR.
- `устарело` — решение потеряло смысл и замены нет.
## Замена и устаревание
1. Заводим новую ADR; в её «Контексте» — строка
«Заменяет ADR-ГГГГ-ММ-ДД-slug».
2. В старой ADR добавляем строку `- Статус: заменено на ADR-…` сразу под
датой. Тело не трогаем — это часть истории.
3. Обновляем статус старой записи в индексе ниже.
## Список записей
Новые сверху.
| Дата | Запись | Статус |
| ---------- | ---------------------------------------------------------------- | ------ |
| 2026-06-13 | [Go и доставка одним бинарём](ADR-2026-06-13-go-single-binary.md) | — |
+36
View File
@@ -0,0 +1,36 @@
# Краткий заголовок решения
- Дата: ГГГГ-ММ-ДД
<!-- Строку статуса добавляют позже, только если запись потеряла силу:
- Статус: заменено на ADR-ГГГГ-ММ-ДД-slug
- Статус: устарело
У активной записи строки статуса нет. -->
## Контекст
Что вынудило принять решение: проблема, силы и ограничения (ресурсы,
стоимость, время на поддержку, существующая архитектура). Пиши так, чтобы
через год было понятно «почему это вообще делалось» без чтения переписки.
## Рассмотренные варианты
<!-- Опциональная секция. Оставь, только если варианты реально
рассматривались. Если решение было единственным очевидным — удали
её, а причину объясни в «Решении». -->
- **Вариант A** — суть, плюсы и минусы.
- **Вариант B** — суть, плюсы и минусы.
- **Вариант C** — если отвергнут сразу, коротко почему.
## Решение
Что именно сделано и — главное — **почему**: какое намерение и какая
причина за этим стоят. Если варианты рассматривались — почему выбран
этот, а не остальные.
## Последствия
- `+` что стало лучше, какие возможности открылись.
- `-` чем платим: новые ограничения, риски, регулярная нагрузка на
поддержку.
- Что нужно сделать как следствие (если есть).