async function loadCacheStats() {
const container = document.getElementById('cacheStatsContent');
if (!container) return;
container.innerHTML = `
`;
try {
const [cacheResponse, sqliteResponse] = await Promise.all([
fetch('/api/cache/status'),
fetch('/api/database/sqlite/status')
]);
const cacheData = await cacheResponse.json();
const sqliteData = await sqliteResponse.json();
if (!cacheData.success) {
container.innerHTML = `Redis cache unavailable: ${cacheData.error || 'Unknown error'}
`;
return;
}
const stats = cacheData.stats || {};
const health = cacheData.health || {};
let html = `
Redis Cache
${stats.country_keys || 0}
Country Keys
${stats.config_keys || 0}
Config Keys
${stats.total_size_mb || 0} MB
Cache Size
${health.memory_used_mb || 0} MB
Memory Used
`;
if (sqliteData.success && sqliteData.exists) {
const modifiedDate = new Date(sqliteData.modified).toLocaleString();
html += `
SQLite Cache Database
${sqliteData.total_countries || 0}
Countries
${(sqliteData.total_networks || 0).toLocaleString()}
Total Networks
${sqliteData.file_size_mb || 0} MB
Database Size
Last Modified
${modifiedDate}
`;
if (sqliteData.top_countries && sqliteData.top_countries.length > 0) {
html += `
Top countries:
${sqliteData.top_countries.map(c =>
`${c.code}: ${c.networks.toLocaleString()}`
).join('')}
`;
}
} else {
html += `
SQLite cache database not available
`;
}
container.innerHTML = html;
} catch (error) {
console.error('Error loading cache stats:', error);
container.innerHTML = `
Failed to load statistics: ${error.message}
`;
}
}
async function flushCache() {
const confirmed = await showConfirmModal(
'Flush Redis Cache',
'Are you sure you want to flush ALL Redis cache?
' +
'This will delete:
' +
'• All cached country data
' +
'• All cached configurations
' +
'• Force regeneration for future requests
' +
'This action cannot be undone!'
);
if (!confirmed) return;
try {
showFlushingIndicator();
const response = await fetch('/api/cache/flush', {
method: 'POST',
headers: {'Content-Type': 'application/json'}
});
const data = await response.json();
hideFlushingIndicator();
if (data.success) {
showToast('success', 'Cache Flushed', 'All Redis cache has been cleared successfully!');
loadCacheStats();
} else {
showToast('danger', 'Error', 'Failed to flush cache: ' + (data.error || 'Unknown error'));
}
} catch (error) {
hideFlushingIndicator();
showToast('danger', 'Error', 'Network error: ' + error.message);
}
}
function showConfirmModal(title, message) {
return new Promise((resolve) => {
const modalId = 'confirmModal_' + Date.now();
const modalHtml = `
`;
document.body.insertAdjacentHTML('beforeend', modalHtml);
const modalEl = document.getElementById(modalId);
const modal = new bootstrap.Modal(modalEl);
modalEl.querySelector('#confirmBtn').addEventListener('click', () => {
modal.hide();
resolve(true);
});
modalEl.addEventListener('hidden.bs.modal', () => {
modalEl.remove();
resolve(false);
});
modal.show();
});
}
function showFlushingIndicator() {
const indicator = document.createElement('div');
indicator.id = 'flushingIndicator';
indicator.className = 'position-fixed top-50 start-50 translate-middle';
indicator.style.zIndex = '9999';
indicator.innerHTML = `
Flushing...
Flushing Cache...
Please wait
`;
document.body.appendChild(indicator);
}
function hideFlushingIndicator() {
const indicator = document.getElementById('flushingIndicator');
if (indicator) {
indicator.remove();
}
}
function showToast(type, title, message) {
const toastId = 'toast_' + Date.now();
const bgClass = type === 'success' ? 'bg-success' : type === 'danger' ? 'bg-danger' : 'bg-warning';
const toastHtml = `
`;
document.body.insertAdjacentHTML('beforeend', toastHtml);
const toastEl = document.getElementById(toastId);
const toast = new bootstrap.Toast(toastEl, { delay: 5000 });
toast.show();
toastEl.addEventListener('hidden.bs.toast', () => {
toastEl.parentElement.remove();
});
}
function showAlert(type, message) {
showToast(type, type === 'success' ? 'Success' : 'Error', message);
}
document.addEventListener('DOMContentLoaded', function() {
const statsPanel = document.getElementById('cacheStatsPanel');
if (statsPanel) {
statsPanel.addEventListener('shown.bs.collapse', function() {
loadCacheStats();
});
}
});