Воркер ведёт in-memory снимок телеметрии раздач (прогресс, скорость, ETA, рейтинг, сиды/пиры, отдано) под отдельным RWMutex, обновляя его на каждом тике поллинга сразу после построения byHash — без лишних вызовов qBittorrent и без хранения в БД (волатильно). qbt.Torrent дополнен полями телеметрии. Веб-UI читает снимок через узкий контракт LiveStatus: карточки активных загрузок показывают живой прогресс-бар (htmx-поллинг фрагмента every 3s, точечно — без сброса фильтров), на странице загрузки появилась секция «Раздача» для сидирующих задач. Начальный кадр рендерится сразу со значениями; при отсутствии данных UI деградирует штатно. Капабилити live-status (OpenSpec), web-ui дополнен. Change заархивирован. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.2 KiB
5.2 KiB
1. Телеметрия в клиенте qBittorrent
- 1.1 Добавить в
qbt.TorrentполяDlspeed,Eta,Ratio,NumSeeds,NumLeechs,Uploaded,Upspeedс json-тегами из/torrents/info(dlspeed,eta,ratio,num_seeds,num_leechs,uploaded,upspeed) - 1.2 Обновить комментарий-доку
Torrent(подмножество полей расширено)
2. Снимок телеметрии в воркере
- 2.1 Добавить тип
worker.Live{Progress, DlSpeed, ETA, State, Seeding, Ratio, Seeds, Peers, Uploaded, UpSpeed}(курированный, без зависимости на qbt у читателей);Seedingвычислять черезclassify(state) == classReady - 2.2 Добавить в
Workerполе снимкаlive map[string]Live+ отдельныйsync.RWMutex(неw.mu); инициализация вNew - 2.3 В
Pollсобрать новую карту из полученногоtorrents— три ключа на торрент (lowercaseHash/InfohashV1/InfohashV2, какbyHash) — и атомарно подменить снимок сразу после построенияbyHash, до store- операций (телеметрия обновляется даже при последующем сбое reconcile) - 2.4 Реализовать
Live(infohash string) (Live, bool)— чтение под RLock,ok=falseпри пустом/неизвестном infohash - 2.5 Тесты: снимок обновляется после
Poll;Liveотдаёт данные качающейся и сидирующей задачи (с вернымSeeding); поиск по любому из трёх хэшей; неизвестный/пустой infohash →ok=false
3. Транспорт: контракт и фрагмент-роуты
- 3.1 Объявить интерфейс
LiveStatusвinternal/httpapiи добавить полеLive LiveStatusвDeps - 3.2 Прокинуть
Live: wrkвhttpapi.Depsвcmd/jellybit/serve.go - 3.3 Добавить роуты
GET /fragments/downloads/{id}/progressиGET /fragments/downloads/{id}/seedingвNewRouter - 3.4 Реализовать обработчики фрагментов:
GetDownload→ infohash/состояниеLive(infohash); рендер партиала;ok=false→ деградация без живых значений
- 3.5 Начальный рендер со значениями: расширить
downloadViewиdownloadDetailViewполями телеметрии; вhandleIndex/handleDownloadвызватьLive(infohash)для нужных задач и положить во view — одна модель для страницы и для фрагмент-роута (без мигания при первой загрузке) - 3.6 Добавить хелперы форматирования скорости/размера/ETA: человекочитаемые
единицы (байты→КиБ/МиБ, скорость/с), sentinel'ы qBittorrent (
eta=8640000→ «—»/«∞»,ratio<0→«—»); зафиксировать выборnum_seeds/num_leechs
4. Шаблоны и живое обновление
- 4.1 Партиал
partials/progress.html(прогресс-бар + скорость + ETA); включить его в карточкуindex.htmlдля активных загрузок - 4.2 Навесить на прогресс-блок активной карточки
hx-get/hx-trigger="every 3s"/hx-swap="outerHTML"; при выходе из downloading фрагмент не содержит атрибутов поллинга (поллинг прекращается) - 4.3 Партиал
partials/seeding.html(рейтинг, сиды/пиры, отдано, скорость отдачи); секция «Раздача» вdownload.htmlдля сидирующих задач, с htmx-поллингом и деградацией при отсутствии данных - 4.4 Проверить, что фоновое обновление не сбрасывает фильтр/поиск/прокрутку на главной (поллинг точечный, на уровне карточки)
- 4.5 При необходимости — стили прогресс-бара/раздачи в
jellybit.css(использовать существующие токены, без инлайн-хардкода цветов)
5. Проверки и ревью
- 5.1
task test(включая новые тесты воркера и httpapi-рендера фрагментов; в т.ч. тест «фрагмент при выходе из downloading отдаётся без htmx-атрибутов поллинга») - 5.2
task lint,gofmt,openspec validate --strict - 5.3 Ревью кода (второй чекпоинт) перед archive: соответствие спекам и
конвенциям (логирование без секретов, ошибки
%w, отдельный RWMutex)