Add container readiness checks and exclude local state from images

Adapted from MikaelKW/nodecast-tv-plus readiness and container context work.

Co-authored-by: MikaelKW <87399352+MikaelKW@users.noreply.github.com>
This commit is contained in:
Technomancer702
2026-10-12 16:39:31 -07:00
parent 7ce5f4693d
commit bd8365efc8
8 changed files with 161 additions and 1 deletions

View File

@ -523,4 +523,4 @@ const users = {
}
};
module.exports = { loadDb, saveDb, sources, hiddenItems, favorites, settings, users, getDefaultSettings, getUserAgent, USER_AGENT_PRESETS };
module.exports = { loadDb, saveDb, checkHealth: readDbForMutation, sources, hiddenItems, favorites, settings, users, getDefaultSettings, getUserAgent, USER_AGENT_PRESETS };

View File

@ -8,6 +8,7 @@ const syncService = require('./services/syncService');
require('./db');
const app = express();
app.locals.ready = false;
const PORT = process.env.PORT || 3000;
// Trust proxy headers (X-Forwarded-Proto, X-Forwarded-For, etc.)
@ -154,6 +155,7 @@ async function loadPlugins() {
// Graceful shutdown handler for plugins with shutdown hooks
process.on('SIGTERM', async () => {
app.locals.ready = false;
console.log('SIGTERM received, shutting down plugins...');
for (const { name, plugin } of loadedPlugins) {
if (plugin && typeof plugin.shutdown === 'function') {
@ -169,6 +171,7 @@ process.on('SIGTERM', async () => {
});
// API Routes
app.get('/api/health', require('./services/health'));
app.use('/api/auth', require('./routes/auth'));
app.use('/api/sources', require('./routes/sources'));
app.use('/api/proxy', require('./routes/proxy'));
@ -205,6 +208,7 @@ app.listen(PORT, async () => {
await loadPlugins().catch(err => {
console.error('Plugin initialization failed:', err);
});
app.locals.ready = true;
// Trigger background sync with delay to allow server to settle
setTimeout(async () => {

18
server/services/health.js Normal file
View File

@ -0,0 +1,18 @@
const database = require('../db');
const { getDb } = require('../db/sqlite');
async function health(req, res) {
res.setHeader('Cache-Control', 'no-store');
if (!req.app.locals.ready) return res.status(503).json({ status: 'unavailable' });
try {
await database.checkHealth();
getDb().prepare('SELECT 1').get();
// Readiness may change while the asynchronous JSON check is running.
if (!req.app.locals.ready) return res.status(503).json({ status: 'unavailable' });
res.json({ status: 'ok' });
} catch {
res.status(503).json({ status: 'unavailable' });
}
}
module.exports = health;