WEB-170 · Задача · Инфраструктура · web
SCALESPIKE-06: offhost realtime mode
Закрыт
P2
ведёт: q170-m4
эпик: WEB-77
Суть
Фаза 6 эпика WEB-77. Выделить gateway + Redis + worker на другой хост.
Gateway:
- Node/Fastify SSE/WebSocket сервер (не Next.js)
- Валидация signed short-lived room token (без Prisma roundtrip)
- Подписка на Redis Stream/PubSub per roomId
- Backpressure: per-client buffer cap, coalesce deltas, drop slow clients
- Replay по Last-Event-ID из Redis Stream
- CORS/origin check, rate limits, connection caps
Next/Pi:
- Выпускает signed room token (HMAC, TTL 60s)
- Отдаёт команды (launch/join/heartbeat/leave) — уходят в Redis
- Не держит long-lived sockets
Presence store:
- Реализовать OFFHOST режим: heartbeat пишет напрямую в Redis (минуя Prisma)
- Compaction worker периодически сбрасывает снапшоты в Postgres
Ключевые точки:
- src/app/api/podcast/interactive/rooms/[roomId]/stream/route.ts (заменить на gateway URL + token)
- src/lib/podcast/interactive/warmupPipeline.ts:365-425 (SSE handler → удалить из Next, gateway делает сам)
- src/lib/podcast/interactive/studioRoomPresenceStore.ts (OFFHOST режим: Redis write, async Prisma compaction)
Критерий: Pi CPU/RAM почти не меняются при росте active sockets на offhost.
Спайк: STUDIO-SCALE-SPIKE.md, раздел «Фаза 6».
Оценка: L (1-2 недели).
Зависимости: WEB-81 (event stream), WEB-82 (warmup без таймеров).
Параллелить с: WEB-83 (разные компоненты).
Доказательства
[25.08 ~15:45Z] Взято волной web170 (sol xhigh, от 2857a88): отдельный Fastify SSE/WS gateway (services/realtime-gateway/), HMAC room-token без Prisma, Redis Stream + replay по Last-Event-ID, backpressure; выпуск токена в Next. Opt-in по env, тёмный, существующий realtime не трогается.
[25.08 ~19:15Z] СДЕЛАНО волной web170: commits 23089db+62e55b2 (от 2857a88). services/realtime-gateway/ — отдельный Fastify-пакет (свой package.json/lockfile/README/env.example), тёмный opt-in, существующий Next-realtime не тронут; выпуск HMAC room-токенов в Next. 📎 Трейл: отчёт /home/ubuntu/waves/WEB170-REPORT.md; ветка web170. → review; деплой гейтвея = отдельное ops-решение (не в посадку веба).
[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), realtime gateway + issuer, dark by default, зонные+негативные тесты волны зелёные. 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-170","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-08-25T19:57:41.759Z