Добавил документацию и описание репозитория
This commit is contained in:
@@ -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.
|
||||
@@ -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) | — |
|
||||
@@ -0,0 +1,36 @@
|
||||
# Краткий заголовок решения
|
||||
|
||||
- Дата: ГГГГ-ММ-ДД
|
||||
<!-- Строку статуса добавляют позже, только если запись потеряла силу:
|
||||
- Статус: заменено на ADR-ГГГГ-ММ-ДД-slug
|
||||
- Статус: устарело
|
||||
У активной записи строки статуса нет. -->
|
||||
|
||||
## Контекст
|
||||
|
||||
Что вынудило принять решение: проблема, силы и ограничения (ресурсы,
|
||||
стоимость, время на поддержку, существующая архитектура). Пиши так, чтобы
|
||||
через год было понятно «почему это вообще делалось» без чтения переписки.
|
||||
|
||||
## Рассмотренные варианты
|
||||
|
||||
<!-- Опциональная секция. Оставь, только если варианты реально
|
||||
рассматривались. Если решение было единственным очевидным — удали
|
||||
её, а причину объясни в «Решении». -->
|
||||
|
||||
- **Вариант A** — суть, плюсы и минусы.
|
||||
- **Вариант B** — суть, плюсы и минусы.
|
||||
- **Вариант C** — если отвергнут сразу, коротко почему.
|
||||
|
||||
## Решение
|
||||
|
||||
Что именно сделано и — главное — **почему**: какое намерение и какая
|
||||
причина за этим стоят. Если варианты рассматривались — почему выбран
|
||||
этот, а не остальные.
|
||||
|
||||
## Последствия
|
||||
|
||||
- `+` что стало лучше, какие возможности открылись.
|
||||
- `-` чем платим: новые ограничения, риски, регулярная нагрузка на
|
||||
поддержку.
|
||||
- Что нужно сделать как следствие (если есть).
|
||||
Reference in New Issue
Block a user