DEV Community

Sam
Sam

Posted on • Edited on

Como RUSHAR um serviço assíncrono de envio de dados

Olá amigos,

Recentemente tive que fazer um projeto para ontem..

Uma dos pontos chave era: Tornar o cadastro de um produto, um cadastro de múltiplos. A feature original se encontrava em um contexto de difícil manutenção (põe diíficil nisso)

O desenvolvimento deveria ser extremamente rápido.

Eis que com um breve refinamento veio a ideia:

Clássica tática de Serverless Async - S3 + SQS + Lambda

Se liga nessa gambi braba...
Ao qual criamos um serviço que faz multi-requests pro nosso endpoint original.

Dessa forma não foi necessário alterar diretamente o domínio da aplicação e criar um novo caso de uso.

A estrutura:

Image description

1) Um big array de registros enviado para o endpoint do monolito

2) Monolito salva um JSON no S3, pega o link e envia para um SQS. Ele também envia uma mensagem amigável pro front.

Porque S3 + SQS?

  • Porque literalmente já vem com a infra pronta, que facilita muito para ganho de tempo.

Mas porque o S3?

  • O SQS tem um limite no tamanho das mensagens, então uma prática(gambiarra) comum é armazenar dados no S3 e enviar os links de acesso desses dados para a fila.

3) Uma lambda recebe um trigger quando a URL do S3 chega no SQS e consome as mensagens da fila.

Há um pequeno desafio aqui, Lambdas escalam horizontalmente por chamadas... Então..

Como evitar que outra instancia da lambda consuma a mesma mensagem?

  • Fazer um setup de visibilidade na AWS e apagar/transferir mensagens lidas para outro lugar

4) Lambda faz o download do JSON no S3 e faz multiplas requests pro endpoint de cadastro múltiplo

Há um outro ponto interessante aqui.

Fazer requests uma a uma iria tornar tudo mais trabalhoso e possivelmente daria um timeout na Lambda.

  • Para resolver esse caso utilizamos o Promise.allSettled() para realizar as requests de maneira paralela e ter um controle melhor das falhas.

As promises com Status Rejected teriam seus dados tratados em outro momento, armazenados em um bucket de logs, ao ponto de permitir enviar por e-mail uma devolutiva para o cliente do porque esses dados não foram cadastrados.

Exemplo do Handler da Lambda:

Image description

Exemplo do processamento com Promise.AllSettled:

Image description

5) Um último desafio, validar uma AWS Lambda localmente

Hoje com o serverless framework https://www.serverless.com/ é possível reproduzir vários recursos da AWS localmente, mas uma Lambda Trigger com SQS ainda é um desafio CHATISSIMO.

Nesse caso, como Lambdas geralmente são soluções simples e isoladas a opção para validar comportamentos das sub-funções foi Unit Tests.

Não costumo usar unit tests em todos os casos mas visto as limitações de reproduzir alguns padrões da AWS localmente, podem ser uma solução.

Pontos interessantes/Possíveis dúvidas

- Porque não usou generators?
Porque o caso de uso não terá dados tão grandes assim e Lambda tem um tempo limite de execução.

- Porque serverless?
O Endpoint não será utilizado com alta frequência e o tempo de desenvolvimento era restrito.

- S3 com JSONS meu parceiro ????
S3 é o noSQL do povo (em alguns casos)

- Tem DLQ, Retry Bucket pra Logs ??
Tem sim, só não entrei no merito pra tentar ser direto ao caso da solução

- E se a Lambda gargalar ???
Hoje da pra fazer Lambda com GO. Go é bala

Obrigado pela leitura !!

Top comments (1)

Collapse
 
analistacarlosh profile image
Carlos Rodrigues

Legal o artigo hem! Principalmente pelos "esquemas" de utilizar o S3 para salvar dados, hehehe.