web-ui: карточка и страница обновляются, пока задачу может двигать фон

- условие самообновления — доменный предикат store.State.IsObservable() вместо
  фазы catched; один поллер на поверхность, интервалы 5 с и 15 с
- отказ тика отвечает 200 и самозавершающимся фрагментом с корневым id цели
  вместо 404/500, который htmx не свопит
- заведён ADR-2026-08-10-observability-is-not-terminality, переписан раздел
  «Живой поллинг» в конвенции веб-UI
This commit is contained in:
av
2026-08-10 14:02:38 +03:00
parent 969926fae3
commit a5d873b62d
29 changed files with 1575 additions and 99 deletions
+34 -8
View File
@@ -86,10 +86,21 @@ SHALL быть доступен для любой раздачи, присутс
### Requirement: Живой прогресс активных загрузок
Веб-UI SHALL обновлять прогресс активных (downloading) загрузок на главной без
перезагрузки страницы — поллингом фрагмента через htmx. Обновление MUST NOT
сбрасывать клиентские фильтр, поиск и прокрутку. Когда задача покидает
состояние downloading, поллинг её прогресса SHALL прекращаться.
Веб-UI SHALL показывать прогресс, скорость и ETA активных (`downloading`)
загрузок на главной без перезагрузки страницы, обновляя их тем же
самообновлением, которым обновляется сама карточка (см. `web-ui`,
«Самообновление живой задачи»). Обновление MUST NOT сбрасывать клиентские
фильтр, поиск и прокрутку.
Когда задача покидает состояние `downloading`, показ скорости и ETA SHALL
прекращаться: вне качания эти величины смысла не имеют. Снимок при этом
продолжает питать прочие живые значения карточки и страницы — размер и рейтинг
раздачи, — и прекращение показа цифр качания MUST NOT означать прекращения
обновления поверхности: она продолжает отражать смену состояния, пока задача
наблюдаема.
Живые цифры MUST браться из снимка воркера; при отсутствии данных по задаче
поверхность деградирует без них, не ломая остального отображения.
#### Scenario: Прогресс растёт без перезагрузки
@@ -99,13 +110,15 @@ SHALL быть доступен для любой раздачи, присутс
#### Scenario: Клиентское состояние сохраняется
- **WHEN** применён фильтр или поиск и происходит фоновое обновление прогресса
- **WHEN** применён фильтр или поиск и происходит фоновое обновление
- **THEN** выбранный фильтр, текст поиска и позиция прокрутки не сбрасываются
#### Scenario: Завершение останавливает поллинг
#### Scenario: Завершение убирает цифры качания, но не обновление
- **WHEN** загрузка переходит из downloading в другое состояние
- **THEN** фоновый поллинг прогресса для этой карточки прекращается
- **WHEN** загрузка переходит из `downloading` в другое наблюдаемое состояние
- **THEN** блок прогресса, скорости и ETA с карточки исчезает
- **AND** карточка продолжает обновляться и приносит новое состояние
- **AND** размер и рейтинг раздачи по-прежнему берутся из снимка
### Requirement: Секция раздачи на странице загрузки
@@ -114,6 +127,12 @@ SHALL быть доступен для любой раздачи, присутс
чей торрент сидирует. Если живых данных по задаче нет, секция SHALL
отсутствовать либо явно показывать «нет данных», не ломая остальную страницу.
Секция MUST NOT опрашивать сервер самостоятельно: она лежит внутри области,
которую страница обновляет целиком, и собственный опрос секции подменял бы
разметку страницы. Её цифры SHALL приходить с тиком самообновления страницы
(см. `web-ui`, «Самообновление живой задачи»), а частота их обновления
SHALL совпадать с частотой обновления страницы.
#### Scenario: Сидирующая задача показывает раздачу
- **WHEN** открыта страница задачи, торрент которой раздаётся
@@ -125,3 +144,10 @@ SHALL быть доступен для любой раздачи, присутс
- **THEN** секция «Раздача» отсутствует или показывает «нет данных», а
распознавание, файлы и история отображаются нормально
#### Scenario: Секция обновляется тиком страницы
- **GIVEN** открыта страница наблюдаемой задачи, чья раздача сидирует
- **WHEN** страница отрисована
- **THEN** секция «Раздача» не несёт собственного опроса
- **AND** её цифры обновляются вместе с остальной страницей