feat(api+web): stream topic chat live over server-sent events
GET /v1/topics/:name/stream opens an SSE firehose, polled server-side
every 2s and streamed as `message` events. Forward-only — clients
hit /messages once for backfill, then live from connect-time onward.
Heartbeats every 30s keep the connection through proxies.
Web chat panel reads the stream via fetch + ReadableStream so the
bearer token stays in the Authorization header (EventSource can't
set custom headers, which would force token-in-URL leaks). Auto-
reconnect with exponential backoff. setInterval polling removed.
Vercel maxDuration bumped to 300s on the catch-all API route so
streams aren't cut at the 10s default.
drizzle migrations/meta/ deleted — superseded by the filename-
tracked custom runner in apps/broker/src/migrate.ts (c2cd67a).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,16 @@ import { handle } from "hono/vercel";
|
||||
|
||||
import { appRouter } from "@turbostarter/api";
|
||||
|
||||
// Streamable endpoints (e.g. /v1/topics/:name/stream SSE) need to keep
|
||||
// the connection open for minutes, not the 10s default. 300s is the
|
||||
// Vercel Pro ceiling; on Hobby the platform clamps to 60s and the
|
||||
// client auto-reconnects via the SSE retry loop.
|
||||
export const maxDuration = 300;
|
||||
|
||||
// Force dynamic rendering — streaming responses can't be statically
|
||||
// optimized and we don't want Next caching SSE traffic.
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const handler = handle(appRouter);
|
||||
export {
|
||||
handler as GET,
|
||||
|
||||
Reference in New Issue
Block a user