{"id":1501,"date":"2025-04-18T15:43:17","date_gmt":"2025-04-18T15:43:17","guid":{"rendered":"https:\/\/mugnos-it.com\/?p=1501"},"modified":"2025-06-03T00:47:47","modified_gmt":"2025-06-03T00:47:47","slug":"voce-sabe-como-implementar-idempotencia-em-apis-sync-e-async","status":"publish","type":"post","link":"https:\/\/mugnos-it.com\/pt\/voce-sabe-como-implementar-idempotencia-em-apis-sync-e-async\/","title":{"rendered":"Voc\u00ea sabe como implementar Idempot\u00eancia em APIs Sync e Async?"},"content":{"rendered":"<div data-elementor-type=\"wp-post\" data-elementor-id=\"1501\" class=\"elementor elementor-1501\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-54b2123d e-flex e-con-boxed e-con e-parent\" data-id=\"54b2123d\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-359fdc09 elementor-widget elementor-widget-text-editor\" data-id=\"359fdc09\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\n<p id=\"19714600-107e-80f3-a5a6-ff0b0416d76f\"><\/p>\n\n\n\n<p id=\"19714600-107e-8047-acf9-cfaff2f09fd6\">J\u00e1 imaginou um usu\u00e1rio clicando v\u00e1rias vezes no bot\u00e3o de pagamento e sendo cobrado m\u00faltiplas vezes? Ou ent\u00e3o um script de infraestrutura rodando de novo e criando recursos duplicados? J\u00e1 passei por isso\u2026 e a causa sempre era a mesma: <strong>falta de idempot\u00eancia<\/strong>.<br><\/p>\n\n\n\n<p id=\"19714600-107e-803d-961f-c5586be8358d\">Duplica\u00e7\u00e3o de requisi\u00e7\u00f5es \u00e9 algo comum de acontecer principalmente em arquiteturas distribuidos. Implementar valida\u00e7\u00f5es de requisi\u00e7\u00f5es duplicadas \u00e9 essencial para evitar bugs e falhas. Em resumo: <strong>idempot\u00eancia garante que executar uma a\u00e7\u00e3o v\u00e1rias vezes sempre leve ao mesmo resultado final,<\/strong> ou seja, chega de reprocessar e causar entradas duplicadas em seus softwares.<br><\/p>\n\n\n\n<p id=\"19714600-107e-805c-9873-ea6d67100a2a\">Logo de cara, \u00e9 importante entender que <strong>alguns servi\u00e7os de mensageria n\u00e3o garantem idempot\u00eancia nativamente<\/strong>, o que significa que uma mesma mensagem pode ser entregue mais de uma vez. Em comunica\u00e7\u00f5es s\u00edncronas isso tamb\u00e9m acontece, <strong>mecanismos de retry e timeouts<\/strong> podem gerar requisi\u00e7\u00f5es duplicadas, j\u00e1 que o cliente pode n\u00e3o receber uma resposta e tentar novamente. Sem um controle adequado, isso pode resultar em <strong>processamentos repetidos<\/strong> e at\u00e9 <strong>inconsist\u00eancias nos dados<\/strong>.<br><br>Olha aqui um exemplo de um servi\u00e7o excepcional da AWS, o AWS SQS:<br><br><em><strong>Filas Standard garantem a entrega de mensagens pelo menos uma vez, por\u00e9m, por causa da arquitetura altamente distribu\u00edda, mais de uma c\u00f3pia de uma mensagem pode ser entregue e as mensagens \u00e0s vezes podem chegar fora de ordem. Apesar disso, as filas padr\u00e3o fazem o poss\u00edvel para manter a ordem em que as mensagens s\u00e3o enviadas.<\/strong><\/em> <a href=\"https:\/\/docs.aws.amazon.com\/pt_br\/AWSSimpleQueueService\/latest\/SQSDeveloperGuide\/standard-queues.html\">https:\/\/docs.aws.amazon.com\/pt_br\/AWSSimpleQueueService\/latest\/SQSDeveloperGuide\/standard-queues.html<\/a><\/p>\n\n\n\n<p id=\"19714600-107e-80e4-bbc5-e529e10c8f8c\">Mas antes de falarmos sobre como implementar a idempot\u00eancia, \u00e9 fundamental entender o conceito de <strong>chave forte<\/strong> ou <strong>chave de idempot\u00eancia<\/strong>. Basicamente, essa chave \u00e9 um identificador \u00fanico associado a uma opera\u00e7\u00e3o, garantindo que, caso a mesma solicita\u00e7\u00e3o seja enviada mais de uma vez, o sistema reconhe\u00e7a e trate como uma \u00fanica execu\u00e7\u00e3o.<br><\/p>\n\n\n\n<p id=\"19714600-107e-80a1-9e7b-ce003dbb7bb9\">Em <strong>APIs s\u00edncronas<\/strong>, essa chave <strong>geralmente<\/strong> \u00e9 enviada no cabe\u00e7alho da requisi\u00e7\u00e3o (mas as vezes \u00e9 um concate de varios valores do payload), como um <strong>UUID<\/strong> (<code>Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000<\/code>) ou um <strong>hash gerado a partir do corpo da requisi\u00e7\u00e3o<\/strong> (exemplo: <code>SHA-256(\"user123-100USD-2024-02-10\")<\/code>).<br><\/p>\n\n\n\n<p id=\"19714600-107e-807f-868b-f65c0bc2cf93\">J\u00e1 em <strong>sistemas ass\u00edncronos<\/strong>, a chave pode ser o pr\u00f3prio <strong>ID \u00fanico da mensagem<\/strong>, como um <code>MessageId<\/code> em um servi\u00e7o de mensageria (<code>MessageId: msg-abc-123<\/code>) ou um identificador customizado gerado pelo produtor antes do envio (<code>Order-Id: 987654321<\/code> ou <code>Order-Id: action-user-date-hour<\/code> ).<br><\/p>\n\n\n\n<p id=\"19714600-107e-80e7-a712-d0295930c3e0\">Sem uma chave forte bem definida, n\u00e3o h\u00e1 como garantir a idempot\u00eancia de forma eficaz.<\/p>\n\n\n\n<p id=\"19714600-107e-80d8-874c-ea70e4f7754e\">Bom, agora q vc entende o que \u00e9 a chave de idempotencia, vamos falar um pouco de como usa-las:<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" id=\"19714600-107e-808d-9a25-fd6d2753fa8a\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"19714600-107e-803f-8f88-c0434893f082\"><strong>1. Idempot\u00eancia em APIs Sync \/ S\u00edncronas (RESTful)<\/strong><\/h3>\n\n\n\n<p id=\"19714600-107e-8095-b97e-dc345f06ca8f\">Para evitar que um mesmo pedido seja processado mais de uma vez em uma API de pagamento, voc\u00ea pode implementar da seguinte forma:<\/p>\n\n\n\n<p id=\"19714600-107e-803c-aca3-dbb26c2d889b\">1\ufe0f\u20e3 O <strong>cliente<\/strong> gera um <code>Idempotency-Key<\/code> \u00fanico para cada requisi\u00e7\u00e3o e envia no cabe\u00e7alho ou at\u00e9 mesmo no corpo do Payload .<br><\/p>\n\n\n\n<p id=\"19714600-107e-8058-a7a5-c0f7f87d33f3\">2\ufe0f\u20e3 O <strong>servidor<\/strong> verifica se essa chave j\u00e1 foi processada antes:<\/p>\n\n\n\n<ul id=\"19714600-107e-80df-8d67-de2067c0b268\" class=\"wp-block-list\">\n<li><strong>Se sim<\/strong>, retorna a resposta armazenada.<\/li>\n\n\n\n<li><strong>Se n\u00e3o<\/strong>, processa a requisi\u00e7\u00e3o e armazena o resultado.<br><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"19714600-107e-808e-b299-df13841a3f25\"><strong>Exemplo de implementa\u00e7\u00e3o<\/strong><\/h3>\n\n\n\n<pre id=\"19714600-107e-806b-b25a-ec6be4576d3d\" class=\"wp-block-code\"><code>python\nCopyEdit\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\nidempotency_store = {}  # Simulando um banco de dados\n\n@app.route('\/payment', methods=&#91;'POST'])\ndef process_payment():\n    idempotency_key = request.headers.get('Idempotency-Key')\n\n    if not idempotency_key:\n        return jsonify({\"error\": \"Idempotency-Key is required\"}), 400\n\n    if idempotency_key in idempotency_store:\n        return jsonify(idempotency_store&#91;idempotency_key])  # Retorna a resposta salva\n\n    # Processa o pagamento (simula\u00e7\u00e3o)\n    response = {\"status\": \"success\", \"message\": \"Payment processed\"}\n\n    idempotency_store&#91;idempotency_key] = response  # Salva o resultado\n    return jsonify(response)\n\nif __name__ == '__main__':\n    app.run(debug=True)\n\n<\/code><\/pre>\n\n\n\n<p id=\"19714600-107e-8032-9a9a-f4de99165aa2\">\u2705 Como voc\u00ea pode ver acima, com essa pequena valida\u00e7\u00e3o voc\u00ea pode evitar uma duplica\u00e7\u00e3o. Se a mesma requisi\u00e7\u00e3o for enviada novamente com a mesma chave, <strong>o servidor retorna o mesmo resultado sem processar de novo.<\/strong><\/p>\n\n\n\n<p id=\"19714600-107e-80ef-bef2-d798d359cf86\">** <strong>IMPORTANTE<\/strong>: Note, que aqui estou armazenando a chave de idepotencia em mem\u00f3ria\u2026 nem preciso falar que isso n\u00e3o \u00e9 uma boa id\u00e9ia n\u00e9 ?! hehe. \u00c9 muito comum o uso de database para isso, principalmente in-memory DB (Redis e memcached) devido o baixo tempo de resposta.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" id=\"19714600-107e-80d4-83e9-daa046f7cef4\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"19714600-107e-804f-97cd-d2a94bfdc099\"><strong>2. Idempot\u00eancia em APIs Async \/ Ass\u00edncronas (Mensageria &#8211; Kafka, SQS, RabbitMQ)<br><\/strong><\/h3>\n\n\n\n<p id=\"19714600-107e-80e3-8d8e-fcf2e4780049\">Um sistema de mensageria pode reenviar a mesma mensagem v\u00e1rias vezes por falhas de rede ou reprocessamento. Precisamos garantir que uma mensagem n\u00e3o seja processada duas vezes. Para isso voc\u00ea pode implementar idempot\u00eancia da seguinte forma:<\/p>\n\n\n\n<p id=\"19714600-107e-80aa-9f8f-e94ef12380ba\">1\ufe0f\u20e3 Cada mensagem enviada para a fila deve conter um <strong>ID \u00fanico<\/strong>.<br><\/p>\n\n\n\n<p id=\"19714600-107e-80bd-b455-c22a8c130173\">2\ufe0f\u20e3 O <strong>consumidor<\/strong> da fila deve armazenar os IDs j\u00e1 processados para evitar duplica\u00e7\u00f5es.<br><\/p>\n\n\n\n<p id=\"19714600-107e-80a9-9a1c-d064bfbc7763\">3\ufe0f\u20e3 Antes de processar uma nova mensagem, o sistema verifica se o ID j\u00e1 foi tratado.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"19714600-107e-805b-bcfc-d0a6f8176eb9\"><strong>Exemplo de implementa\u00e7\u00e3o<\/strong><\/h3>\n\n\n\n<pre id=\"19714600-107e-80f4-94c2-cdefdd99565f\" class=\"wp-block-code\"><code>python\nCopyEdit\nimport uuid\nfrom queue import Queue\n\nmessage_queue = Queue()\nprocessed_messages = set()  # Simulando um banco de dados de mensagens j\u00e1 processadas\n\ndef produce_message():\n    message_id = str(uuid.uuid4())  # Gera um ID \u00fanico\n    message_queue.put({\"id\": message_id, \"content\": \"Process this!\"})\n    print(f\"Message {message_id} sent to queue\")\n\ndef consume_message():\n    while not message_queue.empty():\n        message = message_queue.get()\n        message_id = message&#91;\"id\"]\n\n        if message_id in processed_messages:\n            print(f\"Skipping duplicate message {message_id}\")\n            continue  # Ignora mensagens duplicadas\n\n        # Processa a mensagem\n        print(f\"Processing message {message_id}: {message&#91;'content']}\")\n\n        processed_messages.add(message_id)  # Marca como processada\n\nproduce_message()\nconsume_message()\nconsume_message()  # Tentamos consumir de novo, mas a l\u00f3gica impede duplica\u00e7\u00e3o\n\n<\/code><\/pre>\n\n\n\n<p id=\"19714600-107e-8003-b2df-e412de4fcccf\">\u2705 Isso evita que uma mesma mensagem seja processada mais de uma vez, garantindo idempot\u00eancia.<br><br><\/p>\n\n\n\n<p id=\"19714600-107e-8097-b358-cba2386d15c0\">** <strong>IMPORTANTE<\/strong>: Note, que aqui estou armazenando a chave de idepotencia em mem\u00f3ria\u2026 nem preciso falar que isso n\u00e3o \u00e9 uma boa id\u00e9ia n\u00e9 ?! hehe. \u00c9 muito comum o uso de database para isso, principalmente in-memory DB (Redis e memcached) devido o baixo tempo de resposta.<br><br><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" id=\"19714600-107e-80e0-8b51-dda25ea54420\"\/>\n\n\n\n<p id=\"19714600-107e-807e-bdf3-c6d744efbf4d\"><strong>3. Idempot\u00eancia na regra de neg\u00f3cio<\/strong><\/p>\n\n\n\n<p id=\"19714600-107e-8041-8c21-ca60f0c3bcb7\">Nem todas as funcionalidades exigem idempot\u00eancia absoluta. Algumas opera\u00e7\u00f5es s\u00e3o naturalmente idempotentes por design. Por exemplo, se voc\u00ea precisa atualizar uma tabela no banco de dados sem considerar o valor anterior, rodar o mesmo <code>UPDATE<\/code> uma ou cinco vezes ter\u00e1 o mesmo efeito, certo? Em alguns cen\u00e1rios, pode ser mais eficiente lidar com duplica\u00e7\u00f5es eventuais do que implementar uma valida\u00e7\u00e3o rigorosa para todas as requisi\u00e7\u00f5es ou mensagens. No entanto, nem sempre a solu\u00e7\u00e3o \u00e9 t\u00e3o simples. Mas quando for, por que complicar se voc\u00ea pode simplificar?<br><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" id=\"19714600-107e-8001-969b-de984c238f39\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"19714600-107e-80aa-a3ce-e5cc27ce7910\"><strong>Conclus\u00e3o<br><\/strong><\/h3>\n\n\n\n<p id=\"19714600-107e-80c2-91f4-e485e9439177\">Seja em <strong>APIs RESTful (s\u00edncronas)<\/strong> ou <strong>sistemas ass\u00edncronos (mensageria)<\/strong>, <strong>idempot\u00eancia<\/strong> \u00e9 essencial para evitar efeitos colaterais indesejados. Portanto, sempre que estiver atuando com alguma funcionalidade, criando uma automa\u00e7\u00e3o, software ou at\u00e9 mesmo um snippet de c\u00f3digo, pergunte-se: <strong>&#8220;Se isso rodar de novo, o que acontece?&#8221;, <\/strong>a resposta a essa pergunta com certeza ir\u00e1 deixar bem claro se voc\u00ea precisa criar uma valida\u00e7\u00e3o ou n\u00e3o.<\/p>\n\n\n\n<p id=\"19714600-107e-8035-93b4-e3c44c799b9c\">E a\u00ed, voc\u00ea j\u00e1 implementou idempot\u00eancia nos seus servi\u00e7os? <strong>Me conta!<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" id=\"19714600-107e-803a-95b1-e9c66ecb8dfe\"\/>\n\n\n\n<p id=\"19714600-107e-80fd-be4a-d87b4c2db050\">Aproveitando, Se voc\u00ea curte conte\u00fados como esse e quer aprender os padr\u00f5es e as pr\u00e1ticas para criar e manter sistemas escal\u00e1veis, resilientes e modernos, ao mesmo tempo que se torna uma autoridade no assunto, te convido a fazer parte da <strong>Comunidade de Arquitetura Descomplicada (CaD). <\/strong>Saiba mais em <a href=\"https:\/\/mugnos-it.com\/pt\/cad\/\">https:\/\/mugnos-it.com\/cad\/<\/a><\/p>\n\n\n\n<p id=\"19714600-107e-8042-982f-e244d2e57a2b\">Abra\u00e7os,<\/p>\n\n\n\n<p id=\"19714600-107e-80f5-ad76-df9a992de827\">Douglas Mugnos<\/p>\n\n\n\n<p id=\"19714600-107e-80d3-9d31-cdd7670268bb\">MUGNOS-IT<\/p>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e3c6262 e-flex e-con-boxed e-con e-parent\" data-id=\"e3c6262\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>J\u00e1 imaginou um usu\u00e1rio clicando v\u00e1rias vezes no bot\u00e3o de pagamento e sendo cobrado m\u00faltiplas vezes? Ou ent\u00e3o um script de infraestrutura rodando de novo e criando recursos duplicados? J\u00e1 passei por isso\u2026 e a causa sempre era a mesma: falta de idempot\u00eancia. Duplica\u00e7\u00e3o de requisi\u00e7\u00f5es \u00e9 algo comum de acontecer principalmente em arquiteturas distribuidos. [&hellip;]<\/p>","protected":false},"author":3,"featured_media":1907,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1501","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/mugnos-it.com\/wp-content\/uploads\/2025\/04\/03.-implementar-Idempotencia-em-APIs-Sync-e-Async.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts\/1501","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/comments?post=1501"}],"version-history":[{"count":5,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts\/1501\/revisions"}],"predecessor-version":[{"id":2022,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts\/1501\/revisions\/2022"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/media\/1907"}],"wp:attachment":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/media?parent=1501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/categories?post=1501"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/tags?post=1501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}