V2: guarda de envio real (SEND_ENABLED/FORCE_SEND), idempotencia por send_key e Slack nativo
- src/v2/sendGuard.js (novo): canSend() reduz SHADOW_MODE/DEV_MODE/ SEND_ENABLED/FORCE_SEND a uma formula unica testada exaustivamente (secao 15 do ciclo final: matriz completa de guarda de seguranca). computeMessageHash/buildSendKey/isDuplicate implementam a chave logica de idempotencia da secao 13 (report_type+periodo+destino+hash). - src/v2/config.js: SEND_ENABLED, FORCE_SEND, SLACK_DESTINATION. - src/v2/pipeline.js: buildReport agora calcula envio.pode_enviar/ motivo_guarda/duplicata_bloqueada/send_key a partir de triggerType (.mode) e sendLogRows (Data Table de log de envios). - tools/build_v2_workflow*.js: novo Data Table 'Buscar Log de Envios', troca do HTTP Slack com webhook placeholder por node Slack nativo (credencial real lNqwBBrtLfkRqw2X, reaproveitada do projeto irmao Coordenador GLPI), branches de sucesso/falha gravando o log de envio so apos confirmacao real do Slack. - test/sendGuard.test.js, test/workflowStructure.test.js (novos): cobrem a matriz de guarda de seguranca e travam regressao do bug de timeout (executeOnce=true nos 8 nodes de leitura em lote) e do bug de sendGuard.js nao concatenado no Code node gerado. - Corrigido bug real encontrado nesta sessao: sendGuard.js nao estava na lista de modulos concatenados pelo gerador, deixando canSend/ computeMessageHash/buildSendKey undefined em runtime. - Deployado e validado ao vivo no DEV (workflow 3x5kb58TeBCvirm6): n8n_validate_workflow -> valid:true, 0 erros, executeOnce preservado nos 9 nodes de leitura em lote. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
bdfa675d89
commit
64ddfb9b7b
@@ -21,6 +21,8 @@
|
||||
* previousPendentes -> pendentes do periodo comparavel anterior (ou null)
|
||||
* altaPrioridadeAnterior -> alta_prioridade_pendentes do periodo anterior (ou null)
|
||||
* todayIso -> data de hoje (YYYY-MM-DD), para carimbar a memoria
|
||||
* triggerType -> 'scheduled' | 'manual' (de $execution.mode no n8n)
|
||||
* sendLogRows -> linhas atuais da Data Table de log de envios (idempotencia)
|
||||
*
|
||||
* aiCall.attempted=false quando AI_ENABLED=false (nunca chamou a IA).
|
||||
* aiCall.error != null quando a chamada HTTP falhou/deu timeout (n8n
|
||||
@@ -44,6 +46,7 @@ const {
|
||||
} = require('./insights');
|
||||
const { buildTicketContext, parseAiResponse } = require('./aiSchema');
|
||||
const { formatFallbackMessage, formatShortMessage } = require('./format');
|
||||
const { canSend, computeMessageHash, buildSendKey } = require('./sendGuard');
|
||||
|
||||
function computeEvidenceHash(evidenceTicketIds) {
|
||||
const ordenado = [...evidenceTicketIds].sort((a, b) => a - b);
|
||||
@@ -205,6 +208,35 @@ function buildReport(input, config) {
|
||||
config
|
||||
);
|
||||
|
||||
// --- guarda de envio + idempotencia (secoes 12/13/15 do ciclo final) ---
|
||||
// triggerType/sendLogRows sao dados de EXECUCAO (nao vem do SQL) —
|
||||
// fornecidos pelo Code node do n8n a partir de $execution.mode e da
|
||||
// Data Table de log de envios. Ver src/v2/sendGuard.js.
|
||||
const messageHash = computeMessageHash(mensagemV2);
|
||||
const sendKey = buildSendKey({
|
||||
reportType: period.history_bucket || period.tipo_periodo,
|
||||
periodStart: period.data_inicio,
|
||||
periodEnd: period.data_fim,
|
||||
destination: config.SLACK_DESTINATION || 'destino_nao_configurado',
|
||||
messageHash,
|
||||
});
|
||||
const guarda = canSend({ triggerType: input.triggerType, config });
|
||||
const jaEnviado = (input.sendLogRows || []).some(
|
||||
(r) => r && r.send_key === sendKey && r.status === 'success'
|
||||
);
|
||||
const envio = {
|
||||
trigger_type: input.triggerType || 'desconhecido',
|
||||
report_type: period.history_bucket || period.tipo_periodo,
|
||||
period_start: period.data_inicio,
|
||||
period_end: period.data_fim,
|
||||
destino: config.SLACK_DESTINATION || null,
|
||||
send_key: sendKey,
|
||||
message_hash: messageHash,
|
||||
pode_enviar: guarda.podeEnviar && !jaEnviado,
|
||||
motivo_guarda: guarda.motivo,
|
||||
duplicata_bloqueada: guarda.podeEnviar && jaEnviado,
|
||||
};
|
||||
|
||||
const observabilidade = {
|
||||
periodo: period.periodo_label,
|
||||
tipo_periodo: period.tipo_periodo,
|
||||
@@ -238,6 +270,7 @@ function buildReport(input, config) {
|
||||
insights_suprimidos: suppressed,
|
||||
memoria_atualizacoes: [...insightsComEstado.map((i) => i.memoryRow), ...normalizacoes],
|
||||
anomalias_deterministicas: { spikesCategoria, spikesCliente, concentracaoCliente, tendenciaBacklog },
|
||||
envio,
|
||||
observabilidade,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user