Como RUSHAR um serviço assíncrono de envio de dados
Tags: javascript, node, aws, webdev
Published: 2024-02-02 01:05:28

**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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zhwlbp0e9awiuigmklw.jpg)


**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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/de59wpe1tvevor94zmp5.png)




**Exemplo do processamento com Promise.AllSettled:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzum166bhjgp4y9f1s0w.png)

**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 !!