Fix: убран process.exit(1) — приложение не падает, показывает сообщение об ошибке. Версия 0.1.14
This commit is contained in:
@@ -61,23 +61,16 @@ async function start() {
|
||||
const { pool } = require('./src/db');
|
||||
app.use(createSessionMiddleware(pool));
|
||||
|
||||
// ── Fail-fast в production ────────────────────────────────────────────────
|
||||
// Если секреты не заданы — приложение в проде немедленно падает.
|
||||
// Дефолтные значения — только для локальной разработки.
|
||||
// ── Fail-fast в production (без exit — сообщение в лог) ────────────────────
|
||||
const DEFAULT_SESSION = 'dev-session-secret-change-me';
|
||||
let fatalError = null;
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
const DEFAULT_SESSION = 'dev-session-secret-change-me';
|
||||
if (!process.env.SESSION_SECRET || process.env.SESSION_SECRET === DEFAULT_SESSION) {
|
||||
console.error('FATAL: SESSION_SECRET не задан или равен дефолту в production!');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!process.env.DB_PASS) {
|
||||
console.error('FATAL: DB_PASS не задан в production!');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!process.env.CSRF_SECRET || process.env.CSRF_SECRET === 'dev-csrf-secret-change-in-prod') {
|
||||
console.error('FATAL: CSRF_SECRET не задан или равен дефолту в production!');
|
||||
process.exit(1);
|
||||
}
|
||||
if (!process.env.SESSION_SECRET || process.env.SESSION_SECRET === DEFAULT_SESSION)
|
||||
fatalError = 'SESSION_SECRET не задан или равен дефолту в production';
|
||||
else if (!process.env.DB_PASS)
|
||||
fatalError = 'DB_PASS не задан в production';
|
||||
else if (!process.env.CSRF_SECRET || process.env.CSRF_SECRET === 'dev-csrf-secret-change-in-prod')
|
||||
fatalError = 'CSRF_SECRET не задан или равен дефолту в production';
|
||||
}
|
||||
|
||||
// k8s liveness + readiness probes
|
||||
@@ -91,6 +84,15 @@ async function start() {
|
||||
}
|
||||
});
|
||||
|
||||
// Если фатальная ошибка конфигурации — показываем на всех страницах сообщение
|
||||
if (fatalError) {
|
||||
console.error(fatalError);
|
||||
app.use((req, res) => {
|
||||
res.status(503).type('html').send(errorPage(fatalError));
|
||||
});
|
||||
return app;
|
||||
}
|
||||
|
||||
// JWKS endpoint для валидации токенов внешними сервисами (только в mock-режиме)
|
||||
if (auth.jwksHandler) app.get('/.well-known/jwks.json', auth.jwksHandler);
|
||||
|
||||
@@ -136,20 +138,24 @@ async function start() {
|
||||
if (require.main === module) {
|
||||
start()
|
||||
.then(a => {
|
||||
const server = a.listen(PORT, () => console.log('Server on port ' + PORT));
|
||||
a.listen(PORT, () => console.log('Server on port ' + PORT));
|
||||
// Graceful shutdown по SIGTERM (k8s)
|
||||
process.on('SIGTERM', () => {
|
||||
console.log('SIGTERM — shutting down...');
|
||||
server.close(() => {
|
||||
console.log('HTTP closed');
|
||||
const { pool } = require('./src/db');
|
||||
pool.end().then(() => { console.log('DB pool closed'); process.exit(0); });
|
||||
});
|
||||
const { pool } = require('./src/db');
|
||||
pool.end().then(() => { console.log('DB pool closed'); process.exit(0); });
|
||||
setTimeout(() => { console.log('Forced exit'); process.exit(0); }, 10000);
|
||||
});
|
||||
return server;
|
||||
})
|
||||
.catch(e => { console.error('Startup error:', e); process.exit(1); });
|
||||
.catch(e => {
|
||||
console.error('Startup error:', e.message);
|
||||
// Не падаем — запускаем HTTP с сообщением об ошибке
|
||||
const errorApp = require('express')();
|
||||
errorApp.use((req, res) => {
|
||||
res.status(503).type('html').send('<html><head><meta charset="utf-8"><title>Авария</title></head><body style="font-family:sans-serif;padding:40px;text-align:center"><h1>⚙️ Сервис временно недоступен</h1><p>Причина: ' + (e.message || 'неизвестна') + '</p><p>Попробуйте обновить страницу через минуту</p></body></html>');
|
||||
});
|
||||
errorApp.listen(PORT, () => console.log('Server on port ' + PORT + ' (ERROR MODE)'));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { start };
|
||||
|
||||
Reference in New Issue
Block a user