210 lines
6.5 KiB
JavaScript
210 lines
6.5 KiB
JavaScript
/**
|
|
* CacheManager - Gerenciador central do sistema de cache
|
|
* Coordena IndexedDB, sincronização e acesso aos dados
|
|
*/
|
|
|
|
class CacheManager {
|
|
constructor(config = {}) {
|
|
this.dbName = config.dbName || 'AcoCalcProDB';
|
|
this.version = config.version || 1;
|
|
this.db = null;
|
|
this.config = {
|
|
debug: config.debug || false,
|
|
autoSync: config.autoSync || false,
|
|
cacheExpiry: config.cacheExpiry || (7 * 24 * 60 * 60 * 1000), // 7 dias
|
|
...config
|
|
};
|
|
|
|
this.stores = [
|
|
'cantoneiras',
|
|
'barras',
|
|
'barras_chatas',
|
|
'barras_roscadas',
|
|
'tubos_circulares',
|
|
'tubos_rhs',
|
|
'chapas',
|
|
'perfis_i',
|
|
'perfis_w',
|
|
'perfis_hp',
|
|
'_metadata',
|
|
'_config'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Inicializa o IndexedDB
|
|
*/
|
|
async init() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!window.indexedDB) {
|
|
console.warn('⚠️ IndexedDB não disponível - usando fallback para CSV');
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
const request = indexedDB.open(this.dbName, this.version);
|
|
|
|
request.onerror = () => {
|
|
console.error('❌ Erro ao abrir IndexedDB:', request.error);
|
|
reject(request.error);
|
|
};
|
|
|
|
request.onsuccess = () => {
|
|
this.db = request.result;
|
|
if (this.config.debug) {
|
|
console.log('✅ IndexedDB inicializado:', this.dbName);
|
|
}
|
|
resolve(true);
|
|
};
|
|
|
|
request.onupgradeneeded = (event) => {
|
|
const db = event.target.result;
|
|
|
|
// Criar stores para cada tipo de perfil
|
|
this.stores.forEach(storeName => {
|
|
if (!db.objectStoreNames.contains(storeName)) {
|
|
const store = db.createObjectStore(storeName, { keyPath: 'id' });
|
|
|
|
// Criar índices para busca rápida
|
|
if (storeName !== '_metadata' && storeName !== '_config') {
|
|
store.createIndex('nome', 'nome', { unique: false });
|
|
store.createIndex('tipo', 'tipo', { unique: false });
|
|
}
|
|
|
|
if (this.config.debug) {
|
|
console.log(`✅ Store criada: ${storeName}`);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Verifica saúde do cache
|
|
*/
|
|
async checkHealth() {
|
|
if (!this.db) {
|
|
return {
|
|
healthy: false,
|
|
error: 'Database not initialized'
|
|
};
|
|
}
|
|
|
|
try {
|
|
const stats = {};
|
|
|
|
for (const storeName of this.stores) {
|
|
if (storeName.startsWith('_')) continue;
|
|
|
|
const count = await this.count(storeName);
|
|
const metadata = await this.getMetadata(storeName);
|
|
|
|
stats[storeName] = {
|
|
count,
|
|
lastSync: metadata?.lastSync || null,
|
|
size: metadata?.size || 0
|
|
};
|
|
}
|
|
|
|
return {
|
|
healthy: true,
|
|
stats,
|
|
totalSize: Object.values(stats).reduce((sum, s) => sum + s.size, 0)
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
healthy: false,
|
|
error: error.message
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Limpa todo o cache
|
|
*/
|
|
async clearAll() {
|
|
if (!this.db) {
|
|
throw new Error('Database not initialized');
|
|
}
|
|
|
|
const promises = this.stores
|
|
.filter(s => !s.startsWith('_'))
|
|
.map(storeName => this.clear(storeName));
|
|
|
|
await Promise.all(promises);
|
|
|
|
if (this.config.debug) {
|
|
console.log('✅ Todo o cache foi limpo');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Conta registros em uma store
|
|
*/
|
|
async count(storeName) {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction([storeName], 'readonly');
|
|
const store = transaction.objectStore(storeName);
|
|
const request = store.count();
|
|
|
|
request.onsuccess = () => resolve(request.result);
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Limpa uma store específica
|
|
*/
|
|
async clear(storeName) {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction([storeName], 'readwrite');
|
|
const store = transaction.objectStore(storeName);
|
|
const request = store.clear();
|
|
|
|
request.onsuccess = () => resolve();
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Busca metadados de um tipo
|
|
*/
|
|
async getMetadata(tipo) {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction(['_metadata'], 'readonly');
|
|
const store = transaction.objectStore('_metadata');
|
|
const request = store.get(tipo);
|
|
|
|
request.onsuccess = () => resolve(request.result || null);
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Salva metadados de um tipo
|
|
*/
|
|
async setMetadata(tipo, metadata) {
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction(['_metadata'], 'readwrite');
|
|
const store = transaction.objectStore('_metadata');
|
|
const request = store.put({ tipo, ...metadata });
|
|
|
|
request.onsuccess = () => resolve();
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Retorna estatísticas de uso
|
|
*/
|
|
getStats() {
|
|
return this.checkHealth();
|
|
}
|
|
}
|
|
|
|
// Exportar para uso global
|
|
window.CacheManager = CacheManager;
|
|
|
|
console.log('✅ CacheManager carregado');
|