Files
ripster/backend/src/index.js
2026-03-11 11:56:17 +00:00

106 lines
3.5 KiB
JavaScript

require('dotenv').config();
const http = require('http');
const express = require('express');
const cors = require('cors');
const { port, corsOrigin } = require('./config');
const { initDatabase } = require('./db/database');
const errorHandler = require('./middleware/errorHandler');
const requestLogger = require('./middleware/requestLogger');
const settingsRoutes = require('./routes/settingsRoutes');
const pipelineRoutes = require('./routes/pipelineRoutes');
const historyRoutes = require('./routes/historyRoutes');
const cronRoutes = require('./routes/cronRoutes');
const runtimeRoutes = require('./routes/runtimeRoutes');
const wsService = require('./services/websocketService');
const pipelineService = require('./services/pipelineService');
const cronService = require('./services/cronService');
const diskDetectionService = require('./services/diskDetectionService');
const hardwareMonitorService = require('./services/hardwareMonitorService');
const logger = require('./services/logger').child('BOOT');
const { errorToMeta } = require('./utils/errorMeta');
async function start() {
logger.info('backend:start:init');
await initDatabase();
await pipelineService.init();
await cronService.init();
const app = express();
app.use(cors({ origin: corsOrigin }));
app.use(express.json({ limit: '2mb' }));
app.use(requestLogger);
app.get('/api/health', (req, res) => {
res.json({ ok: true, now: new Date().toISOString() });
});
app.use('/api/settings', settingsRoutes);
app.use('/api/pipeline', pipelineRoutes);
app.use('/api/history', historyRoutes);
app.use('/api/crons', cronRoutes);
app.use('/api/runtime', runtimeRoutes);
app.use(errorHandler);
const server = http.createServer(app);
wsService.init(server);
await hardwareMonitorService.init();
diskDetectionService.on('discInserted', (device) => {
logger.info('disk:inserted:event', { device });
pipelineService.onDiscInserted(device).catch((error) => {
logger.error('pipeline:onDiscInserted:failed', { error: errorToMeta(error), device });
wsService.broadcast('PIPELINE_ERROR', { message: error.message });
});
});
diskDetectionService.on('discRemoved', (device) => {
logger.info('disk:removed:event', { device });
pipelineService.onDiscRemoved(device).catch((error) => {
logger.error('pipeline:onDiscRemoved:failed', { error: errorToMeta(error), device });
wsService.broadcast('PIPELINE_ERROR', { message: error.message });
});
});
diskDetectionService.on('error', (error) => {
logger.error('diskDetection:error:event', { error: errorToMeta(error) });
wsService.broadcast('DISK_DETECTION_ERROR', { message: error.message });
});
diskDetectionService.start();
server.listen(port, () => {
logger.info('backend:listening', { port });
});
const shutdown = () => {
logger.warn('backend:shutdown:received');
diskDetectionService.stop();
hardwareMonitorService.stop();
cronService.stop();
server.close(() => {
logger.warn('backend:shutdown:completed');
process.exit(0);
});
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
process.on('uncaughtException', (error) => {
logger.error('process:uncaughtException', { error: errorToMeta(error) });
});
process.on('unhandledRejection', (reason) => {
logger.error('process:unhandledRejection', {
reason: reason instanceof Error ? errorToMeta(reason) : String(reason)
});
});
}
start().catch((error) => {
logger.error('backend:start:failed', { error: errorToMeta(error) });
process.exit(1);
});