Tentar novamente um envio é mais difícil do que enviar


Toda integração que tira algo do seu sistema tem o mesmo ponto fraco, e é

não o caminho feliz. É a segunda tentativa.

Seu código publica um documento em um provedor. A conexão cai antes que a resposta chegue. Agora você não tem nenhuma identificação de trabalho, nenhuma confirmação e nenhuma ideia se alguma coisa saiu do prédio. O tempo limite informou sobre sua rede. Não lhe disse nada sobre o deles.

Então você tenta novamente e envia a coisa duas vezes ou nunca envia. Escolha um, porque

sem a ajuda da API você não pode ter os dois.

Por que as soluções usuais não resolvem

O primeiro instinto é um guarda do lado do cliente. Faça hash da carga útil, mantenha uma tabela do que você já tem

enviado, verifique-o antes de cada tentativa.

Isso funciona até que a tentativa de duplicação venha de um processo diferente, de um contêiner diferente ou de um

trabalhador de fila iniciado após uma implantação. Sua mesa é o estado local defendendo-se contra uma distribuição

problema.

O segundo instinto é perguntar ao fornecedor se o emprego existe. Isso significa listar empregos recentes

e combinando algo, geralmente o destinatário e uma janela de carimbo de data/hora. É uma pesquisa e

pesquisas têm falsos positivos. Dois envios legítimos para o mesmo destinatário com um minuto de diferença são exatamente iguais a um envio e uma nova tentativa.

O terceiro instinto é tornar a operação naturalmente idempotente. Isso funciona perfeitamente para um upsert de banco de dados e falha completamente para qualquer coisa que saia do seu controle. Um documento que foi transmitido não pode ser destransmitido por uma segunda chamada.

O que realmente resolve

Uma chave de idempotência, gerada pelo chamador, anexada à solicitação e honrada pelo

servidor para uma janela definida.

O contrato é simples. O chamador inventa uma string exclusiva por operação lógica. Cada tentativa

carrega a mesma corda. A primeira solicitação a chegar faz o trabalho e registra o resultado nessa chave. Cada solicitação posterior que transporta essa string obtém o resultado registrado de volta em vez de fazer o trabalho novamente.

A parte importante é onde o estado mora. Está no servidor, que é o único lugar que sabe

se o trabalho existe. Seu loop de nova tentativa deixa de precisar ser inteligente. Só precisa reutilizar a chave.

Stripe popularizou esse padrão e a razão pela qual ele se espalhou é que a alternativa é ilimitada.

Sem ele, cada chamador grava mal sua própria desduplicação, e a falha só aparece sob carga.

APIs de documentos e mensagens são onde mais importa, porque o efeito colateral é visível para

alguém fora da sua empresa. Fax para Agentes é um exemplo atual do padrão adotado

seriamente. Requer uma Chave de Idempotência em cada chamada mutante, portanto, uma nova tentativa devolve o

mesmo trabalho em vez de criar um segundo.

Os estados que ninguém modela adequadamente

A idempotência resolve a duplicata. Não resolve a outra metade, que é que você ainda não sabe o que aconteceu.

A maioria das integrações modela isso como um booleano. Enviado ou não enviado. Isso está errado, e você descobre isso

a primeira vez que uma transmissão é concluída pela metade.

Uma máquina de estado útil para um envio tem mais espaço. Fax for Agents publica seis estados:

enfileirado, ativo, parcial, com falha, desconhecido e entregue. Dois deles são os interessantes.

desconhecido significa que o provedor não disse. Não falhou, não foi entregue. A resposta correta para

desconhecido é esperar. Um loop de nova tentativa que trata o desconhecido como falha precisa ser reescrito, porque isso é

como você produz duplicatas mesmo com idempotência em vigor.

parcial significa que parte dele chegou. Reenviar o documento inteiro entregaria as primeiras páginas

duas vezes, então parcial é um estado que nunca deve ser retransmitido automaticamente. Precisa de uma pessoa, ou de um

política escrita antecipadamente por uma pessoa.

E entregue deve ser a palavra mais restrita do vocabulário. Nessa API é escrito apenas quando

as evidências do provedor para a tentativa a apoiam, nunca quando a solicitação foi meramente

aceito. A lacuna entre “aceitamos seu trabalho” e “ele chegou” é onde a maioria dos falsos

a confiança vive.

O que perguntar a qualquer API da qual você está prestes a depender

Quatro perguntas, respondidas na documentação antes de você escrever uma linha de código.

Ele aceita uma string de idempotência fornecida pelo chamador em cada chamada mutante e por quanto tempo

essa corda aguenta?

Quantos estados terminais um trabalho possui? Se a resposta for dois, a API está escondendo algo

de você.

Existe um estado que significa “ainda não sabemos” e a documentação diz o que você deve fazer quando o vir?

Quando um webhook chega, você pode verificar se ele veio deles? A entrega assinada com um ID de evento é

a diferença entre um manipulador de webhook e um endpoint aberto.

Nada disso é exótico. É a diferença entre uma integração que degrada e outra que

duplica silenciosamente.



Source link