[DESAFIO] Processamento assíncrono simples e resiliente - Eu estou preso nesse desafio a dias, vim pedir socorro! Acho que você vai gostar....
Fala pessoal! Tudo certo?
Ultimamente venho esbarrando em uma dificuldade para resolver um problema e vim aqui compartilhar com vocês este desafio interessante e discutir possíveis soluções... Espero que aprendamos algo juntos nessa jornada!
O problema
De maneira resumida: o problema consiste em conseguir processar eventos de forma assíncrona com um equilíbrio entre complexidade/custo e resiliência/consistência. Basicamente o objetivo é conseguir registrar a intenção de reagir a um evento e ter a possibilidade de reprocessar este evento em caso de falha sem a necessidade de um componente de infra adicional a um banco de dados.
Um exemplo:
é bem comum precisarmos realizar o envio de e-mails após uma determinada ação de um usuário em nossos sistemas. Porém, o fluxo principal daquela ação que "triggou" o envio do e-mail não deveria (na maioria dos casos) estar atrelado ao sucesso ou não do envio desta mensagem. Para isso é bem interessante utilizar algum método de processamento assíncrono para isso.
Existem diversas formas de atingir este comportamento, vou listar algumas aqui:
- Utilizar alguma lib de pubsub. O node.js por exemplo tem um módulo nativo (link) para isso e também uma lib (link) com algumas abstrações que se mostra muito útil e poderosa. O nest.js possui uma abstração da segunda que é muito simples de utilizar.
- Nest.js por exemplo tem disponível uma lib para cqrs que implementa uma maneira muito interessante de cadastrar e reagir a diferentes eventos dentro de um sistema
- Utilizar um sistema de filas como rabbitMQ ou Kafka. Estas ferramentas possibilitam uma gama ENORME de possibilidades e configurações para realizar diferentes tipos de processamentos assíncronos e distribuidos.
Repare que, das opções listadas acima, das duas uma: ou você não tem uma maneira esperta de reprocessar e mapear os erros que aconteceram, ou você precisa configurar e manter uma infra completamente adicional ao mínimo que uma aplicação em estado inicial/MVP precisaria...
E esta tem sido minha principal dificuldade!
Eu estou procurando um meio termo entre o simples processamento assíncrono dentro do mesmo processo e a configuração de um datastore completamente adicional ao mínimo necessário para testar minhas ideias e colocá-las rapidamente em produção.
Minha ideia:
envolver o handle dos eventos de alguma das duas libs (nestjs-events ou nestjs-cqrs) com uma chamada ao meu banco de dados (praticamente indispensável a qualquer aplicação independente do tamanha ou simplicidade). Uma chamada antes do processamento do evento, onde guardo o evento emitido e os dados passados, e outra chamada após o processamento atualizado o status para SUCCESS ou FAILED. Desta forma eu poderia reprocessar todos os eventos que por ventura viesse a falhar facilmente!
Esta ideia não é algo 100% novo e portanto me parece bem factível. Ela se parece muito com o conceito de middlewares/interceptors que possuímos em interfaces HTTP por exemplo.
E aí? Você sabe uma maneira esperta de resolver este desafio? Me conte como resolveria e se vê valor em uma solução como esta.
Fique ligado pois daqui a pouco vou compartilhar o template de aplicação que tenho utilizado contendo:
- Hexagonal arch
- Testes unitários
- Testes de integração
- Modulo de métricas e monitoramento
- Modulo de autenticação e autorização
- Modulo de Envio de notificações (email)
- Estratégias de programação funcional que deixam o código limpo e fácil de racioncinar
Só falta resolver esta ponta solta e estará pronto para ser compartilhado!!
Estamos juntos!! Valeu pela atenção e espero que você também tenha se sentido desafiado e interssado por este problema como eu!
Abs,