Pular para conteúdo

Tratamento de erros do endpoint /api/v1/xadm

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-06

Este documento descreve o que acontece quando um PUT/DELETE em /api/v1/xadm falha: como o erro é persistido, quando o Sentry é acionado, e como a serialização de requests preserva a ordem esperada pelo ERP.

Relacionado: src/main/java/br/com/xadm/service/XadmService.java, XadmApplyService.java.


Contrato HTTP (inalterado)

O endpoint sempre devolve HTTP 200 quando o payload é JSON válido, mesmo em falha de persistência. O resultado real está no corpo:

Corpo Significado
{"requestId": N, "resultado": "SUCESSO", "mensagem": null} Persistência comitou.
{"requestId": N, "resultado": "ERRO", "mensagem": "..."} Persistência falhou.

HTTP 400 é devolvido apenas para JSON malformado (JsonProcessingException). Esses erros não vão para o Sentry (são considerados erros de cliente).


Serialização de requests XADM

O ERP especifica pares DELETE → PUT para limpar/reescrever estado. Se o integrador processasse esses requests em paralelo, dois cenários quebrariam:

  1. Inversão de ordem: PUT comita primeiro, DELETE comita por cima → linha fica marcada deleted quando deveria ter o estado novo.
  2. Deadlock PostgreSQL (ERROR: deadlock detected, SQLState 40P01): duas transações concorrentes fazendo UPDATE na mesma linha (ex.: itenspedamx.seq_n) se travam mutuamente — o Postgres aborta uma; o request quebra com 200 ERRO.

Solução: XadmService envolve as chamadas a applyPut/applyDelete em um ReentrantLock(fair=true) global. Apenas um request XADM passa pelo trecho de persistência por vez, na ordem (aproximadamente) FIFO de chegada. Casa com o comportamento sequencial do integrador antigo.

Trade-off: throughput cai a 1 request-por-vez no trecho serializado. Volume do XADM é baixo (eventos de negócio do ERP), aceitável. Parsing de JSON e gravação na tabela request (audit) não estão sob o lock — podem acontecer em paralelo.

Limitação: o lock cobre apenas o caminho XADM. Outros endpoints que escrevem nas mesmas tabelas (PowerSync, controllers REST diretos) podem teoricamente colidir com o XADM. Hoje isso é raro o suficiente para não ser tratado; se virar problema, considerar serializar mais amplo ou retomar a estratégia de retry.


Whitelist KNOWN_ORIGENS para Sentry

Apenas erros em requests com Origem na whitelist disparam Sentry.captureException. Origens fora da lista continuam sendo registradas no request (coluna resultado=ERRO, mensagem com detalhe) mas não geram evento no Sentry — evita ruído de chamadas espúrias ou origens internas.

Whitelist atual (XadmService.KNOWN_ORIGENS):

PPEDAMX, PPEDIDO, PBLDI, PNOTAI, PNOTAD, PCSTPROD, PREQUIS, INT-PIED

INT-PIED é a origem do fluxo de entrada PIED (ver decisão 0013).

Origens internas explicitamente fora da whitelist: API_HEALTH, powersync, "?" (quando payload chega sem campo Origem).

Adicionando nova origem: edite XadmService.KNOWN_ORIGENS e recompile/redeploy. Não há config externa.


Tabela de decisão: onde o erro é reportado

Cenário Log Sentry issue
Happy path INFO resultado=SUCESSO —
Falha de persistência, origem conhecida WARN XADM PUT/DEL falhou ✅ com origem/tipo/request_id
Falha de persistência, origem desconhecida WARN XADM PUT/DEL falhou —
JSON malformado (HTTP 400) WARN parse error —
Falha do SDK Sentry (DSN inválido, network) DEBUG Sentry não disponível... —

Como inspecionar em produção

Logs (Loki/stdout): procurar por - XADM PUT processando requestId=... / XADM DEL processando requestId=... — entrada do request. - XADM PUT concluído requestId=... resultado=SUCESSO — sucesso. - XADM PUT falhou: requestId=... origem=... detalhe=... — request final que falhou. - Sentry não disponível ou falha ao reportar erro XADM — indica problema no SDK Sentry.

Sentry: filtrar por - Tag origem:PPEDIDO (ou outra conhecida) para ver falhas por origem. - Tag tipo:PUT vs tipo:DEL.

Banco (request table): SELECT * FROM request WHERE resultado='ERRO' ORDER BY id DESC — mensagem contém tabela=... registro=(...) | mensagem_original=... formatado.


Histórico

  • 2026-04-24: incidente PPEDIDO seq_n=777 → deadlock_detected no int.sulplata motivou esta spec.
  • Solução inicial considerada: retry com backoff em deadlock. Descartada porque retry pode inverter a ordem DELETE → PUT esperada pelo ERP (correção de paralelismo não preserva ordering). Adotada serialização global no XADM.
  • Spec: docs/ia/002-rest-ok-antigo-erro-novo-spec.md.
  • Plan: docs/ia/002-rest-ok-antigo-erro-novo-plan.md.