- каталог задач: PLAN.md → ROADMAP.md с каноническими секциями, все 44 записи получили тип, заголовки приведены к форме своего типа - расхождения, найденные судьями канона: исключения инварианта «источник неприкосновенен», инвариант про один активный infohash, UTC в logging.md, поведение из architecture.md заменено ссылками на спеки - триггеры профиля ревью переписаны под умолчание standard
8.7 KiB
live-status Specification
Purpose
Живая телеметрия раздач: единственный сэмплер — воркер, снимок держится в
памяти на тике поллинга и в БД не персистится. Состав телеметрии (прогресс,
скорость, ETA, размер; для сидирующих — рейтинг, сиды и пиры, отдано), узкий
контракт чтения транспортом и живое обновление интерфейса поллингом фрагментов.
Что именно рисуется на странице и в карточке — web-ui; откуда берутся сами
состояния загрузки — download-tracking.
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 секция «Раздача» отсутствует или показывает «нет данных», а распознавание, файлы и история отображаются нормально