Files
2026-03-18 13:34:41 +01:00

76 lines
2.2 KiB
TypeScript

import { auth } from '@/lib/auth'
import { db } from '@/lib/db'
import { scores, roundPlayers } from '@/lib/db/schema'
import { eq, and } from 'drizzle-orm'
import { headers } from 'next/headers'
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> },
) {
const { id: roundId } = await params
const session = await auth.api.getSession({ headers: await headers() })
if (!session) return new Response('Unauthorized', { status: 401 })
// Verify caller is a member of this round
const [membership] = await db
.select()
.from(roundPlayers)
.where(and(eq(roundPlayers.roundId, roundId), eq(roundPlayers.userId, session.user.id)))
.limit(1)
if (!membership) return new Response('Forbidden', { status: 403 })
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
async function send() {
const rows = await db
.select({ holeId: scores.holeId, playerId: scores.playerId, strokes: scores.strokes })
.from(scores)
.where(eq(scores.roundId, roundId))
controller.enqueue(encoder.encode(`data: ${JSON.stringify(rows)}\n\n`))
}
// Initial payload
await send()
// Poll every 3 seconds
const interval = setInterval(async () => {
try { await send() } catch { clearInterval(interval); controller.close() }
}, 3000)
// Heartbeat every 30s to keep connection alive through proxies
const heartbeat = setInterval(() => {
try { controller.enqueue(encoder.encode(': heartbeat\n\n')) } catch { /* closed */ }
}, 30_000)
// Clean up on disconnect or 4-hour timeout
const timeout = setTimeout(() => {
clearInterval(interval)
clearInterval(heartbeat)
controller.close()
}, 4 * 60 * 60 * 1000)
request.signal.addEventListener('abort', () => {
clearInterval(interval)
clearInterval(heartbeat)
clearTimeout(timeout)
controller.close()
})
},
})
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache, no-transform',
Connection: 'keep-alive',
'X-Accel-Buffering': 'no', // disable nginx buffering
},
})
}