diff --git a/scripts/migrationRunner.js b/scripts/migrationRunner.js index a26639a..9bc02ea 100644 --- a/scripts/migrationRunner.js +++ b/scripts/migrationRunner.js @@ -137,23 +137,6 @@ const MIGRACOES = [ 'ALTER TABLE CHATC2_CONVERSAS ADD CON_RESOLUCAO VARCHAR(4000)', ], }, - - // ---------------------------------------------------------- - // MIGRAÇÃO 25: Generator para MENSAGEM_CLIENTES (tabela do ERP) - // ---------------------------------------------------------- - { - id: 25, - descricao: 'Criar generator para MENSAGEM_CLIENTES (tabela ja existe no ERP)', - sql: [ - 'CREATE GENERATOR GEN_MENSAGEM_CLIENTES', - ], - async after(alias) { - try { - const r = await db.query(alias, 'SELECT COALESCE(MAX(MSC_CODIGO_ID),0)+1 AS V FROM MENSAGEM_CLIENTES'); - await db.execute(alias, 'SET GENERATOR GEN_MENSAGEM_CLIENTES TO ' + (r[0]?.V || 1)); - } catch (_) {} - }, - }, ]; // ============================================================ diff --git a/src/controllers/chatController.js b/src/controllers/chatController.js index 404b6d3..af2fd60 100644 --- a/src/controllers/chatController.js +++ b/src/controllers/chatController.js @@ -736,7 +736,7 @@ class ChatController { // Salva resolução na tabela MENSAGENS_CLIENTES como aviso (se configurado) if (isS(fl.CFE_RESOLUCAO_SALVAR_MSC) && resolucao && c.CON_CLIENTE_ID) { try { - const mscId = await db.nextId(alias, 'GEN_MENSAGEM_CLIENTES'); + const mscId = await db.nextId(alias, 'GEN_MENSAGEM_CLIENTES_ID'); await db.execute(alias, `INSERT INTO MENSAGEM_CLIENTES (MSC_CODIGO_ID, MSC_CLIENTE_ID, MSC_USUARIO_ID, MSC_DT_MENSAGEM, MSC_AVISO, MSC_MENSAGEM) VALUES (?, ?, ?, CURRENT_TIMESTAMP, 'S', ?)`, diff --git a/src/database.js b/src/database.js index 69e2cd7..aa730ba 100644 --- a/src/database.js +++ b/src/database.js @@ -98,7 +98,7 @@ const GENERATORS = [ 'GEN_CHATC2_CSAT_AVALIACOES', 'GEN_CHATC2_MOTIVOS_ATENDIMENTO', 'GEN_CHATC2_AGENDAMENTOS', - 'GEN_MENSAGEM_CLIENTES', + 'GEN_MENSAGEM_CLIENTES_ID', ]; async function nextId(alias, generatorName) { diff --git a/src/routes/index.js b/src/routes/index.js index 8a8eaa7..1a9f245 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -39,7 +39,6 @@ router.get('/api/:alias/metrics', authenticateToken, (req, res) => { uptimeSeconds: Math.floor(process.uptime()), memory: process.memoryUsage(), metrics: metrics.getAll(), - cache: require('../services/cacheService').stats(), pool: require('../database').poolStats(), timestamp: new Date().toISOString(), }); diff --git a/src/services/cacheService.js b/src/services/cacheService.js deleted file mode 100644 index 61c53b4..0000000 --- a/src/services/cacheService.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Cache em memória com TTL. - * - * Simples, sem dependências externas. Usado para evitar consultas repetidas - * ao banco para dados que mudam raramente (ex: configurações da empresa). - * - * Uso: - * const cache = require('../services/cacheService'); - * let valor = cache.get('chave'); - * if (!valor) { - * valor = await db.query(...); - * cache.set('chave', valor, 60000); // TTL 60s - * } - */ - -const store = new Map(); - -/** - * Armazena um valor no cache. - * @param {string} key - * @param {*} value - * @param {number} [ttlMs=60000] - Tempo de vida em ms (padrão: 1 minuto) - */ -function set(key, value, ttlMs = 60000) { - store.set(key, { - value, - expiresAt: Date.now() + ttlMs, - }); -} - -/** - * Recupera um valor do cache. Retorna undefined se expirado ou inexistente. - * @param {string} key - * @returns {*|undefined} - */ -function get(key) { - const entry = store.get(key); - if (!entry) return undefined; - if (Date.now() > entry.expiresAt) { - store.delete(key); - return undefined; - } - return entry.value; -} - -/** - * Invalida uma chave específica. - * @param {string} key - */ -function del(key) { - store.delete(key); -} - -/** - * Invalida todas as chaves que começam com o prefixo. - * Útil para invalidar todo o cache de uma empresa (ex: 'config:5:'). - * @param {string} prefix - */ -function delByPrefix(prefix) { - for (const key of store.keys()) { - if (key.startsWith(prefix)) { - store.delete(key); - } - } -} - -/** - * Retorna estatísticas do cache para debug. - */ -function stats() { - let total = 0, valid = 0; - const now = Date.now(); - for (const [, entry] of store) { - total++; - if (entry.expiresAt > now) valid++; - } - return { total, valid, expired: total - valid }; -} - -// Limpeza periódica de entradas expiradas (evita vazamento de memória) -const intervalo = setInterval(() => { - const now = Date.now(); - for (const [key, entry] of store) { - if (entry.expiresAt <= now) store.delete(key); - } -}, 60000); -if (intervalo.unref) intervalo.unref(); - -module.exports = { set, get, del, delByPrefix, stats }; diff --git a/src/services/configService.js b/src/services/configService.js index 1aac193..adee264 100644 --- a/src/services/configService.js +++ b/src/services/configService.js @@ -1,56 +1,31 @@ /** - * Serviço de configuração da empresa com cache. + * Serviço de configuração da empresa (sem cache). * - * As flags CFE_* (triagem, saudação, CSAT, etc.) são lidas em toda operação - * de chat/triagem/webhook. Este serviço armazena em cache (TTL 2min) e - * invalida automaticamente quando as configurações são alteradas. + * Lê direto do banco — sem TTL, sem stale data. + * As flags CFE_* são consultadas a cada operação, então refletem + * imediatamente qualquer alteração salva em Settings. */ const db = require('../database'); -const cache = require('./cacheService'); - -const TTL = 2 * 60 * 1000; // 2 minutos /** - * Retorna a configuração completa de uma empresa (cacheada). - * Invalidação: chamar invalidarConfig(alias, empresaId) após salvar settings. + * Retorna a configuração completa de uma empresa (direto do banco). * * @param {string} alias * @param {number} empresaId - * @returns {Promise} Linha da tabela CHATC2_CONFIGURACOES_EMPRESA + * @returns {Promise} */ async function getConfig(alias, empresaId) { - const key = 'cfg:' + alias + ':' + empresaId; - const cached = cache.get(key); - if (cached) return cached; - - // Garante que o registro existe (insere se não existir) await garantirRegistro(alias, empresaId); - const result = await db.query(alias, 'SELECT * FROM CHATC2_CONFIGURACOES_EMPRESA WHERE CFE_EMPRESA_ID = ?', [empresaId]); - - const config = result[0] || {}; - cache.set(key, config, TTL); - return config; + return result[0] || {}; } -/** - * Invalida o cache de configuração de uma empresa. - * Deve ser chamado após salvar alterações nas configurações. - * - * @param {string} alias - * @param {number} empresaId - */ -function invalidarConfig(alias, empresaId) { - cache.del('cfg:' + alias + ':' + empresaId); -} +/** No-op: não há cache para invalidar */ +function invalidarConfig() {} -/** - * Garante que existe um registro de configuração para a empresa. - * Idempotente — se já existe, não faz nada. - */ async function garantirRegistro(alias, empresaId) { try { const existe = await db.query(alias, @@ -63,7 +38,6 @@ async function garantirRegistro(alias, empresaId) { `, [empresaId]); } } catch (e) { - // Tabela pode não existir ainda — ignora if (!e.message.includes('unknown') && !e.message.includes('não encontrado')) { console.error('[ConfigService] Erro ao garantir registro:', e.message.substring(0, 100)); }