import { createServer } from 'http'; import { app, logger } from './app'; import { config } from './config'; import { connectRedis } from './config/redis'; import { connectDatabase, disconnectDatabase } from './config/db'; import { initializeSocket } from './socket'; import { loadLuaScripts } from './services/vote.service'; import { loadVotingScripts } from './services/voting.engine'; import { prizeConfigService } from './services/prize-config.service'; import { programConfigService } from './services/program-config.service'; import { participantService } from './services/participant.service'; async function main(): Promise { try { if (!config.adminAccessCode) { logger.warn('ADMIN_ACCESS_CODE 未配置,管理员登录将被拒绝'); } if (!config.isDev && config.jwtSecret === 'dev-secret-change-in-production') { logger.error('生产环境禁止使用默认 JWT_SECRET,请配置环境变量'); process.exit(1); } // Connect to Database logger.info('Connecting to Database...'); await connectDatabase(); // Connect to Redis logger.info('Connecting to Redis...'); await connectRedis(); // Load Lua scripts logger.info('Loading Lua scripts...'); await loadLuaScripts(); await loadVotingScripts(); // Load prize configuration logger.info('Loading prize configuration...'); await prizeConfigService.load(); // Load program configuration logger.info('Loading program configuration...'); await programConfigService.load(); // Restore participants from Redis logger.info('Restoring participants from Redis...'); await participantService.restoreFromRedis(); // Create HTTP server const httpServer = createServer(app); // Initialize Socket.io logger.info('Initializing Socket.io...'); await initializeSocket(httpServer); // Start server - listen on all interfaces for LAN access httpServer.listen(config.port, '0.0.0.0', () => { logger.info({ port: config.port, env: config.nodeEnv }, 'Server started'); logger.info(`Health check: http://localhost:${config.port}/health`); logger.info(`LAN access: http://192.168.1.5:${config.port}`); }); // Graceful shutdown const shutdown = async (signal: string) => { logger.info({ signal }, 'Shutdown signal received'); // Disconnect from database await disconnectDatabase(); httpServer.close(() => { logger.info('HTTP server closed'); process.exit(0); }); // Force exit after 10 seconds setTimeout(() => { logger.error('Forced shutdown after timeout'); process.exit(1); }, 10000); }; process.on('SIGTERM', () => shutdown('SIGTERM')); process.on('SIGINT', () => shutdown('SIGINT')); } catch (error) { logger.error({ error }, 'Failed to start server'); process.exit(1); } } main();