O telefone tocou às 2 da manhã. Um supervisor de turno de um DC de e-commerce em Riverside praticamente gritava: "Lao Mi, o sorter enlouqueceu! O mesmo volume acabou de ser escaneado três vezes, os chutes estão transbordando, o transportador vai travar!"

Eu disse para ele manter as mãos longe do equipamento e puxar dois arquivos de log. Meia hora depois ele ligou de volta, com a voz envergonhada: "Você estava certo... o WES liberou a mesma onda duas vezes."

Já vi esse filme muitas vezes. No chão, sempre dizem "o sistema está com problema". Na minha experiência, nove em cada dez vezes, o que parece um problema é o WES e o WCS brigando entre si — e a causa raiz é quase sempre a interface entre os dois. Aqui está a cadeia de diagnóstico que eu realmente uso, do sintoma à causa raiz.

Não toque na linha. Faça os dois registros conversarem primeiro.

Conflitos de comando geralmente morrem de duas formas: despacho duplicado de tarefas, ou um callback de status perdido. O WES envia um comando de liberação, a rede falha, o reconhecimento nunca volta, então o WES dispara o mesmo comando de novo após seu timeout configurado. O WCS aceita os dois de bom grado — porque ninguém construiu deduplicação por número de tarefa na interface. Uma tarefa entra duas vezes na fila de separação, e o mesmo pacote é solicitado pelo chute duas ou três vezes.

O passo um é sempre o mesmo: coloque o log de despacho do WES e o log de recebimento de comandos do WCS lado a lado, e alinhe os números de tarefa um por um. Mas há uma armadilha aqui que pega oito em cada dez armazéns: os relógios dos dois servidores não estão sincronizados. O log do WES diz que o comando saiu às 02:14:03; o do WCS diz que foi recebido às 02:13:47. Quando os timestamps não batem, você nunca consegue estabelecer causa e efeito. Antes de tocar em qualquer log, confirme que os dois lados estão no NTP — e confirme o fuso horário. Já vi mais de um site onde um lado registrava em UTC e o outro em hora local.

Eu mesmo tropecei nisso em 2021, num DC em Ontario, com mais de cem mil pés quadrados, rodando um sorter de correia cruzada. Alta temporada, no meio da noite: o mesmo pacote apareceu no sistema três vezes. Com os dois logs sobre a mesa, estava claro como o dia — o WES havia liberado a onda duas vezes, separadas por exatamente um intervalo de timeout, e o log de execução do WCS mostrava dois números de tarefa idênticos, ambos honrados. Causa raiz em uma frase: reenvio por timeout batendo numa interface sem idempotência.

Há um compromisso genuíno escondido nesse valor de timeout. Curto demais, e cada jitter de rede dispara um reenvio falso; longo demais, e mudanças de onda e pedidos urgentes ficam esperando. Esse número não pode ser um chute — tem que sair da latência medida na sua rede real, e a contagem de tentativas e a política de backoff pertencem por escrito à especificação da interface. Integradores demais deixam isso como acordo verbal, e o acordo sai pela porta com o engenheiro.

Linha de separação no piso de execução

Quando um pedido urgente desloca uma tarefa em andamento, para onde vai a tarefa antiga?

A preempção por pedido urgente é a zona de conflito mais complicada, e a lógica é mais traiçoeira do que a simples duplicação. O WES recebe um pedido urgente, marca parte das tarefas da onda atual como canceladas, e desliza as novas tarefas para dentro. Mas o WCS já empurrou esses comandos para o PLC — o cancelamento chega tarde demais para parar um desvio já em movimento. Agora o mesmo pacote está sendo chamado para o chute A pela tarefa antiga e para o chute B pela nova. A qual deles o equipamento obedece?

O diagnóstico significa seguir dois fios: a máquina de estados de tarefas do WES (o cancelamento realmente saiu, e exatamente quando?) e a fila de comandos do WCS (onde estava esse comando na execução quando o cancelamento chegou?). A evidência decisiva continua sendo o delta de timestamps — quando o cancelamento foi emitido versus quando o comando realmente terminou de executar. Faça a conta e você saberá se o cancelamento tinha alguma chance de alcançar.

Há uma armadilha mais sutil por baixo: os dois lados nem falam os mesmos números de tarefa. O WES usa seus próprios IDs de tarefa; o WCS os traduz em números de comando de equipamento, com uma tabela de mapeamento no meio. Perca essa tabela e os dois sistemas falam sem se entender. Vi isso em 2023 num armazém nos arredores de Chicago — a tabela de mapeamento vivia na memória, o serviço WCS reiniciou durante a noite, e ela sumiu. O engenheiro do turno da noite encarou os dois logs e não conseguiu encontrar uma única tarefa correspondente. Não porque nada tivesse sido registrado, mas porque os números não batiam. A solução não tem glamour, mas funciona: persista a tabela de mapeamento no disco, e faça o log do WCS carregar o número de tarefa original do WES até o fim.

E aqui está meu veredito sobre pedidos urgentes: não faça preempção dura a menos que seu volume exija. Dê aos pedidos urgentes seu próprio chute ou sua própria onda — não mexa nas tarefas que já estão em execução. Os poucos minutos economizados com a preempção não cobrem o custo de uma linha travada. Se precisar preemptar, o cancelamento tem que ser em duas fases: um pré-cancelamento que trava os comandos não executados no WCS, depois um cancelamento formal; tudo que já está em movimento passa por um fluxo de compensação após a conclusão. Esperar que um único comando de cancelamento supere a física é simplesmente desrespeitar a velocidade da luz.

Pare de perguntar por quê. Torne-o idempotente.

Os dois modos de falha acima compartilham uma causa raiz: a interface não é idempotente. O que é preciso do lado do WES é simples — cada tarefa carrega um número de tarefa globalmente único, e os reenvios mantêm o mesmo número. Do lado do WCS: ao receber, verificar "já vi esse número de tarefa?"; se sim, responder sucesso e não executar de novo. Os callbacks de status funcionam igual — anexe um número de sequência monotonicamente crescente para que o WES possa ordenar por conta própria os callbacks fora de ordem ou duplicados.

Na aceitação, entrego ao integrador três frases, e elas entram no contrato como anexo: primeira, derrube a rede por alguns segundos e reconecte — nenhuma tarefa pode executar duas vezes. Segunda, reinicie o WCS — os mapeamentos históricos de tarefas devem sobreviver. Terceira, cancelar um pedido urgente contra uma tarefa em execução deve disparar uma ação de compensação definida, não apenas "o cancelamento foi enviado". Passe nessas três e noventa por cento das histórias de fantasmas da camada de execução nunca acontecem.

Meu veredito se mantém: nove em cada dez "problemas de sistema" são interfaces sem idempotência. Do décimo restante, metade são relógios não sincronizados e metade é a mão trêmula de alguém num botão às 2 da manhã.

Antes do seu próximo go-live, puxe o cabo de rede por alguns segundos e plugue de volta você mesmo. Só um sistema que sobreviva a esses poucos segundos merece sua alta temporada.

Traduzido do inglês. Em caso de divergência, prevalece a versão em inglês.