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:
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:
Exemplo do processamento com Promise.AllSettled:
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)
Legal o artigo hem! Principalmente pelos "esquemas" de utilizar o S3 para salvar dados, hehehe.