Implementing idempotency in microservices

A plataforma DevPrime oferece a funcionalidade de idempotência automática para utilização nos microsserviços.

Nós implementaremos um exemplo no modo backend onde não é necessário passar uma chave para consumir a API do microsserviço. O processo gerencia automaticamente a idempotência confrome o payload da API.

O primeiro passo para habilitar a idempotência é modificar a configuração “Idempotency” no Idempotency no “DevPrime_App”. Deopis caso não tenha feito é necessário adicionar um segundo State para a persistência da idempotência.

Parâmetros utilizados na configuração

  • Alias indica o State utilizado na persistência da Idempotency
  • Duration é utilizado para definir o tempo do registro de controle de duplicidade do comando.
  • Flow indica tipo de Idempotency e pode ser definido como “backend” ou “frontend”
  • Key é utilizada para definir uma chave requerida no head no Flow “frontend”
  • Scope limita a atuação da idepontencia e utiliza os parametros “all|web|stream”
  • Action define se a idepontencia será automática ou manual com os parâmetros “auto|manual”

Criando um microserviço para utilizar no exemplo

Nós utilizaremos um microsserviço baseado na plataforma DevPrime

Iniciando a configuração da idempotência

Configuração da idempotência na chave “DevPrime_App”
Altere na configuração do Idempotency na opção “Enabled” para “true”
code .\src\app\appsettings.json

1
2
3
4
5
6
7
8
9
    "Idempotency": {
      "Enable": "true",
      "Alias": "State2",
      "Duration": "86400",
      "Flow": "backend",
      "key": "idempotency-key",
      "Scope": "all",
      "Action": "auto"
    }

Inclua um segunda persistência na chave “DevPrime_State”
Nesse exemplo utilizaremos um Redis local com uma senha padrão
code .\src\app\appsettings.json

1
2
3
4
5
6
7
8
9
{
  "enable": "true",
  "alias": "State2",
  "dbtype": "redis",
  "connection": "127.0.0.1:6379,password=LltF8Nx*yo",
  "timeout": "5",
  "retry": "2",
  "durationofbreak": "45"
}

Iniciando idempotência automática no microsserviço

Agora chegou o momento de testar a configuração. Antes de iniciar o microsserviço certifique de ter ativado os containers e criado a fila no RabbitMQ.

Execute a aplicação e faça um post pela API Order
No exemplo abaixo estamos utilizando um json padrão para o post.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "customerName": "Bill",
  "customerTaxID": "string",
  "itens": [
    {
      "description": "short",
      "amount": 1,
      "sku": "XNY1AC",
      "price": 100
    }
  ],
  "total": 100
}

Observe no Log a informação da idempotência
O processo de idempotência entrou automaticamente para proteger esse request HTTP sem a necessidade de nenhuma informação do lado do consumidor da API.
DevPrime Capabilities idempotency

Efetue um segundo um post idêntico pela API Order
Ao observar esse segundo cenário já é possivel perceber que a idempotência protegeu o microsserviço impedindo uma inclusão duplicada.

A API já recebeu um retorno rejeitando o POST duplicado
DevPrime Capabilities idempotency

Ao analisar o Log nós conseguimos acompanhar todo o processo da idempotência
DevPrime Capabilities idempotency

Iniciando a idempotência manual no microsserviço

O DevPrime permite que você informe manualmente um método especifico que terá o suporte a idempotência. O primeiro passo é alterar a configuração principal e depois ir diretamente no método para adicionar a configuração.

** Alterando a chave “Action” para “Manual”**

1
2
3
4
5
6
7
8
9
    "Idempotency": {
      "Enable": "true",
      "Alias": "State2",
      "Duration": "86400",
      "Flow": "backend",
      "key": "idempotency-key",
      "Scope": "all",
      "Action": "manual"
    }

Ao utilizar a opção “Action” como “manual” se rodar novamente o microsserviço e fizer um post duplicado irá perceber que ele não vai rejeitar, pois o processo automático está desligado.

** Ativando a idempotência em um método**
Como o processo agora está manual nós ativaremos idempotência em cada método a ser protegido. No exemplo abaixo nós demonstramos essa possibilidade diretamente no Adapter Web.
code src\Adapters\Web\Order.cs

Localize no Adapter Web a API “Order” e efetue a modificação conforme apresentado.

1
2
3
4
5
app.MapPost("/v1/order", async (HttpContext http, IOrderService Service, DevPrime.Web.ViewModels.Order.Order command) => await Dp(http).Pipeline(() =>
        {
            Dp(http).Idempotency.Enable = true;
            Service.Add(command.ToApplication());
        }));

Execute novamente e vai perceber que voltou a funcionar o recurso de idempotência, porém apenas para o POST na API “/v1/order”.

Mais artigos sobre idempotência

Implementing idempotency in microservices
Idempotency in microservices and REST APIs

Última modificação March 13, 2022 (cb296b2)