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.