Agora vamos começar com a nossa implementação. Para o nosso exemplo, usaremos um aplicativo simples de carrinho de compras.
Crie as classes modelo
No projeto que criamos anteriormente, crie as seguintes classes na pasta Modelos.
public class Product
{
public int Product_Id { get; set; }
public string Product_Code { get; set; }
public string Product_Name { get; set; }
public double Product_Price { get; set; }
}
public class Order
{
public int Order_Id { get; set; }
public List Products { get; set; }
}
public class KeyStore
{
public string Key { get; set; }
public DateTime Expiry { get; set; }
}
Embora as classes de produtos e pedidos sejam normalmente usadas em um aplicativo de carrinho de compras, a classe Keystore é usada aqui para armazenar nossas teclas de idempotência. Nesta implementação, salvaremos essas chaves no banco de dados (DBContext). Naturalmente, você pode alterar a implementação para armazenar as chaves no cache ou em qualquer outro armazenamento de dados.
Crie a classe controladora
Clique com o botão direito do mouse na pasta dos controladores na janela Solution Explorer e crie um controlador de API chamado OrderController. Agora, digite o seguinte método de ação na classe OrderController. Este método cria um novo pedido.
(HttpPost)
public IActionResult CreateOrder((FromBody) Order order, (FromHeader(Name = "X-Idempotency_Key")) string key)
{
if (string.IsNullOrEmpty(key))
{
return BadRequest("Idempotency key is required.");
}
if (_dbContext.KeyStore.FirstOrDefault(k => k.Key == key)!= null)
{
var existingItem = _dbContext.Orders.FirstOrDefault(o => o.Order_Id == order.Order_Id);
return Conflict(new { message = "Request has already been processed.", item = existingItem });
}
_dbContext.KeyStore.Add(new KeyStore {Key = key, Expiry = DateTime.Now.AddDays(7)});
_dbContext.Add(order);
_dbContext.SaveChanges();
return Ok(order.Order_Id);
}
Examine o código acima. Uma chave de idempotência é gerada no lado do cliente e passada no cabeçalho da solicitação. Essa chave será usada pelo servidor para garantir que as chamadas repetidas para o mesmo método de ação não criem registros duplicados no banco de dados. Em outras palavras, se a chave já estiver presente na Keystore, a solicitação de criação do recurso será ignorada. A presença da chave no keystore significa que a solicitação já foi processada anteriormente.
Takeaways
Ao abraçar a idempotência, você pode criar APIs robustas, confiáveis e tolerantes a falhas. As APIs idempotentes são particularmente importantes e benéficas em sistemas distribuídos, onde os problemas de rede podem levar a um grande número de solicitações de tentativa do lado do cliente. Dito isto, você deve sempre validar dados de entrada para garantir a consistência dos dados antes de armazenar dados no banco de dados.