Fix drag-to-move and WS keepalive

drag-to-move: use window-level mousemove/mouseup listeners for reliable
drag detection — React synthetic events on container were unreliable

WS keepalive: server sends ping JSON every 25s so nginx proxy_read_timeout
never fires; client ignores pings (not broadcast to peers anymore)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 13:44:12 +03:00
parent 14c5327870
commit 3da2d5e0ab
2 changed files with 51 additions and 51 deletions

View File

@@ -6,6 +6,8 @@ import type { RawData } from 'ws'
// hotel slug → set of connected streams
const hotelRooms = new Map<string, Set<SocketStream>>()
const PING_INTERVAL_MS = 25_000 // ping every 25s — keeps nginx proxy_read_timeout alive
const ws: FastifyPluginAsync = async (fastify) => {
await fastify.register(fastifyWebsocket)
@@ -19,8 +21,21 @@ const ws: FastifyPluginAsync = async (fastify) => {
if (!hotelRooms.has(hotel)) hotelRooms.set(hotel, new Set())
hotelRooms.get(hotel)!.add(connection)
// Send periodic ping so nginx proxy_read_timeout never fires
const pingTimer = setInterval(() => {
if (connection.socket.readyState === 1) {
connection.socket.send(JSON.stringify({ type: 'ping' }))
}
}, PING_INTERVAL_MS)
connection.socket.on('message', (raw: RawData) => {
const data = raw.toString()
// Ignore client pings — no need to broadcast them
try {
const msg = JSON.parse(data) as { type?: string }
if (msg.type === 'ping') return
} catch { /* not JSON, fall through */ }
const peers = hotelRooms.get(hotel)
if (!peers) return
peers.forEach(peer => {
@@ -31,6 +46,7 @@ const ws: FastifyPluginAsync = async (fastify) => {
})
connection.socket.on('close', () => {
clearInterval(pingTimer)
hotelRooms.get(hotel)?.delete(connection)
if (hotelRooms.get(hotel)?.size === 0) hotelRooms.delete(hotel)
})