mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-25 09:46:47 +00:00
feat(system): background image update checker with stack badges
Adds an ImageUpdateService that queries OCI registry manifest endpoints every 6 hours to compare remote digests against local RepoDigests. Results are cached in a new stack_update_status SQLite table. A pulsing blue dot badge appears in the stack sidebar for stacks with updates available. Manual refresh available via POST /api/image-updates/refresh with a 10-minute rate limit.
This commit is contained in:
@@ -21,6 +21,7 @@ import { HostTerminalService } from './services/HostTerminalService';
|
||||
import { DatabaseService } from './services/DatabaseService';
|
||||
import { NotificationService } from './services/NotificationService';
|
||||
import { MonitorService } from './services/MonitorService';
|
||||
import { ImageUpdateService } from './services/ImageUpdateService';
|
||||
import { templateService } from './services/TemplateService';
|
||||
import { ErrorParser } from './utils/ErrorParser';
|
||||
import { NodeRegistry } from './services/NodeRegistry';
|
||||
@@ -1530,6 +1531,34 @@ app.post('/api/templates/deploy', async (req: Request, res: Response) => {
|
||||
}
|
||||
});
|
||||
|
||||
// =========================
|
||||
// Image Update Checker API
|
||||
// =========================
|
||||
|
||||
app.get('/api/image-updates', authMiddleware, (_req: Request, res: Response) => {
|
||||
try {
|
||||
const updates = DatabaseService.getInstance().getStackUpdateStatus();
|
||||
res.json(updates);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch image update status:', error);
|
||||
res.status(500).json({ error: 'Failed to fetch image update status' });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/image-updates/refresh', authMiddleware, (_req: Request, res: Response) => {
|
||||
try {
|
||||
const triggered = ImageUpdateService.getInstance().triggerManualRefresh();
|
||||
if (!triggered) {
|
||||
res.status(429).json({ error: 'Rate limited. Please wait at least 10 minutes between manual refreshes.' });
|
||||
return;
|
||||
}
|
||||
res.json({ success: true, message: 'Image update check started in background.' });
|
||||
} catch (error) {
|
||||
console.error('Failed to trigger image update refresh:', error);
|
||||
res.status(500).json({ error: 'Failed to trigger refresh' });
|
||||
}
|
||||
});
|
||||
|
||||
// =========================
|
||||
// Node Management API
|
||||
// =========================
|
||||
@@ -1673,6 +1702,9 @@ async function startServer() {
|
||||
// Start Background Watchdog
|
||||
MonitorService.getInstance().start();
|
||||
|
||||
// Start Background Image Update Checker
|
||||
ImageUpdateService.getInstance().start();
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user