Decouple room monitoring from player count, fix Jackbox API fetch

Extracts checkRoomStatus into shared jackbox-api.js with proper
User-Agent header (bare fetch was silently rejected by Jackbox API)
and always-on error logging (previously gated behind DEBUG flag).

Splits room-start detection (room-monitor.js) from audience-based
player counting (player-count-checker.js) to eliminate circular
dependency and allow immediate game.started detection. Room monitor
now polls immediately instead of waiting 10 seconds for first check.

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-08 18:25:52 -04:00
parent 4747aa9632
commit 505c335d20
5 changed files with 221 additions and 210 deletions

View File

@@ -4,7 +4,8 @@ const { authenticateToken } = require('../middleware/auth');
const db = require('../database');
const { triggerWebhook } = require('../utils/webhooks');
const { getWebSocketManager } = require('../utils/websocket-manager');
const { startPlayerCountCheck, stopPlayerCountCheck } = require('../utils/player-count-checker');
const { stopPlayerCountCheck } = require('../utils/player-count-checker');
const { startRoomMonitor, stopRoomMonitor } = require('../utils/room-monitor');
const router = express.Router();
@@ -356,13 +357,12 @@ router.post('/:id/games', authenticateToken, (req, res) => {
console.error('Error triggering notifications:', error);
}
// Automatically start player count check if room code was provided
// Automatically start room monitoring if room code was provided
if (room_code) {
try {
startPlayerCountCheck(req.params.id, result.lastInsertRowid, room_code, game.max_players);
startRoomMonitor(req.params.id, result.lastInsertRowid, room_code, game.max_players);
} catch (error) {
console.error('Error starting player count check:', error);
// Don't fail the request if player count check fails
console.error('Error starting room monitor:', error);
}
}
@@ -580,12 +580,13 @@ router.patch('/:sessionId/games/:gameId/status', authenticateToken, (req, res) =
return res.status(404).json({ error: 'Session game not found' });
}
// Stop player count check if game is no longer playing
// Stop room monitor and player count check if game is no longer playing
if (status !== 'playing') {
try {
stopRoomMonitor(sessionId, gameId);
stopPlayerCountCheck(sessionId, gameId);
} catch (error) {
console.error('Error stopping player count check:', error);
console.error('Error stopping room monitor/player count check:', error);
}
}
@@ -600,11 +601,12 @@ router.delete('/:sessionId/games/:gameId', authenticateToken, (req, res) => {
try {
const { sessionId, gameId } = req.params;
// Stop player count check before deleting
// Stop room monitor and player count check before deleting
try {
stopRoomMonitor(sessionId, gameId);
stopPlayerCountCheck(sessionId, gameId);
} catch (error) {
console.error('Error stopping player count check:', error);
console.error('Error stopping room monitor/player count check:', error);
}
const result = db.prepare(`
@@ -826,12 +828,12 @@ router.post('/:sessionId/games/:gameId/start-player-check', authenticateToken, (
return res.status(400).json({ error: 'Game does not have a room code' });
}
// Start the check
startPlayerCountCheck(sessionId, gameId, game.room_code, game.max_players);
// Start room monitoring (will hand off to player count check when game starts)
startRoomMonitor(sessionId, gameId, game.room_code, game.max_players);
res.json({
message: 'Player count check started',
status: 'waiting'
message: 'Room monitor started',
status: 'monitoring'
});
} catch (error) {
res.status(500).json({ error: error.message });
@@ -843,11 +845,12 @@ router.post('/:sessionId/games/:gameId/stop-player-check', authenticateToken, (r
try {
const { sessionId, gameId } = req.params;
// Stop the check
// Stop both room monitor and player count check
stopRoomMonitor(sessionId, gameId);
stopPlayerCountCheck(sessionId, gameId);
res.json({
message: 'Player count check stopped',
message: 'Room monitor and player count check stopped',
status: 'stopped'
});
} catch (error) {