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:
- Inversão de ordem: PUT comita primeiro, DELETE comita por cima → linha fica
marcada
deletedquando deveria ter o estado novo. - Deadlock PostgreSQL (
ERROR: deadlock detected, SQLState40P01): 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_detectednoint.sulplatamotivou esta spec. - Solução inicial considerada: retry com backoff em deadlock. Descartada porque retry
pode inverter a ordem
DELETE → PUTesperada 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.