/** * Test Data Database Server * Express.js server with search API and web interface * * Fixed version - singleton DB connection, crash resilience, * graceful shutdown, request logging. */ const express = require('express'); const cors = require('cors'); const path = require('path'); const apiRoutes = require('./routes/api'); const { cleanup } = require('./routes/api'); const app = express(); const PORT = process.env.PORT || 3000; const HOST = '0.0.0.0'; // --------------------------------------------------------------------------- // Crash resilience - log and continue rather than dying // --------------------------------------------------------------------------- process.on('uncaughtException', (err) => { console.error(`[${new Date().toISOString()}] [UNCAUGHT EXCEPTION] ${err.stack || err.message}`); }); process.on('unhandledRejection', (reason) => { console.error(`[${new Date().toISOString()}] [UNHANDLED REJECTION] ${reason}`); }); // --------------------------------------------------------------------------- // Middleware // --------------------------------------------------------------------------- app.use(cors()); app.use(express.json()); app.use(express.static(path.join(__dirname, 'public'))); // Request logging app.use((req, res, next) => { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; console.log( `[${new Date().toISOString()}] ${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms` ); }); next(); }); // --------------------------------------------------------------------------- // Routes // --------------------------------------------------------------------------- app.use('/api', apiRoutes); // Serve index.html for root app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); // --------------------------------------------------------------------------- // Start server // --------------------------------------------------------------------------- const server = app.listen(PORT, HOST, () => { console.log(`\n========================================`); console.log(`Test Data Database Server`); console.log(`========================================`); console.log(`Server running on all interfaces (${HOST}:${PORT})`); console.log(`Local: http://localhost:${PORT}`); console.log(`LAN: http://192.168.0.6:${PORT}`); console.log(`API endpoints:`); console.log(` GET /api/search?serial=...&model=...`); console.log(` GET /api/record/:id`); console.log(` GET /api/datasheet/:id`); console.log(` GET /api/stats`); console.log(` GET /api/filters`); console.log(` GET /api/export?format=csv&...`); console.log(`========================================\n`); }); // --------------------------------------------------------------------------- // Graceful shutdown // --------------------------------------------------------------------------- function shutdown(signal) { console.log(`\n[${new Date().toISOString()}] Received ${signal}. Shutting down gracefully...`); server.close(() => { console.log(`[${new Date().toISOString()}] HTTP server closed.`); cleanup(); console.log(`[${new Date().toISOString()}] Database connection closed. Goodbye.`); process.exit(0); }); // Force exit after 10 seconds if graceful shutdown stalls setTimeout(() => { console.error(`[${new Date().toISOString()}] Forced shutdown after timeout.`); cleanup(); process.exit(1); }, 10000); } process.on('SIGTERM', () => shutdown('SIGTERM')); process.on('SIGINT', () => shutdown('SIGINT')); module.exports = app;