WEB-169 · Задача · Инфраструктура · web
SCALESPIKE-05: floor index для 10k rooms
Закрыт
P2
ведёт: q169-m4
эпик: WEB-77
Суть
Фаза 5 эпика WEB-77. Переделать floor/hub на paginated index.
API:
- GET /api/podcast/interactive/rooms?limit=60&cursor=&scope=&language=&sort=
- Ответ: { rooms: LocatorCard[], nextCursor, total }
- Counts из Redis hash/pipeline одним батчем (не per-room sweep)
- Ranking/heat обновлять при presence/exchange/lifecycle event → ZADD floor:rooms:active
UI:
- Убрать передачу 10k ID в batch (сейчас collectPresenceRoomIds возвращает все)
- Виртуализованный список с infinite scroll / pagination
- Floor counts только для visible page
Ключевые точки:
- src/lib/podcast/interactive/studioFloorPresenceCounts.ts:30 (MAX_FLOOR_PRESENCE_ROOMS → убрать хардкап для Redis path, paginated API)
- src/hooks/useStudioFloorPresenceCounts.ts:36-41 (idKey → запрашивать только visible roomIds)
- src/lib/podcast/interactive/studioLivePresenceCounts.ts:44-57 (collectPresenceRoomIds → только visible page)
- src/lib/podcast/interactive/sharedStudioRooms.ts:390-429 (buildSharedStudioLocator → поддержать paginated input)
- src/lib/podcast/interactive/studioDiscovery.ts (applyDiscovery → серверный, не клиентский для 10k)
Критерий: один floor refresh делает O(page_size), не O(total_rooms).
Спайк: STUDIO-SCALE-SPIKE.md, раздел «Фаза 5».
Оценка: M/L (1 неделя).
Зависимости: WEB-80 (Redis counts), WEB-83 желателен после WEB-81 (event-driven heat updates).
Параллелить с: WEB-84 (разные компоненты).
Доказательства
[25.08 ~13:40] Волна web169 (sol xhigh, A1, wt-web169 от c3fb44e): floor index по спайку SCALESPIKE-05, миграция строго аддитивная, EXPLAIN-скрипт в scripts/, негатив-тест. БД/прод не трогается.
[25.08 ~15:50] СДЕЛАНО волной web169: commit bcdbac1 (wt-web169 от c3fb44e). Серверный floor index Studio: GET /api/podcast/interactive/rooms (limit=60, keyset cursor createdAt+id), trending из Redis ZSET floor:rooms:active, presence одним HMGET на страницу, UI infinite-scroll + content-visibility (не грузит весь список). Миграция 20260825120000 СТРОГО аддитивная (3 partial CREATE INDEX на Podcast, EXPLAIN-скрипт scripts/web169-explain.sql — прогнать на проде при посадке). Честно: канонической spike-доки в дереве нет — новая схема НЕ выдумывалась, использованы существующие Podcast + объявленные Redis-ключи; предложение по физсхеме в отчёте. Redis best-effort (без Redis путь не ломается). → review; кандидат в батч 54 (индексы применить при посадке).
[25.08 ~15:00Z] В ПРОДЕ посадкой 54: релиз arm64-l59-20260825T134818Z, v4-2857a88 (merge-батч 2857a88, все проверки зелёные, Gate D сохранён ON). Миграция 3×CREATE INDEX ПРИМЕНЕНА на прод (pg_indexes подтверждает все 3), floor-API /api/podcast/interactive/rooms отвечает 200.
📎 Трейл: отчёт /home/ubuntu/waves/WEB169-REPORT.md; ветка web169@bcdbac1 (в проде 54, merge 01e8644); миграция prisma/migrations/20260825120000_web169_studio_floor_index (ПРИМЕНЕНА на прод); EXPLAIN: scripts/web169-explain.sql.
[2026-08-25 19:11Z] Независимая приёмка запущена: волна accscale на A1 (sol xhigh, приёмщик≠автор), worktree от прод-коммита a453b16; обязательны негативные тесты новых классов; для не-влитых тикетов волна установит факт NOT-LANDED. Бриф /home/ubuntu/waves/accscale-brief.md, отчёт будет в ACCSCALE-REPORT.md.
[2026-08-25 20:05Z] ПРИНЯТО (accscale): влит в a453b16 (git-факт ancestry), floor index: миграция+API+hook, keyset-пагинация, зонные+негативные тесты волны зелёные. GO → done. Отчёт A1:ACCSCALE-REPORT.md. ВАЖНО из epic77plan: код в проде, но ВКЛЮЧЕНИЕ на живых данных не доказано (флаги dark) — включение отдельными тикетами эпика WEB-77.
Починено в
a453b16
Воркер
не привязан — привязать:
curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \
-d '{"issueId":"WEB-169","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-08-25T19:57:41.578Z