Files
jellybit/tasks/items/download-page-stale-in-recognizing.md
T
av f89911447d задачи: заведён баг о застывшей странице загрузки
- страница /download/{id} держит бейдж «распознаётся» после перехода задачи
  дальше; воспроизведено на боевом umbar на последней версии
- причина неизвестна: тик самообновления объявлен и покрыт тестом, поэтому
  первый критерий приёмки — назвать, на каком шаге он теряется
2026-08-10 18:05:34 +03:00

5.3 KiB

🐞 Обновлять страницу загрузки при выходе из «распознаётся»

  • Тип: fix
  • Категория: Ядро продукта
  • Зачем: на боевом umbar последней версии страница держит бейдж «распознаётся» после того, как задача ушла в review или done — состояние видно только по F5

Спека web-ui («Самообновление живой задачи») заказывает: страница наблюдаемой задачи обновляет себя сама, пока задачу может двигать фон. recognizing наблюдаем (State.IsObservable), тик страницы объявлен every 15s, и разметка покрыта тестом TestDownloadPageSelfPoll — а на боевом стенде страница застывает. Расходится не разметка, а поведение живой страницы, и причина неизвестна: тик либо не уходит, либо уходит и не свопит, либо гасит сам себя.

Речь только о странице /download/{id}. Список загрузок ведёт свой поллер (карточка опрашивает /fragments/downloads/{id}/card) и в эту задачу не входит: на нём застывания не заявлено и оно не проверялось.

Воспроизведение

  1. Открыть /download/{id} на боевом umbar, пока задача в recognizing.
  2. Дождаться, когда фон уведёт её дальше — в review или done.
  3. Смотреть на страницу, не трогая её.

Видно вместо ожидаемого: бейдж и вся главная область остаются на «распознаётся» дольше одного тика (15 с) — сколько именно, не замерено. Нажатие F5 показывает настоящее состояние сразу. Наблюдалось на umbar на последней выложенной версии, то есть уже с самообновлением из коммита a5d873b.

Замера «через сколько секунд перестало обновляться», журнала сети из браузера и проверки на локальном запуске нет — первым делом их и надо снять.

Затрагивает

  • web/templates/partials/download_main.html — объявление тика: hx-get="/download/{id}", hx-trigger="every …", hx-select="#download-main", hx-swap="outerHTML" и hx-preserve на «Опасной зоне»;
  • handleDownload и buildDownloadView (internal/httpapi/download.go) — ответ на тик, ветка isHTMXfragTickErr и вычисление SelfPoll/PollEvery;
  • fragNote (internal/httpapi/live.go) — самозавершающийся фрагмент, который снимает поллер с поверхности;
  • State.IsObservable (internal/store/download.go) — предикат, на котором стоит тик;
  • спеки web-ui («Самообновление живой задачи») и live-status;
  • боевой рантайм: версия развёрнутого бинаря, раздача статики и заголовки кэширования страницы /download/{id}.

Критерии приёмки

  • Причина названа и подтверждена: показано, на каком шаге тик теряется — запрос не уходит, ответ не свопится или поллер снят (оракул: журнал сети браузера или лог сервера с боевого стенда, приложенный к задаче).
  • Страница, открытая в recognizing, показывает новое состояние без F5 не позже двух тиков после перехода (оракул: ручной прогон на umbar с засечкой времени перехода по логу сервера и времени смены бейджа).
  • Найденная причина закрыта проверкой, которая падала бы до починки (оракул: тест в internal/httpapi; причина не ловится тестом — сказано прямо, чем она закрыта вместо теста).
  • Тик по-прежнему замолкает на ненаблюдаемом состоянии (оракул: существующий TestDownloadPageSelfPoll зелёный).
  • task gate зелёный (оракул: сам гейт).

Рамки

На SSE не переезжать — это отдельная задача sse-live-updates; чинится существующий htmx-поллинг. Ветку fragTickErr не убирать: она стоит там, чтобы отказ чтения не оставлял вкладку стучать вечно (ADR-2026-08-10-observability-is-not-terminality).