diff --git a/personal/plans/lampac-watchlist-plugin.md b/personal/plans/lampac-watchlist-plugin.md index f667df80..35a79745 100644 --- a/personal/plans/lampac-watchlist-plugin.md +++ b/personal/plans/lampac-watchlist-plugin.md @@ -8,7 +8,7 @@ related: - '[[family/projects/watchlist-automation]]' - '[[family/documents/movies-watchlist]]' - '[[personal/plans/lampac-watched-to-watchlist]]' -status: sync-down-feed-implemented-matcher-parity-blocked +status: investigation-2026-09-25-all-screens-feed-and-latency tags: - lampac - lampa @@ -24,13 +24,129 @@ tags: - card-parse - feed - matcher-parity + - partnext + - latency title: Watchlist в UI Lampa — каталог из списка type: plan -updated: '2026-09-24' +updated: '2026-09-25' --- # Watchlist в UI Lampa — каталог из списка +## 🔍 2026-09-25: РАССЛЕДОВАНИЕ — фид виден на всех экранах + «долго грузится» + +**Жалоба Alex (дословно):** «есть проблема с watchlist фидом в лампе: он отображается +не только на "главной" но даже когда я выбираю категорию например "документальные" +в разделе Фильмы, то есть независимо от активного экрана. и он как будто долго +прогружается относительно основного CUB списка, почему он не моментально проявляется, +он же статичный». + +**Статус: расследование завершено, причина установлена, фикс НЕ применён (ждёт апрува).** + +### Причина 1 — фид на всех экранах: в `plugin-cub.js` НЕТ фильтра по экрану + +Файл: `/Users/admin/lampac-tmp/plugin-cub.js` (196 строк, сборка `build_plugin.py`; +это тот же файл, что залит в Lampac как `module/Catalog/plugin.js`). + +`wlPatchPartNext()` (строки 155–193) — перехват глобального `Lampa.Api.partNext`: + +```js +Lampa.Api.partNext = function (parts, parts_limit, partLoaded, partEmpty) { + try { + if (Lampa.Arrays.isArray(parts) && !parts.__wl_done) { + var menu = window.__wl_menu; + if (menu && Object.keys(menu).length) { + parts.__wl_done = true; + wlInject(parts, menu); // ← БЕЗУСЛОВНАЯ вставка + } +``` + +**Ни одного обращения к активному экрану** — нет проверки `Lampa.Activity.active()`, +`activity.url`, `Lampa.Storage.field('source')` или чего-либо подобного. + +Механика: `partNext` — глобальный API, через него строят страницу ВСЕ источники. +`plugin.js:30` (`main()`) и `plugin.js:36` (`category()`) **оба** вызывают +`Lampa.Api.partNext(parts_data, parts_limit, ...)`. Отсюда: +- CUB рисует главную → перехват срабатывает → наши 4 секции сверху; +- вход в категорию («документальные» внутри Фильмов) → Lampa перестраивает страницу + через **тот же** `partNext` → перехват срабатывает снова → фид снова сверху. + +`wlInject()` (строки 121–127) кладёт секции через `unshift` в **начало** пула, поэтому +они рисуются поверх содержимого любой категории — ровно то, на что жалуется Alex. + +### Причина 2 — «долго грузится»: замеры (не догадки) + +Всё замерено `curl` на Кра́кене по `127.0.0.1:9118` (порт только изнутри хоста): + +| Запрос | Время | `size_download` | +|---|---|---| +| `GET /catalog/list?plugin=watchlist&cat=films` — повторный | **4 мс** | 107 640 | +| тот же — **первый (холодный кэш)** | **2 250 мс** | 107 640 | +| `GET /watchlist-films.json` — чистая статика мимо Catalog | **1 мс** | 88 156 | +| `GET /catalog/list?plugin=watchlist&cat=new` | 2–147 мс | 8 512 | +| **`GET /catalog/card?plugin=watchlist&uri=movie%2F424781&type=movie`** | **66 118 мс** | 939 | + +🔴 **ПИТФОЛЛ ЗАМЕРА: `curl -w '%{size_download}'` показывает размер СЖАТОГО тела.** +Я сначала прочитал 107 640 как «фид всего 105 КБ, грузиться нечему» — это ошибка. +Реальные размеры: `watchlist-films.json` = **88 156 несжатых** при 347 позициях, +`cards.json` = **548 219** (данные `ls -la` на Кра́кене). Для замеров объёма брать +`ls -la` или `%{size_download}` вместе с `Accept-Encoding: identity`. + +**Что из этого следует:** + +1. **4 мс на прогретом кэше** — данные отдаются мгновенно, «статичный» — правда. +2. **2.25 с на ПЕРВОМ холодном запросе категории** — это парсинг JSON парсерами + модуля Catalog (`content.nodes`, `args`) при пустом `hybridCache`. Дальше — кэш. + Отсюда ощущение «не моментально проявляется»: категория, которую давно не открывали, + платит 2+ секунды, а родной CUB-список тем временем уже отрисован. +3. **66 секунд на карточке фильма** — отдельный, более серьёзный баг. 66 с на файл + 939 байт из локального каталога — это не диск. `card_parse.initUrl` исполняется как + C#, `node: card`, читается `wwwroot/cards/card-movie-NNN.json`. Внутри + `CardController` что-то ждёт (таймаут внешнего вызова / `reactionsGet` к cub). + **Не диагностировано до конца — следующий шаг.** +4. **Наши секции стартуют позже родных:** `partNext` собирает пул, `parts_limit = 6`, + наши секции идут через `unshift` и грузятся отдельным HTTP-запросом на каждую + (`/catalog/list?plugin=watchlist&cat=`) — 4 запроса. Родной фид CUB приходит + одним запросом, поэтому «проявляется» раньше. + +### Контракт Lampac (проверено, НЕ трогать без причины) + +`catalog/sites/watchlist.yaml` на Кра́кене +(`/srv/dev-disk-by-uuid-6194539b-.../lampac/catalog/sites/watchlist.yaml`): + +- `plugin: watchlist` (🔴 без него ключ = `displayname` = «Мой список» → `ModInit.goInit` + вырезает кириллицу регуляркой `[^a-z0-9\-]` → site="" → HTTP 400 → «ЗДЕСЬ ПУСТО»). +- `host: http://127.0.0.1:9118`, категории `Новинки/Films/Мультфильмы/Аниме`. +- 🔴 **Первая категория в списке ИГНОРИРУЕТ `format`** и берёт `list.uri` напрямую — + поэтому первой стоит «Новинки» (`list.uri: watchlist-new.json`). +- `card_parse.initUrl` конвертирует `uri` `movie/424781` → `cards/card-movie-424781.json`, + `node: card`. `card_args.tmdb_id` обязан быть **числом** (через `format: long.TryParse`), + иначе карточка = «здесь пусто». + +**Nightly-пайплайн** (`/home/kraken/scripts/watchlist-nightly.sh`, крон `0 1 * * *`, +пользователь `kraken` НА КРА́КЕНЕ): `sync-vault pull` → `process-thumbs --apply` → +`resolve --recheck --apply` → **`sync-down --apply`** (сборка фида, `LAMPAC_ROOT=`UUID-путь) +→ `sync-up --apply` → backup `TimeCode.sql` (`sqlite3 .backup`) → `sync-from-lampac --apply` +→ `sync-vault push`. Рестарта lampac в скрипте НЕТ и он не нужен (`wwwroot/` bind-mount, +тот же inode) — но при залипшем каталоге в UI помогает обновление страницы / переключение +категории. На 2026-09-25 `watchlist-catalog.sh` уже убран в `.bak-removed-20260924-181942`, +отдельной строки крона `30 2 * * *` в crontab **нет** (п.2 из списка незакрытого — закрыт). + +### Открытые шаги (для следующей сессии) + +1. **Фикс «фид на всех экранах»:** добавить в `wlPatchPartNext` проверку активного экрана — + инжектить только когда `Lampa.Activity.active()` указывает на главную, иначе + пропускать. Точный предикат определить CDP-пробой на живом ТВ (`probe_ui.py`): + прочитать `Lampa.Activity.active()` на главной и внутри категории, сравнить. +2. **Диагностировать 66 с на карточке** — `docker logs lampac` + трейс `CardController`. +3. **Matcher-parity** (главный блокер с 2026-09-24, см. ниже) — всё ещё не закрыт. + +**Правило диагностики этой сессии:** не читать `%{size_download}` как «размер фида» +(это gzip). И — `ifconfig` на Кра́кене отсутствует, ssh-команды через `bash -c` иначе +падают шумом. + +--- + ## 🔴 2026-09-24 (вечер): ПЕРЕПИСЫВАНИЕ — один sync-скрипт вместо отдельного генератора **Требование Alex:** «перепиши по нормальному чтобы не отдельный скрипт на лампу был