fix: remove cache do configService; remove cacheService.js (nao usado)

- configService agora le direto do banco (sem TTL, sem stale data)
- invalidarConfig virou no-op (não há cache para invalidar)
- cacheService.js removido (so era usado pelo configService)
- endpoint /metrics sem referencia ao cacheService
This commit is contained in:
2026-07-01 17:07:18 +00:00
parent bc03f5dc1d
commit 44a84301a3
6 changed files with 11 additions and 144 deletions
-17
View File
@@ -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 (_) {}
},
},
];
// ============================================================
+1 -1
View File
@@ -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', ?)`,
+1 -1
View File
@@ -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) {
-1
View File
@@ -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(),
});
-89
View File
@@ -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 };
+9 -35
View File
@@ -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<object>} Linha da tabela CHATC2_CONFIGURACOES_EMPRESA
* @returns {Promise<object>}
*/
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));
}