Files
cmdb-insight/backend/src/routes/cache.ts
Bert Hausmans a7f8301196 Add database adapter system, production deployment configs, and new dashboard components
- Add PostgreSQL and SQLite database adapters with factory pattern
- Add migration script for SQLite to PostgreSQL
- Add production Dockerfiles and docker-compose configs
- Add deployment documentation and scripts
- Add BIA sync dashboard and matching service
- Add data completeness configuration and components
- Add new dashboard components (BusinessImportanceComparison, ComplexityDynamics, etc.)
- Update various services and routes
- Remove deprecated management-parameters.json and taxonomy files
2026-01-14 00:38:40 +01:00

159 lines
4.7 KiB
TypeScript

/**
* Cache management routes
*
* Provides endpoints for cache status and manual sync triggers.
*/
import { Router, Request, Response } from 'express';
import { cacheStore } from '../services/cacheStore.js';
import { syncEngine } from '../services/syncEngine.js';
import { logger } from '../services/logger.js';
import { OBJECT_TYPES } from '../generated/jira-schema.js';
import type { CMDBObjectTypeName } from '../generated/jira-types.js';
const router = Router();
// Get cache status
router.get('/status', async (req: Request, res: Response) => {
try {
const cacheStats = await cacheStore.getStats();
const syncStatus = await syncEngine.getStatus();
// Compare cache count with Jira count for ApplicationComponent
let jiraComparison: { jiraCount?: number; cacheCount: number; difference?: number } | undefined;
if (cacheStats.objectsByType['ApplicationComponent'] !== undefined) {
try {
const { jiraAssetsClient } = await import('../services/jiraAssetsClient.js');
const { OBJECT_TYPES } = await import('../generated/jira-schema.js');
const typeDef = OBJECT_TYPES['ApplicationComponent'];
if (typeDef) {
const searchResult = await jiraAssetsClient.searchObjects(`objectType = "${typeDef.name}"`, 1, 1);
const jiraCount = searchResult.totalCount;
const cacheCount = cacheStats.objectsByType['ApplicationComponent'] || 0;
jiraComparison = {
jiraCount,
cacheCount,
difference: jiraCount - cacheCount,
};
}
} catch (err) {
logger.debug('Could not fetch Jira count for comparison', err);
}
}
res.json({
cache: cacheStats,
sync: syncStatus,
supportedTypes: Object.keys(OBJECT_TYPES),
jiraComparison,
});
} catch (error) {
logger.error('Failed to get cache status', error);
res.status(500).json({ error: 'Failed to get cache status' });
}
});
// Trigger full sync
router.post('/sync', async (req: Request, res: Response) => {
try {
logger.info('Manual full sync triggered');
// Don't wait for completion - return immediately
syncEngine.fullSync().catch(err => {
logger.error('Full sync failed', err);
});
res.json({
status: 'started',
message: 'Full sync started in background',
});
} catch (error) {
logger.error('Failed to trigger full sync', error);
res.status(500).json({ error: 'Failed to trigger sync' });
}
});
// Trigger sync for a specific object type
router.post('/sync/:objectType', async (req: Request, res: Response) => {
try {
const { objectType } = req.params;
// Validate object type
if (!OBJECT_TYPES[objectType]) {
res.status(400).json({
error: `Unknown object type: ${objectType}`,
supportedTypes: Object.keys(OBJECT_TYPES),
});
return;
}
logger.info(`Manual sync triggered for ${objectType}`);
const result = await syncEngine.syncType(objectType as CMDBObjectTypeName);
res.json({
status: 'completed',
objectType,
stats: result,
});
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Failed to sync object type';
logger.error(`Failed to sync object type ${req.params.objectType}`, error);
// Return 409 (Conflict) if sync is already in progress, otherwise 500
const statusCode = errorMessage.includes('already in progress') ? 409 : 500;
res.status(statusCode).json({
error: errorMessage,
objectType: req.params.objectType,
});
}
});
// Clear cache for a specific type
router.delete('/clear/:objectType', async (req: Request, res: Response) => {
try {
const { objectType } = req.params;
if (!OBJECT_TYPES[objectType]) {
res.status(400).json({
error: `Unknown object type: ${objectType}`,
supportedTypes: Object.keys(OBJECT_TYPES),
});
return;
}
logger.info(`Clearing cache for ${objectType}`);
const deleted = await cacheStore.clearObjectType(objectType as CMDBObjectTypeName);
res.json({
status: 'cleared',
objectType,
deletedCount: deleted,
});
} catch (error) {
logger.error(`Failed to clear cache for ${req.params.objectType}`, error);
res.status(500).json({ error: 'Failed to clear cache' });
}
});
// Clear entire cache
router.delete('/clear', async (req: Request, res: Response) => {
try {
logger.info('Clearing entire cache');
await cacheStore.clearAll();
res.json({
status: 'cleared',
message: 'Entire cache cleared',
});
} catch (error) {
logger.error('Failed to clear cache', error);
res.status(500).json({ error: 'Failed to clear cache' });
}
});
export default router;