Uma chamada pode produzir efeito no fornecedor e terminar sem resposta no sistema da loja. Outra chamada pode receber a aprovação e falhar ao atualizar o banco local. Nos dois casos, tentar de novo exige saber qual etapa será repetida e como evitar uma segunda operação de negócio.
Uma tentativa não é uma operação de negócio
O pedido PED-0001 pode gerar uma operação de pagamento e várias tentativas de comunicação. Cada nível tem o próprio identificador:
- Identificador do negócio: o pedido, a venda ou o documento que originou a operação.
- Identificador da operação local: a intenção que o sistema acompanha até a conclusão.
- Identificador da tentativa: a chamada específica, com início, duração e retorno próprios.
- Identificador remoto: a cobrança, a pré-autorização ou o recurso criado no fornecedor.
- Chave de idempotência: a identidade que o serviço usa para reconhecer uma repetição, quando o contrato oferece esse recurso.
- Identificador do evento: o aviso que pode ser recebido ou entregue de novo.
Uma segunda tentativa pode ter outro identificador de requisição e manter a mesma chave de idempotência da intenção original. Um identificador de rastreio, usado no log, não impede a duplicidade. O número do pedido, sozinho, também não basta, porque o contrato define se um pedido admite vários pagamentos, cancelamentos ou tentativas comerciais diferentes.
Idempotência e controle de duplicidade
A idempotência mantém o mesmo efeito pretendido quando a operação é repetida. Uma criação por POST pode ter uma proteção específica, mas o método não oferece essa proteção por si. O contrato informa onde a chave vale, quais dados precisam continuar iguais, como as chamadas simultâneas são tratadas e por quanto tempo o serviço guarda o controle.
No gateway de pagamento, a primeira chamada e a repetição usam a chave operacao-0001 e os mesmos dados. A criação de uma chave operacao-0002 só porque a resposta da primeira demorou pode gerar outra cobrança. A reutilização da chave operacao-0001 depois de uma mudança no valor ou no destinatário também contraria o contrato.
Uma restrição de chave única no banco impede gravar duas vezes a mesma identidade, mas não resolve tudo quando o efeito e o registro da conclusão acontecem em momentos separados. Dois consumidores podem ver um registro como não tratado e prosseguir, e um terceiro pode aplicar o negócio e cair antes de registrar a conclusão. A implementação precisa coordenar a identidade, o efeito e a confirmação.
O que cada evidência permite afirmar
- Falha de resolução do nome antes do envio: a tentativa não passou dessa etapa, e o histórico das outras tentativas e os intermediários ainda são conferidos.
- Tempo esgotado à espera da resposta: o programa não recebeu o retorno no prazo, e o recebimento, o processamento e a situação no fornecedor continuam desconhecidos.
- Recusa explícita da mesma operação: o retorno registra a recusa, e o motivo e o tratamento definido pelo fornecedor orientam o passo seguinte.
- Aprovação remota com o pedido pendente na loja: existe uma divergência entre dois estados confirmados, e a aplicação local, o acompanhamento e a associação entre os registros são conferidos.
O resultado desconhecido descreve o que se sabe e não vira recusado só para liberar uma tela. Um tempo esgotado no programa, ou o cancelamento da espera, também não desfaz uma alteração feita no fornecedor.
Repetição controlada
Os erros passageiros podem admitir repetição, mas um erro de contrato, a falta de permissão e uma recusa comercial pedem outra decisão. O código, a mensagem e o contrato classificam o erro, e não existe uma lista universal de respostas que permitem repetir. Uma política de repetição limita a quantidade de tentativas e o tempo total com três recursos:
- Backoff: a pausa entre as tentativas, que pode aumentar a cada falha, como em 1, 2 e 4 segundos, com os valores definidos pela integração;
- Jitter: a variação aleatória da pausa, que evita que muitos clientes repitam ao mesmo tempo;
- Retry-After: o tempo de espera informado pelo próprio serviço, quando a resposta traz esse cabeçalho.
A renovação da credencial pode recuperar o acesso, mas não muda o resultado de uma operação já enviada. As novas tentativas mantêm as identidades exigidas e registram os próprios retornos. Quando o serviço não oferece chave nem consulta confiável, o suporte não cria uma garantia de repetição, registra o resultado desconhecido e segue o procedimento do fornecedor para localizar, confirmar ou desfazer a operação.
Reconciliação entre o fornecedor e o sistema
A reconciliação compara os registros e as situações dos dois lados e regulariza as diferenças com evidências. A comparação começa pela mesma conta, loja, ambiente e operação. O identificador remoto, a referência de origem, o valor e a moeda confirmam a associação, e um horário próximo, sozinho, não basta.
Uma consulta que não encontra o recurso pode ter usado o ambiente errado, outro identificador, só uma página do resultado ou um momento anterior à disponibilização. Quando o recurso está pendente, o acompanhamento continua. Quando está confirmado, a atualização local é recuperada pelo procedimento apropriado. Quando há uma recusa conclusiva, o motivo orienta o passo seguinte.
Forçar uma situação ou criar outra cobrança não corrige a divergência. Reaplicar um retorno confirmado é diferente de repetir a criação remota, e o cancelamento e o estorno são operações novas, com identificação, permissão e regras próprias.
Eventos, fila e banco local
Confirmar uma entrega depois da gravação deixa uma janela para a reentrega de um trabalho já aplicado, e confirmar antes da gravação pode perder o trabalho quando a gravação falha. Dois controles de implementação tratam esse problema:
- Inbox: o registro dos eventos recebidos e tratados, que impede aplicar o mesmo evento duas vezes;
- Outbox: a gravação das mensagens a publicar na mesma transação da alteração local, para que a publicação aconteça depois, sem se perder.
A publicação feita a partir do outbox ainda pode se repetir, e o efeito remoto não entra na transação do banco local. Por isso, a proteção no consumidor e a reconciliação continuam necessárias. Esses controles fazem parte do desenho da integração, e a existência deles é confirmada antes de qualquer conclusão baseada neles.
No suporte
Diante de uma operação com resultado desconhecido, convém preservar a identidade da operação e de cada tentativa e confirmar a situação no fornecedor antes de qualquer repetição. Depois, a análise separa a recuperação da atualização local, o acompanhamento de uma pendência e uma operação comercial nova.
Para guardar
- A operação de negócio e a tentativa de comunicação têm identidades diferentes.
- O identificador de rastreio não protege contra a duplicidade.
- A idempotência tem alcance, dados e prazo definidos pelo contrato.
- O tempo esgotado à espera da resposta deixa o resultado remoto incerto.
- A repetição precisa de limites, e a reconciliação precisa de uma associação confiável entre os registros.
Um POST de cobrança terminou em tempo esgotado, e o integrador gerou uma chave nova e conseguiu a aprovação. O que ainda falta investigar?
A situação da primeira operação. A chave nova pode ter criado outra cobrança, sem proteção contra a duplicidade em relação à anterior. As referências, os identificadores remotos, os valores e o contrato mostram se existem duas cobranças.
O pagamento está aprovado no fornecedor, mas o banco local não foi atualizado. É preciso criar o pagamento de novo?
Não. A associação entre o pedido e a cobrança é confirmada, e o resultado é aplicado no banco local pelo procedimento previsto. A criação remota já tem resultado conhecido, e uma nova cobrança aumentaria a divergência.