Карточка списка на главной теперь даёт краткий обзор «от загрузки до
решения об удалении»: метка «ID:» перед идентификатором, дата добавления
(абсолютная + относительная, всегда), размер раздачи и рейтинг отдачи.
Спойлер контекста убран — контекст смотрят на /download/{id}.
Данные:
- рейтинг и общий размер — из живого снимка воркера (qbt total_size →
worker.Live.TotalSize); размер доступен для любой раздачи в снимке;
- размер-фолбэк, когда торрента нет в qBittorrent (orphaned) — сумма
размеров разложенных файлов: новая колонка file_link.size, layouter
пишет размер при линковке, ридер LayoutSizeByDownload суммирует по
странице одним запросом (дедуп по dst_path);
- дата — source_added_at → фолбэк created_at, показ в TZ сервера.
handleIndex читает снимок для всех карточек (map-lookup), рейтинг/размер
статичны на рендере (без поллинга). Миграция 0007, ER-схема обновлена.
Change download-card-lifecycle-overview влит в спеки и заархивирован.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
123 lines
8.1 KiB
Markdown
123 lines
8.1 KiB
Markdown
# live-status Specification
|
|
|
|
## Purpose
|
|
TBD - created by archiving change live-status. Update Purpose after archive.
|
|
## Requirements
|
|
### Requirement: Снимок живой телеметрии
|
|
|
|
Воркер — единственный сэмплер qBittorrent — SHALL на каждом тике поллинга
|
|
обновлять in-memory снимок телеметрии всех известных раздач. Снимок MUST NOT
|
|
персиститься в БД: он волатилен и переживает только до рестарта процесса.
|
|
|
|
#### Scenario: Обновление снимка на тике
|
|
|
|
- **WHEN** воркер завершает успешный тик поллинга qBittorrent
|
|
- **THEN** снимок телеметрии содержит актуальные данные по каждой раздаче,
|
|
присутствующей в ответе qBittorrent
|
|
|
|
#### Scenario: Снимок волатилен
|
|
|
|
- **WHEN** процесс только что перезапущен и первый тик поллинга ещё не прошёл
|
|
- **THEN** снимок пуст, а UI отображает задачи без живых значений, не падая
|
|
|
|
### Requirement: Состав телеметрии
|
|
|
|
Телеметрия одной раздачи SHALL включать прогресс (доля 0..1), скорость загрузки,
|
|
ETA и общий размер раздачи (total size); а для сидирующих раздач дополнительно —
|
|
рейтинг, число сидов и пиров, объём отданного и скорость отдачи. Общий размер
|
|
SHALL быть доступен для любой раздачи, присутствующей в снимке (не только
|
|
сидирующей). Значения SHALL извлекаться из ответа qBittorrent `/torrents/info`
|
|
без дополнительного сетевого вызова.
|
|
|
|
#### Scenario: Телеметрия качающейся задачи
|
|
|
|
- **WHEN** торрент задачи находится в состоянии загрузки
|
|
- **THEN** в снимке для неё доступны прогресс, скорость загрузки и ETA
|
|
|
|
#### Scenario: Общий размер доступен для любой раздачи в снимке
|
|
|
|
- **WHEN** торрент задачи присутствует в снимке в любом состоянии
|
|
- **THEN** в телеметрии для неё доступен общий размер раздачи
|
|
|
|
#### Scenario: Телеметрия сидирующей задачи
|
|
|
|
- **WHEN** торрент задачи завершён и раздаётся
|
|
- **THEN** в снимке для неё доступны рейтинг, число сидов/пиров, объём
|
|
отданного и скорость отдачи
|
|
|
|
### Requirement: Чтение телеметрии транспортом
|
|
|
|
Сервис SHALL предоставлять чтение снимка телеметрии по задаче через
|
|
изолированный контракт, не зависящий от способа доставки в браузер (поллинг
|
|
сейчас, SSE в будущем). Если для задачи нет записи в снимке (соответствующий
|
|
торрент отсутствовал в qBittorrent на последнем тике), чтение SHALL сообщать
|
|
об отсутствии данных, а UI MUST деградировать без живых значений, не падая.
|
|
|
|
#### Scenario: Данные есть
|
|
|
|
- **WHEN** транспорт читает телеметрию задачи, чей торрент был в последнем тике
|
|
- **THEN** он получает живые значения этой задачи
|
|
|
|
#### Scenario: Данных нет
|
|
|
|
- **WHEN** транспорт читает телеметрию задачи, торрента которой нет в qBittorrent
|
|
- **THEN** он получает признак отсутствия данных и рендерит страницу без живых
|
|
значений
|
|
|
|
### Requirement: Свежесть не выше тика поллинга
|
|
|
|
Живые значения, видимые в браузере, SHALL быть не свежее последнего тика
|
|
поллинга воркера; браузер MUST NOT опрашивать qBittorrent напрямую. Любой
|
|
запрос UI за телеметрией SHALL обслуживаться из in-memory снимка, не порождая
|
|
обращения к qBittorrent — поэтому частота обновления UI может быть выбрана
|
|
свободно (в т.ч. чаще тика для плавности), не нагружая qBittorrent.
|
|
|
|
#### Scenario: Браузер не обгоняет воркер
|
|
|
|
- **WHEN** браузер запрашивает фрагмент телеметрии чаще, чем длится тик
|
|
поллинга
|
|
- **THEN** он получает значения последнего тика, и обращения к qBittorrent при
|
|
этом не происходит
|
|
|
|
### Requirement: Живой прогресс активных загрузок
|
|
|
|
Веб-UI SHALL обновлять прогресс активных (downloading) загрузок на главной без
|
|
перезагрузки страницы — поллингом фрагмента через htmx. Обновление MUST NOT
|
|
сбрасывать клиентские фильтр, поиск и прокрутку. Когда задача покидает
|
|
состояние downloading, поллинг её прогресса SHALL прекращаться.
|
|
|
|
#### Scenario: Прогресс растёт без перезагрузки
|
|
|
|
- **WHEN** загрузка качается и пользователь смотрит на главную
|
|
- **THEN** её прогресс-бар, скорость и ETA обновляются на месте без
|
|
перезагрузки страницы
|
|
|
|
#### Scenario: Клиентское состояние сохраняется
|
|
|
|
- **WHEN** применён фильтр или поиск и происходит фоновое обновление прогресса
|
|
- **THEN** выбранный фильтр, текст поиска и позиция прокрутки не сбрасываются
|
|
|
|
#### Scenario: Завершение останавливает поллинг
|
|
|
|
- **WHEN** загрузка переходит из downloading в другое состояние
|
|
- **THEN** фоновый поллинг прогресса для этой карточки прекращается
|
|
|
|
### Requirement: Секция раздачи на странице загрузки
|
|
|
|
Страница `/download/{id}` SHALL показывать секцию «Раздача» с живой статистикой
|
|
(рейтинг, число сидов и пиров, объём отданного, скорость отдачи) для задач,
|
|
чей торрент сидирует. Если живых данных по задаче нет, секция SHALL
|
|
отсутствовать либо явно показывать «нет данных», не ломая остальную страницу.
|
|
|
|
#### Scenario: Сидирующая задача показывает раздачу
|
|
|
|
- **WHEN** открыта страница задачи, торрент которой раздаётся
|
|
- **THEN** в секции «Раздача» видны рейтинг, сиды/пиры, отдано и скорость отдачи
|
|
|
|
#### Scenario: Нет живых данных — секция деградирует
|
|
|
|
- **WHEN** открыта страница задачи, торрента которой нет в qBittorrent
|
|
- **THEN** секция «Раздача» отсутствует или показывает «нет данных», а
|
|
распознавание, файлы и история отображаются нормально
|
|
|