2026-10-16 07:40:29 -06:00
|
|
|
"""`GET /api/events`: the server-sent event stream (session required; locked sessions allowed)."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Query, Request
|
|
|
|
|
from fastapi.responses import StreamingResponse
|
|
|
|
|
from starlette.concurrency import run_in_threadpool
|
|
|
|
|
|
|
|
|
|
from ..auth.groups import SCREENS
|
|
|
|
|
from ..events import EventHub, stream
|
|
|
|
|
from .deps import resolve_standalone, settings_of
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/api", tags=["events"])
|
|
|
|
|
|
|
|
|
|
SSE_HEADERS = {"Cache-Control": "no-cache", "X-Accel-Buffering": "no", "Connection": "keep-alive"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/events")
|
2026-10-16 22:46:56 -06:00
|
|
|
async def events(
|
|
|
|
|
request: Request,
|
|
|
|
|
screen: str | None = Query(None, max_length=32),
|
|
|
|
|
packet_id: int | None = Query(None, ge=1, le=2**62),
|
|
|
|
|
) -> StreamingResponse:
|
|
|
|
|
"""The event stream. `packet_id` is the packet the page has open; presence carries it, so the packet page can
|
|
|
|
|
show who else is looking at the same packet. The client reopens the stream when the open packet changes."""
|
2026-10-16 07:40:29 -06:00
|
|
|
# The session check runs on its own pooled connection, returned before the stream starts
|
|
|
|
|
p = await run_in_threadpool(resolve_standalone, request)
|
|
|
|
|
hub: EventHub = request.app.state.events
|
|
|
|
|
sub = hub.subscribe(
|
|
|
|
|
session_id=p.session_id,
|
|
|
|
|
user_id=p.user_id,
|
|
|
|
|
display_name=p.user["display_name"],
|
|
|
|
|
screen=screen if screen in SCREENS and screen in p.screens else None,
|
2026-10-16 22:46:56 -06:00
|
|
|
packet_id=packet_id,
|
2026-10-16 07:40:29 -06:00
|
|
|
)
|
|
|
|
|
hello = {"session_id": str(p.session_id), "build": settings_of(request).ps_build}
|
|
|
|
|
return StreamingResponse(
|
|
|
|
|
stream(hub, sub, hello=hello, is_disconnected=request.is_disconnected),
|
|
|
|
|
media_type="text/event-stream",
|
|
|
|
|
headers=SSE_HEADERS,
|
|
|
|
|
)
|