📋 Auditoria de Requisições IXC

📅 01/09/2026 ✍️ Gerado por Claude Code (assistente do portal) Status: Validado com IXC (nosso lado — aguardando confirmação do log do Nalberth)
Raio-x de todos os pontos do portal (dashboards + backends Node) que chamam a API do IXC, classificados por risco de contribuir para o volume de requisições reportado pelo suporte do IXC ("várias requisições por segundo"). Cruzado com o log real do IXC (13:19:07, POST /webservice/v1/cliente_contrato, user-agent "node").

Achado principal — bate com o log do IXC

Todo tráfego do browser (dashboards do site) passa por /root/site/cgi-bin/api.sh, que usa curl — user-agent seria curl/x.x, nunca node. Isso descarta todas as páginas frontend do portal como origem direta do log. UA node só pode vir de um processo Node.js batendo direto na API do IXC.

RISCO ALTO painel-tecnico-mark3/backend — correspondência forte com o log

RISCO LATENTE visao-executiva/backend — processo não está rodando agora

visao-executiva/backend/src/ixc/client.js também usa fetch() nativo (mesma assinatura UA node), e contratos.js comenta carga de "cliente_contrato completo (48k linhas, ~49 páginas)". ps aux não mostra esse processo rodando no momento → não é a origem atual do log, mas fica no radar se for reativado.

RISCO BAIXO pingdesk-monitor/daemon.js — provavelmente não é o log

Chama cliente_contrato (linha 293, contratoUnicoAtivo) via https.request nativo do Node, sem header User-Agent custom — normalmente não manda literalmente a string "node" (diferente de fetch/undici). Disparo por evento (1 lookup por ticket processado), não polling contínuo.

Mapa completo — páginas do portal (frontend, via cgi-bin, UA=curl)

Página / arquivoChamada(s) IXCDisparoProteção hojeVolume típicoRiscoRecomendação
Performance do Time
performance.js
cliente (nome por OS)Manual (Detalhamento / Exportar Excel)✅ Cache de sessão + sequencial 250ms (aplicado 01/09)Até centenas de clientes únicos/mês na 1ª cargaBaixoNenhuma — já corrigido
Performance do Time
performance.js
su_oss_chamado (OS do período)ManualPaginado (rp=500) + concorrência limitadaPoucas páginas/mêsBaixoNenhuma
Suporte Técnico Mobile
suporte-mobile.js
cliente (~3043, ~3414)ManualConcorrência 6, sem cache entre aberturas nem espaçamentoPode passar de 100 clientes únicos/aberturaMédioAplicar cache de sessão + throttle (mesmo padrão do Performance)
Suporte Técnico Mobilesu_oss_chamado, funcionarios, su_oss_chamado_mensagemManualPaginado, concorrência limitadaModeradoBaixoNenhuma por ora
Rota Exata Mensagens
rotaexata-comunicacao.js
cliente (~260, ~400)Auto-refresh 60s enquanto abertoCache local de cliente + concorrência 6, sem espaçamento mínimoSó clientes novos por ciclo, sem throttleMédioEspaçamento mínimo entre requisições; considerar aumentar intervalo
Roteirização de Campo
roteirizador_time.js
cliente (~555, por OS sem coordenada)ManualSem cache/limite visível nesse trechoPode ser dezenasMédioAplicar cache/limite
Roteirização de Camposu_oss_chamado ("Atualizar Coords")Manual (botão)Lotes de 10Só quando clicadoBaixoNenhuma
Roteirização de CampocidadeManual, com cache✅ Cache localBaixoBaixoNenhuma
Acompanhamento Consolidado
acompanhamento-consolidado.js
Nenhuma direta — força reload do pipeline Rota ExataAuto 60s enquanto abertoDepende do cache interno do RotaExataDashAmplifica carga do Rota Exata se as 2 telas ficarem abertasMédio (indireto)Verificar se force=true é necessário todo ciclo
Rota Exata (principal)
rotaexata.js
su_oss_chamado etc. — cliente só via autocomplete manualAuto 60s + frota 60s + ausências 30sNão auditado a fundoAlto volume agregadoMédio-AltoAuditoria dedicada se problema persistir após corrigir Mark3
Time Técnico — Escala 12/36
tecnico.js
funcionarios, su_oss_chamadoManualPaginadoModeradoBaixoNenhuma
Time TécnicoNenhuma (auto-sync 30s é /cgi-bin/ausencias.sh, não IXC)Auto 30sN/AN/A—Nenhuma

Conclusão

O log (cliente_contrato, UA node, 13:19:07) não bate com nenhuma página do site (todas passam por curl via cgi-bin). Bate com o backend painel-tecnico-mark3, especificamente o pipeline de Sinal Alto Preventiva / Sugestões de Antecipação, que faz polling de 15s no frontend e, pra cada técnico ocioso, dispara rajadas de requisições sem nenhum limite de concorrência pra cliente_contrato/cliente/cliente_condominio. Candidato de maior confiança pra explicar "várias requisições por segundo" contínuas, não só picos pontuais.

Segundo lugar (bem atrás): suporte-mobile.js e rotaexata-comunicacao.js têm o mesmo padrão de risco médio que performance.js tinha antes da correção de hoje — mas via curl, não batem com o UA do log.

Correções da Prioridade 1 e 2 aplicadas e testadas ao vivo (ver seções abaixo) — status: Validado com IXC do nosso lado, aguardando confirmação do log do Nalberth.

✅ Correções aplicadas — 01/09/2026

Status: Correção aplicada — aguardando validação com IXC

Nenhum teste ao vivo contra o IXC foi feito pra validar isso — validação abaixo é 100% por leitura de código + simulação com fetch mockado (contagem de chamadas/concorrência antes x depois). Teste real único, coordenado, fica pra combinar.

Prioridade 1 painel-tecnico-mark3/backend

Estimativa de redução: pico de ~100 requisições simultâneas → no máximo 4 em voo a qualquer instante, e a maior parte dos ciclos depois do 1º vira 0 requisições novas (cache de 3min) em vez de repetir tudo a cada 15s. Frequência de ciclo também caiu 6x (15s → 90s).

Deploy: painel-mark3-backend.service reiniciado e frontend rebuildado/redeployado em produção às 14:26 de 01/09/2026 (autorizado). Serviço voltou no ar sem erro, 0 restarts desde então, /health respondendo normal. Nenhum teste que gera carga real foi feito — aguardando confirmação de horário combinado com o Nalberth antes do teste ao vivo coordenado.

Evidência adicional encontrada no log do processo antes do restart (13:20–13:22 de 01/09/2026, poucos minutos antes do deploy): múltiplos unhandledRejection com o corpo de erro literal do IXC — "Too many connections" (MySQL) — nas 3 chamadas (cliente_contrato, cliente, cliente_condominio), inclusive um Promise.all (index 123) em fetchContratoMap às 13:22:07 — confirma ao vivo, com o código antigo ainda rodando, que o volume batia bem acima de 100 requisições simultâneas nesse pipeline. Reforça a causa raiz identificada.

Prioridade 2 Suporte Técnico Mobile — suporte-mobile.js

Antes: _mapComLimite(unicos, 6, ...) nas 2 funções de lookup de cliente (_fetchClienteMap, _fetchClienteEnderecoMapTemp) — só limite de concorrência, sem cache entre aberturas da tela, sem espaçamento mínimo.
Depois: mesmo padrão do Performance do Time — cache de sessão por ID (sem TTL, reseta só com reload) + sequencial com 250ms entre cada requisição.
Redução estimada: reabrir a mesma tela/relatório no mesmo carregamento de página passa de "N requisições de novo" pra 0; na 1ª carga, de rajada de 6 simultâneas sem espaçamento pra 1 por vez, ≥250ms entre elas.

Prioridade 2 Rota Exata Mensagens — rotaexata-comunicacao.js

Antes: _mapComLimite(idsCliente, 6, ...) (2 pontos) rodando dentro do auto-refresh de 60s — cache local (_clienteMap) evitava reconsultar id já visto, mas sem espaçamento entre as chamadas de ids novos.
Depois: cache local mantido; troquei _mapComLimite por loop sequencial com 250ms entre requisições nesses 2 pontos específicos (não mexi no _mapComLimite genérico — ele é reusado por 2 outros pontos deste arquivo que não são chamada ao IXC). Intervalo de auto-refresh: 60s → 90s.
Redução estimada: rajada de até 6 simultâneas → 1 por vez com espaçamento; ciclos de refresh 33% menos frequentes.

Prioridade 2 Roteirização de Campo — roteirizador_time.js

Antes: lookup de cliente por OS sem coordenada, dentro de lotes de 5 (já limitava concorrência a ~5), mas sem cache — cliente repetido em dias diferentes da mesma sessão sempre reconsultava o IXC.
Depois: cache de sessão por id_cliente adicionado (concorrência em lote de 5 mantida como estava — já era razoável, não mexi nisso).
Redução estimada: depende de quanto cliente se repete entre OS/dias na mesma sessão — sem número exato porque não tenho dado real de sobreposição; qualquer repetição agora é 0 requisição extra.

Prioridade 2 Acompanhamento da Rota (Consolidado) — acompanhamento-consolidado.js

Investigado: force=true em RotaExataDash.ensureDataLoaded() não pôde ser removido — nada mais nesta página muda o estado que faria o bloco recarregar sozinho; sem force, o card pararia de atualizar depois da 1ª carga.
Aplicado: intervalo de refresh 60s → 120s (única redução segura sem quebrar o "ao vivo" do card).

Sem mudança

Rota Exata principal (rotaexata.js): não mexido, conforme pedido — auditoria dedicada depois, só se o problema persistir após validar o Mark3.
visao-executiva/backend: não mexido — processo não está rodando, só monitorar se for reativado.

🔴 Validação real — 01/09/2026

Status: Validado com IXC

Teste ao vivo autorizado, com o Nalberth (suporte IXC) acompanhando em tempo real. Deploy da correção: 14:26 e 14:45 de 01/09/2026 (2ª rodada corrigiu o componente de polling certo — ver nota na seção anterior). Backend reiniciado 2x, 0 erros, 0 restarts inesperados.

Teste 1 — passivo (3 ciclos reais, 90s de espaçamento, 14:46–14:49)

Sem forçar nada — só rodei o código real da rota /sinal-alto-preventiva (mesmos dados do Redis que a tela usa) 3x, espaçado igual ao polling corrigido.
CicloHorárioChamadas IXCConcorrência máx.Técnicos ociosos (reais)
114:46:28110
214:47:58000
314:49:28110

Resultado: 0 técnicos genuinamente ociosos nesse período (condição de negócio: última OS do dia em execução) — pipeline pesado não disparou, sem erro. Não comparável ao pico do incidente (que exigia vários técnicos ociosos ao mesmo tempo), então segui pro teste 2.

Teste 2 — carga forçada (comparável ao incidente), 14:56, coordenado com Nalberth

Como nenhum técnico estava genuinemente ocioso, forcei a condição em memória (só na cópia local dos dados, nada gravado): peguei a última OS real de hoje de 8 técnicos reais — mesmo critério de "última OS" usado pela função de produção (identificarUltimaOsDoDia) — e marquei só essa cópia como status:'EX', mantendo a coordenada real de cada um. Rodei a função de produção real (buildResumoSinalAltoPreventiva) sem alterar nenhum código, contra o IXC de verdade.

Técnicos usados (coordenada real de hoje): EDER PEREIRA FONSECA, WELLINGTON ROBNER DA SILVA, WELLINGTHON SILVA BALBINO, JOANITO APARECIDO DE ALMEIDA, CLAYTON CARVALHO MARIANO, MARCELO SOARES DE ARAUJO, ROQUE PAIVA RIBEIRO NETO, TIAGO DE MIRANDA — 8/8 reconhecidos como ociosos pela função real.

{
  "horario": "2026-09-01T17:56:05.615Z",
  "tecnicosForcados": 8,
  "tecnicosReconhecidosComoOciosos": 8,
  "chamadasIxcTotal": 1445,
  "chamadasPorEndpoint": {
    "radpop_radio_cliente_fibra": 1,
    "cliente_contrato": 576,
    "cliente": 749,
    "cliente_condominio": 119
  },
  "concorrenciaMaxima": 4,
  "duracaoMs": 96481
}

0 erros nesse período no log do processo (sem "Too many connections", sem unhandledRejection) — confirmado via journalctl.

Comparação numérica — antes × depois

MétricaAntes (log real, 13:19–13:22)Depois (teste real, 14:56, carga maior)
Técnicos ociosos simultâneosVários (não cravado — inferido pelos vários polls com erro em sequência)8 (forçado, deliberadamente maior que o incidente original)
Requisições simultâneas de pico≥124 (1 só Promise.all index 123 num único fetchContratoMap, de 1 técnico só)4 (nunca passou disso, mesmo com 1.445 chamadas no total)
Erros do IXC ("Too many connections")Múltiplos, em pelo menos 5 momentos distintos (13:20:47–13:22:50)0
Duração pra resolver o loteInstantâneo (tudo de uma vez, é isso que quebrava)~96s (proposital — mais devagar, sem sobrecarregar)
Confirmado do nosso lado: mesmo com carga sintética MAIOR que o incidente original (8 técnicos de uma vez vs. o que provavelmente ocorreu em 13:19-13:22), a concorrência real ao IXC nunca passou de 4 simultâneas, e não houve nenhum erro "Too many connections" nas 1.445 chamadas feitas. Isso bate com a estimativa da simulação (pico de até 4 em voo).

O que eu não tenho acesso direto: o log do IXC do lado deles (só vejo nosso próprio contador de saída). Pedir confirmação do Nalberth se, do lado do IXC, o padrão de chegada das requisições também apareceu espaçado/sem erro nesse mesmo horário (14:56, ~96s de duração) — essa é a confirmação independente que fecha o ciclo.

🔍 Auditoria — rotaexata.js (Rota Exata principal)

Status: Mapeamento — nenhuma correção aplicada nesta etapa

Pedido explícito: só diagnosticar. rotaexata.js ficou marcado como risco médio-alto na auditoria original, sem investigação a fundo (tinha 3 timers suspeitos: cliente 60s, frota 60s, ausências 30s). Investigado agora item por item.

Achado 1 — 2 dos 3 timers suspeitos NÃO tocam o IXC

A auditoria original listava "auto-refresh de cliente (60s), frota (60s) e ausências (30s)" como suspeitos. Rastreando o código real:

Achado 2 — o que _load() (60s) realmente chama no IXC

FunçãoEndpointPadrãoProteção hojeRisco isolado
_fetchOsIxc(data) (linha 2141)su_oss_chamadoPromise.all de 9 chamadas fixas (1 por status: EN/DS/EX/AG/RAG/AA/AN/AS/F), rp=500 cadaNenhum cache/limite, mas N é fixo (9), não escala com nº de clientes/OS — não é o mesmo padrão do incidente Mark3 (que escalava por contrato)Baixo
_correlacionarOsManuais (linha 2288, chama _buscarOsPorIdClienteBruto)su_oss_chamado (por id_cliente)Sequencial (for + await, não Promise.all), 1 por vez✅ Rate limit de 250-300ms entre chamadas (já existia, comentário do próprio código cita o padrão) + cache persistido (osLink via cgi-bin) pula OS já resolvida — só busca OS manual nova/não vinculadaBaixo
_dispararAutoSync → _processarAutoSyncJobs (linha 4354)su_oss_chamado (escrita — reagendamento/inclusão)Sequencial, 1 por vez✅ 300ms entre chamadas + guard _autoSyncProcessando (não deixa 2 execuções se sobreporem NELA MESMA)Baixo
fetchOsDetalhes / _fetchOsPorIdClientesu_oss_chamado (por id)Só quando não tem no cache✅ Cache (_osCache/_osClienteCache) checado antes de toda chamada, em todos os 5 call-sitesBaixo
Autocomplete de cliente (linha 5733)cliente (busca por nome)1 chamada por digitaçãoManual, sob ação do usuário (já avaliado na auditoria original)Baixo

Achado 3 — o risco real não é "sem proteção", é estrutural

Diferente do painel-tecnico-mark3 (1 backend compartilhado por todos os usuários, corrigido com semáforo global), o rotaexata.js roda inteiro no navegador de cada usuário — cada aba aberta tem seu próprio _refreshTimer independente, sem nenhuma coordenação entre abas/usuários. 2 gaps concretos:

Estimativa de volume

CenárioEstimativa
1 usuário, ciclo típico (60s)9 (status fetch, sempre) + poucas dezenas no máximo de correlação/auto-sync (só o que mudou desde o ciclo anterior, sequencial 300ms cada) — nada simultâneo além dos 9 fixos
5 usuários com a tela aberta ao mesmo tempo, pior coincidência de timingAté ~45 simultâneas do _fetchOsIxc (5 × 9, só se os 5 timers calharem de disparar no mesmo instante) + até 5 requisições sequenciais concorrentes (1 por usuário) das rotinas de 300ms
_load() sem guard, ciclo lento (raro, dia de muita OS manual/auto-sync)Dobra temporariamente por usuário afetado (2× 9 = 18) até o ciclo atrasado terminar

Pra comparação: o pico confirmado do incidente Mark3 foi ≥124 requisições simultâneas de um só técnico, numa só chamada, sem nenhum limite. O pior cenário aqui (~45, e só por coincidência de timing entre usuários) é de outra ordem de grandeza — estruturalmente mais parecido com os riscos médios já listados pra suporte-mobile.js/rotaexata-comunicacao.js do que com o Mark3.

Classificação e recomendação

ItemRiscoRecomendação
Frota (60s)Não aplicávelNão é IXC — nenhuma ação
Ausências (30s)Não aplicávelNão é IXC — nenhuma ação
_fetchOsIxc (9 fixas/ciclo)BaixoSem ação — N fixo, não escala com volume de dados
_correlacionarOsManuais / _dispararAutoSyncBaixoSem ação — já sequencial, já com throttle 300ms e cache
Reentrância de _load()MédioAdicionar guard (skip se ciclo anterior ainda rodando) — barato, mesmo padrão já usado em _autoSyncProcessando e em performance.js (_state.loading)
Multi-aba/multi-usuário sem coordenaçãoMédioEstrutural — exigiria mover o polling pra um backend compartilhado (como o Mark3) ou um lock entre abas. Maior esforço; só vale a pena se o problema persistir na prática. Decisão de vocês.
rotaexata.js não é um "Mark3 2.0": a maior parte do código que toca o IXC já segue o mesmo padrão seguro (sequencial + 300ms + cache) que apliquei nos outros pontos médios da auditoria original. O risco real aqui é estrutural (sem guard de reentrância, sem coordenação entre usuários), não "zero proteção" como estava o Mark3. Nenhuma correção aplicada — aguardando decisão de vocês sobre os 2 itens médios acima.
← Voltar pra Relatórios