mirror of
https://github.com/elder-plinius/R00TS.git
synced 2026-02-12 17:22:52 +00:00
177 lines
5.1 KiB
JavaScript
177 lines
5.1 KiB
JavaScript
require('dotenv').config();
|
|
const express = require('express');
|
|
const mongoose = require('mongoose');
|
|
const cors = require('cors');
|
|
const morgan = require('morgan');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const { CronJob } = require('cron');
|
|
|
|
// Create logs directory if it doesn't exist
|
|
const logsDir = path.join(__dirname, 'logs');
|
|
if (!fs.existsSync(logsDir)) {
|
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
console.log(`Created logs directory at ${logsDir}`);
|
|
}
|
|
|
|
// Configure logging
|
|
const logStream = fs.createWriteStream(
|
|
path.join(logsDir, `server-${new Date().toISOString().split('T')[0]}.log`),
|
|
{ flags: 'a' }
|
|
);
|
|
|
|
// Redirect console output to log file and console
|
|
const originalConsoleLog = console.log;
|
|
const originalConsoleError = console.error;
|
|
|
|
console.log = function() {
|
|
const args = Array.from(arguments);
|
|
const timestamp = new Date().toISOString();
|
|
const logMessage = `[${timestamp}] INFO: ${args.join(' ')}
|
|
`;
|
|
logStream.write(logMessage);
|
|
originalConsoleLog.apply(console, arguments);
|
|
};
|
|
|
|
console.error = function() {
|
|
const args = Array.from(arguments);
|
|
const timestamp = new Date().toISOString();
|
|
const logMessage = `[${timestamp}] ERROR: ${args.join(' ')}
|
|
`;
|
|
logStream.write(logMessage);
|
|
originalConsoleError.apply(console, arguments);
|
|
};
|
|
|
|
// Import routes
|
|
const wordRoutes = require('./routes/words');
|
|
const datasetRoutes = require('./routes/datasets');
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 5000;
|
|
|
|
// Middleware
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
app.use(morgan('dev'));
|
|
|
|
// Serve static files from the React app
|
|
app.use(express.static(path.join(__dirname, '..')));
|
|
|
|
// Connect to MongoDB with retry logic
|
|
const connectWithRetry = () => {
|
|
console.log('Attempting to connect to MongoDB...');
|
|
mongoose.connect(process.env.MONGODB_URI, {
|
|
useNewUrlParser: true,
|
|
useUnifiedTopology: true,
|
|
})
|
|
.then(() => {
|
|
console.log('MongoDB connected successfully');
|
|
// Initialize scheduled tasks after successful connection
|
|
initializeScheduledTasks();
|
|
})
|
|
.catch(err => {
|
|
console.error('MongoDB connection error:', err);
|
|
console.log('Retrying connection in 5 seconds...');
|
|
setTimeout(connectWithRetry, 5000);
|
|
});
|
|
};
|
|
|
|
// Handle MongoDB disconnection (auto-reconnect)
|
|
mongoose.connection.on('disconnected', () => {
|
|
console.log('MongoDB disconnected! Attempting to reconnect...');
|
|
connectWithRetry();
|
|
});
|
|
|
|
// Initial connection
|
|
connectWithRetry();
|
|
|
|
// Initialize scheduled tasks
|
|
function initializeScheduledTasks() {
|
|
// Import backup script
|
|
const { performBackup } = require('./scripts/backup');
|
|
|
|
// Schedule daily backup at 3:00 AM
|
|
const backupJob = new CronJob('0 3 * * *', performBackup, null, true);
|
|
console.log('Scheduled automatic database backup job');
|
|
|
|
// Schedule weekly database maintenance at 2:00 AM on Sundays
|
|
const maintenanceJob = new CronJob('0 2 * * 0', async () => {
|
|
console.log('Running weekly database maintenance...');
|
|
try {
|
|
// Perform any maintenance tasks here
|
|
// For example, compact collections, validate data integrity, etc.
|
|
console.log('Database maintenance completed successfully');
|
|
} catch (error) {
|
|
console.error('Database maintenance error:', error);
|
|
}
|
|
}, null, true);
|
|
console.log('Scheduled weekly database maintenance job');
|
|
}
|
|
|
|
// Health check endpoint
|
|
app.get('/api/health', (req, res) => {
|
|
const dbStatus = mongoose.connection.readyState === 1 ? 'connected' : 'disconnected';
|
|
|
|
res.json({
|
|
status: 'ok',
|
|
timestamp: new Date().toISOString(),
|
|
server: {
|
|
uptime: process.uptime(),
|
|
memory: process.memoryUsage(),
|
|
},
|
|
database: {
|
|
status: dbStatus
|
|
}
|
|
});
|
|
});
|
|
|
|
// API Routes
|
|
app.use('/api/words', wordRoutes);
|
|
app.use('/api/datasets', datasetRoutes);
|
|
|
|
// Serve the main HTML file for any other request
|
|
app.get('*', (req, res) => {
|
|
res.sendFile(path.join(__dirname, '..', 'index.html'));
|
|
});
|
|
|
|
// Error handling middleware
|
|
app.use((err, req, res, next) => {
|
|
console.error('Unhandled error:', err);
|
|
res.status(500).json({ error: 'Internal server error', message: err.message });
|
|
});
|
|
|
|
// Handle uncaught exceptions
|
|
process.on('uncaughtException', (err) => {
|
|
console.error('Uncaught exception:', err);
|
|
// Keep the process alive but log the error
|
|
});
|
|
|
|
// Handle unhandled promise rejections
|
|
process.on('unhandledRejection', (reason, promise) => {
|
|
console.error('Unhandled promise rejection:', reason);
|
|
// Keep the process alive but log the error
|
|
});
|
|
|
|
// Start the server
|
|
const server = app.listen(PORT, () => {
|
|
console.log(`R00TS server running on port ${PORT}`);
|
|
console.log(`Server time: ${new Date().toLocaleString()}`);
|
|
console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
|
|
console.log(`MongoDB URI: ${process.env.MONGODB_URI.replace(/\/.*@/, '//***:***@')}`);
|
|
console.log('Server is ready to accept connections');
|
|
});
|
|
|
|
// Graceful shutdown
|
|
process.on('SIGTERM', () => {
|
|
console.log('SIGTERM received, shutting down gracefully');
|
|
server.close(() => {
|
|
console.log('Server closed');
|
|
mongoose.connection.close(false, () => {
|
|
console.log('MongoDB connection closed');
|
|
process.exit(0);
|
|
});
|
|
});
|
|
});
|
|
|
|
module.exports = app; // Export for testing
|