feat: SSE live fight spectating with spectator count
Enable real-time fight spectating for all live fights (not just human fights). Multiple spectators can watch simultaneously via SSE. Spectator count is tracked per-fight and broadcast with every SSE event. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
a540320901
commit
610e799605
@@ -12,6 +12,13 @@ import { getPendingChallenge, submitHumanResponse } from '../engine/human-respon
|
||||
|
||||
export const fightsRouter = new Hono()
|
||||
|
||||
// Track spectator counts per fight
|
||||
const spectatorCounts = new Map<string, number>()
|
||||
|
||||
export function getSpectatorCount(fightId: string): number {
|
||||
return spectatorCounts.get(fightId) || 0
|
||||
}
|
||||
|
||||
// List recent fights (with bot names)
|
||||
fightsRouter.get('/', async (c) => {
|
||||
const rows = await db.select()
|
||||
@@ -322,10 +329,20 @@ fightsRouter.get('/:id/stream', (c) => {
|
||||
const fightId = c.req.param('id')
|
||||
|
||||
return streamSSE(c, async (stream) => {
|
||||
// Track spectator
|
||||
spectatorCounts.set(fightId, (spectatorCounts.get(fightId) || 0) + 1)
|
||||
const count = spectatorCounts.get(fightId)!
|
||||
|
||||
// Send initial spectator count
|
||||
await stream.writeSSE({
|
||||
event: 'spectator_count',
|
||||
data: JSON.stringify({ count }),
|
||||
})
|
||||
|
||||
const cleanup = fightEvents.on(fightId, (event) => {
|
||||
stream.writeSSE({
|
||||
event: event.type,
|
||||
data: JSON.stringify(event.data),
|
||||
data: JSON.stringify({ ...event.data, spectators: spectatorCounts.get(fightId) || 0 }),
|
||||
})
|
||||
})
|
||||
|
||||
@@ -333,14 +350,17 @@ fightsRouter.get('/:id/stream', (c) => {
|
||||
if (event.fightId === fightId && event.type === 'fight_end') {
|
||||
stream.writeSSE({
|
||||
event: 'fight_end',
|
||||
data: JSON.stringify(event.data),
|
||||
data: JSON.stringify({ ...event.data, spectators: spectatorCounts.get(fightId) || 0 }),
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
await stream.writeSSE({ event: 'ping', data: '' })
|
||||
await stream.writeSSE({
|
||||
event: 'ping',
|
||||
data: JSON.stringify({ spectators: spectatorCounts.get(fightId) || 0 }),
|
||||
})
|
||||
await stream.sleep(5000)
|
||||
const fight = await db.select({ status: schema.fights.status })
|
||||
.from(schema.fights)
|
||||
@@ -351,6 +371,13 @@ fightsRouter.get('/:id/stream', (c) => {
|
||||
} catch {
|
||||
// Client disconnected
|
||||
} finally {
|
||||
// Decrement spectator count
|
||||
const current = spectatorCounts.get(fightId) || 1
|
||||
if (current <= 1) {
|
||||
spectatorCounts.delete(fightId)
|
||||
} else {
|
||||
spectatorCounts.set(fightId, current - 1)
|
||||
}
|
||||
cleanup()
|
||||
cleanupGlobal()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user