Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
September 27, 2022 11:31 am GMT

Garantindo a idempotncia de eventos com Redis

Importante: Esse artigo assume que o pblico alvo tem algum conhecimento prvio relacionado a:

  • Eventos
  • Processamento assncrono
  • APIs
  • Redis
  • Kafka.

Introduo

Quando se fala em processamento assncrono, comum que se fale em eventos. Eventos so aes que ocorrem em um determinado momento e que podem ser disparados por uma ao ou por um evento externo e o processamento dele pode ser feito em um momento posterior.

Mas o que Idempotncia?

Conceito de idempotncia, segundo a Wikipdia:

Idempotncia a propriedade que algumas operaes tm de poderem ser aplicadas vrias vezes sem que o valor do resultado se altere aps a aplicao inicial.

No contexto deste artigo, iremos utilizar o conceito de idempotncia como parte de uma estratgia para evitar o processamento repetido de notificaes.

Contextualizao

Fao parte de um time que, entre outras aplicaes, dono de uma API responsvel por receber notificaes via webhook com o intuito de public-las em tpicos do Kafka, consumidos por outras aplicaes, como, por exemplo, um worker responsvel por tratar e envi-las para vrios destinos, como o Open Search do time, um Data Lake compartilhado com a companhia e alguns webhooks de outros squads.

Problema

Uma das premissas que nenhuma notificao pode ser perdida, por isso, temos, em nossos workers, estratgias como Retries e DLQs para garantir que, mesmo que qualquer parte do processo falhe, a notificao ser enviada para o destino. Alm disso, por lidarmos com fontes externas que enviam dados via webhook, h a possibilidade de que falhas na comunicao entre os softwares faam com que esses dados, vez ou outra, sejam processados mais de uma vez. Assim, chegamos na seguinte pergunta:

Como garantir que uma notificao ser processada apenas uma vez?

Soluo

Para garantir que uma notificao no ser enviada duas vezes para o mesmo destino, utilizamos o Redis para armazenar informaes sobre as notificaes que j foram enviadas. Quando uma notificao enviada, ela armazenada no Redis. Quando uma notificao reprocessada, verificamos se ela j foi enviada para o Redis. Se ela j foi enviada, no precisamos envi-la novamente. Se ela ainda no foi enviada, precisamos envi-la.

Exemplo fictcio

Desenho inicial da soluo

  • Nome da API: payment-api,
  • Tipo da Notificao: paymentNotification,
  • Descrio: API que recebe informaes de pagamentos realizados por todas as lojas de uma companhia via webhook.
  • Schema:
{  "id": "number",  "date": "string",  "method": "string",  "installments": "number",  "store_id": "number",}

Importante: Nesse exemplo, assumimos uma premissa que id nico apenas para o contexto da loja que o gerou, representada por store_id, e durante a data que foi gerado, date.

Gerao da chave do Redis

Para as notificaes do tipo paymentNotification, recebidas via webhook por payment-api, foi gerada uma lista com o nmero mnimo de suas propriedades que, juntas, formam uma chave idempotente.

Considerando a premissa que assumimos, as propriedades eleitas para formar uma chave idempotente seriam:

  • id
  • store_id
  • date

Isolando s trs propriedades em um novo objeto, teramos algo como:

{  "id": 123,  "store_id": 123456789,  "date": "2022-01-01T00:00:00.000Z"}

E essa seria a chave:

123-123456789-2022-01-01T00:00:00.000Z

Nesse exemplo temos apenas a payment-api, porm, em um cenrio real, poderamos ter uma instncia do Redis compartilhada por vrias APIs, cada uma com suas prprias entidades de domnio, portanto, com suas prprias listas de propriedades que formariam uma chave idempotente.

Dado esse cenrio onde pode-se ter vrias APIs utilizando um Redis compartilhado, para evitar conflitos podemos adicionar, por exemplo, o nome da API e o tipo da notificao como prefixo da chave idempotente, ficando assim: :nome_api-:tipo_notificacao-:id-:store_id-:date.

Com a nova adio a chave ficou assim:

payment-api-paymentNotification-123-123456789-2022-01-01T00:00:00.000Z

Porm, tendo em vista que date no ser lida por humanos, podemos simplificar a chave e utilizar seu valor em milissegundos.
Agora essa a nova chave:

payment-api-paymentNotification-123-123456789-1640995200000

Mas qual parte do dado usar como valor?

Agora que j temos a chave, precisamos definir o valor que ser armazenado nela, para isso, precisamos entender o que queremos que acontea quando uma determinada notificao for reenviada. Entre as opes, temos:

  1. Armazenar o valor da resposta retornada quando a notificao foi enviada pela primeira vez.
  2. Armazenar o valor true ou 1 para indicar que a notificao j foi enviada.

Analisando as opes

  • A primeira opo interessante, pois, caso uma notificao seja recebida mais de uma vez, poderemos retornar o mesmo valor sem process-la novamente, tendo em vista que, pode ser que o remetente esteja reenviando a notificao porque no recebeu a primeira resposta ou algo do tipo. Porm, essa opo tem um problema: o valor pode ser muito grande, o que pode gerar um problema relacionado a espao, por exemplo.

  • A segunda opo mais simples, porm, do ponto de vista do espao, bastante eficiente, se tornando to interessante quanto a primeira opo em alguns contextos, por exemplo, num caso em que o remetente no aguarda uma resposta ou aguarda uma resposta padro, como 200 OK.

Opo escolhida

No ponto de vista da payment-api que foi citada como exemplo, a segunda opo foi escolhida, pois no h um remetente aguardando uma resposta especfica, portanto, no h necessidade de armazenar o valor da resposta.

Desenho da soluo

Desenho final da soluo

Armazenando referncias de notificaes no Redis

A ideia principal que quando uma requisio via webhook chegar para payment-api, a API ir gerar a chave idempotente e, caso ela no exista no Redis, ir processar a requisio e armazenar suas referncias nele, caso contrrio, ir retornar a resposta default, que ser 200 OK e adicionar um log que a requisio foi ignorada, pois j foi processada. No momento que j temos a chave, o valor e a certeza de precisamos armazen-los, utilizamos o comando SET do Redis, que recebe como parmetros a chave e o valor.

Expirando a chave

Agora que j temos chave e valor armazenados no Redis, precisamos definir o tempo de expirao da chave. Para isso, utilizamos o comando EXPIRE do Redis, que recebe como parmetros a chave e o tempo de expirao em segundos. No caso do exemplo, iremos definir uma expirao de um dia, ou seja, 86400 segundos.

Resumindo

  • Gerar a chave idempotente
  • Verificar se a chave existe no Redis
  • Caso no exista, processar a requisio e armazenar a chave no Redis com um tempo de expirao de um dia
  • Caso exista, retornar a resposta default e adicionar um log que a requisio foi ignorada, pois j est no Redis

Concluso

Esse um exemplo de como utilizar o Redis para evitar que requisies via webhook sejam processadas mais de uma vez, porm, esse no o nico cenrio em que o Redis pode ser utilizado, ele pode ser utilizado para muitas outras coisas, como, por exemplo, para armazenar dados de sesso, dados de autenticao, dados de cache, etc.

Espero que tenham gostado do artigo, qualquer dvida ou sugesto, podem deixar nos comentrios.


Original Link: https://dev.to/pjonatansr/garantindo-a-idempotencia-de-eventos-com-redis-1opa

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To