Files
dashboard/backend/src/server.ts

115 lines
3.5 KiB
TypeScript

import app from './app';
import environment from './config/environment';
import logger from './utils/logger';
import { testConnection, closePool, runMigrations } from './config/database';
import { startAuditCleanupJob, stopAuditCleanupJob } from './jobs/audit-cleanup.job';
import { startNotificationJob, stopNotificationJob } from './jobs/notification-generation.job';
import { startReminderJob, stopReminderJob } from './jobs/reminder.job';
import { startIssueReminderJob, stopIssueReminderJob } from './jobs/issue-reminder.job';
import { startChecklistReminderJob, stopChecklistReminderJob } from './jobs/checklist-reminder.job';
import { permissionService } from './services/permission.service';
const startServer = async (): Promise<void> => {
try {
// Test database connection
logger.info('Testing database connection...');
const dbConnected = await testConnection();
if (!dbConnected) {
logger.warn('Database connection failed - server will start but database operations may fail');
} else {
// Run pending migrations automatically on startup
await runMigrations();
// Load permission cache after migrations
await permissionService.loadCache();
}
// Start the GDPR IP anonymisation job
startAuditCleanupJob();
// Start the notification generation job
startNotificationJob();
// Start the order reminder job
startReminderJob();
// Start the issue reminder job
startIssueReminderJob();
// Start the checklist reminder job
startChecklistReminderJob();
// Start the server
const server = app.listen(environment.port, () => {
logger.info('Server started successfully', {
port: environment.port,
environment: environment.nodeEnv,
database: dbConnected ? 'connected' : 'disconnected',
});
// Log integration status so operators can see what's configured
logger.info('Integration status', {
bookstack: !!environment.bookstack.url,
nextcloud: !!environment.nextcloudUrl,
vikunja: !!environment.vikunja.url,
});
});
// Graceful shutdown handling
const gracefulShutdown = async (signal: string) => {
logger.info(`${signal} received. Starting graceful shutdown...`);
// Stop scheduled jobs first
stopAuditCleanupJob();
stopNotificationJob();
stopReminderJob();
stopIssueReminderJob();
stopChecklistReminderJob();
server.close(async () => {
logger.info('HTTP server closed');
// Close database connection
await closePool();
logger.info('Graceful shutdown completed');
process.exit(0);
});
// Force shutdown after 10 seconds
setTimeout(() => {
logger.error('Forced shutdown after timeout');
process.exit(1);
}, 10000);
};
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
} catch (error) {
logger.error('Failed to start server', { error });
process.exit(1);
}
};
// Handle unhandled promise rejections
process.on('unhandledRejection', (reason: Error, _promise: Promise<any>) => {
logger.error('Unhandled Promise Rejection', {
reason: reason.message,
stack: reason.stack,
});
});
// Handle uncaught exceptions
process.on('uncaughtException', (error: Error) => {
logger.error('Uncaught Exception', {
message: error.message,
stack: error.stack,
});
process.exit(1);
});
// Start the server
startServer();