Rocketseat / poc-nestjs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

POC: Nest.js (Back-end)

Esse projeto tem como propósito realizar uma POC (prova de conceito) da ferramenta Nest.js como alternativa para desenvolvimento dos projetos back-end na Rocketseat.

O projeto aqui detalhado tem como propósito testar única e exclusivamente a ferramenta e não a performance individual ou do grupo que o realizar, ou seja, nossa análise não será feita com a entrega do código e sim com os feedbacks das pessoas envolvidas em sua criação, ou seja, é super importante que ao longo do processo você vá criando uma opinião própria e anote suas dificuldades e pontos onde achou que a ferramenta lhe atendeu bem.

Projeto

O projeto receberá informações sobre vendas e reembolsos através de um sistema de mensageria assíncrona que detalharemos mais a frente, essas mensagens conterão dados da venda, produtos e cliente que deverão ser armazenados em um banco de dados.

Além de se comunicar com serviços externos para obter informações das vendas, o serviço também fornecerá uma forma de consulta dos dados cadastrados através de requisições HTTP.

O serviço deve permitir, através de HTTP, que o usuário autenticado cancele uma venda alterando seu status para cancelado e criando um novo reembolso para aquela venda.

Além de receber mensagens de serviços externos, o app deverá também se comunicar com outras aplicações externas (Ignite e Experts) quando novas compras ou reembolsos relacionados a esses produtos forem cadastrados para, então, liberar ou remover o acesso da pessoa nos produtos.

Ah, o nome desse projeto vai ser Hidra :)

Ferramentas e conceitos

O objetivo dessa POC é testar principalmente o Nest.js, mas com ele vamos aproveitar para testar algumas ferramentas e conceitos que temos interesse de adotar dentro das aplicações internas, que são:

GraphQL

Como percebemos, cada vez mais temos vários clientes consumindo as mesmas APIs e logo teremos aplicativos mobile também e, com isso, uma API RESTful acaba se tornando mais limitada para conseguir servir os dados para múltiplos clientes de uma forma escalável.

O GraphQL visa resolver esse e outros problemas permitindo que o front-end determine quais dados quer que sejam retornados do back-end evitando problemas over fetching (trazer dados que não são usados na interface) e under fetching (trazer dados de menos tendo que fazer mais requisições para o back-end).

O Nest.js possui uma integração direta com o GraphQL.

Kafka

Outra ideia interna é começar a separar mais as aplicações em estruturas de serviços que serão responsáveis por uma parte menor de responsabilidades e, para isso, precisamos ter uma forma dos serviços se comunicarem entre si.

O Kafka é um sistema de mensageria assíncrona que nos permite comunicar duas aplicações diferentes de forma escalável.

Imagine o Kafka como um sistema de pub/sub ou de filas, mas mais focado em comunicação entre serviços back-end.

O Nest.js possui uma integração direta com o Kafka.

API Versioning

É muito comum, quando temos vários clientes para o mesmo back-end, que as informações retornadas do servidor acabem impactando a experiência da aplicação front-end.

Imagine que seu front-end precise da listagem dos usuários com o endereço, mas em algum momento o campo de endereço vira um vetor já que agora o usuário pode possuir mais de um endereço. Quanto temos mais de um front-end consumindo essa informação, é difícil manter todos projetos sincronizados para consumirem a informação com o novo formato e por isso é importante mantermos versões da nossa API a fim de não quebrar os clientes que ainda estiverem consumindo o formato anterior.

Nessa POC não faremos o API versioning ainda, mas é importante entender sua motivação, pois nos projetos reais provavelmente iremos utilizar esse conceito.

O Nest.js está próximo de liberar uma forma de definirmos prefixos nas rotas dentro dos controllers facilitando o API versioning.

PostgreSQL

Além disso, é importante que o projeto desenvolvido tenha testes de integração (assim como acontece hoje no Skylab) e utilize banco de dados PostgreSQL.

Autenticação

Para autenticação não é necessário configurar uma tabela de usuários e todo processo de autenticação, apenas crie uma verificação se existe um cabeçalho chamado "Authorization" e que dentro tenha algum token mesmo que aleatório.

Setup do projeto

O primeiro passo é criar o projeto Nest dentro da pasta packages utilizando a CLI do Nest.js (é preciso instala-la de forma global).

Você pode acessar a pasta packages e executar:

nest new hidra

Agora, para executar o sistema de mensageria (Kafka) e o banco de dados PostgreSQL que serão usados pela aplicação utilize o Docker Compose (é necessário instalar o Docker e o Docker Compose em sua máquina):

Na pasta raiz do projeto, execute:

docker compose up -d

Você pode conferir que todos containers foram criados utilizando docker ps e acessar os logs de um container com docker logs {container_id}.

O Kafka está acessível na porta 9092 e o PostgreSQL na porta 5432.

Credenciais do PostgreSQL:

- USERNAME=docker
- PASSWORD=docker
- DATABASE=hidra

Agora com o projeto criado é mão na massa e daqui pra frente é com vocês! :)

Lembre-se, o intuito é você ter a experiência completa de entender a documentação do Nest.js e demais ferramentas e como configurar tudo do zero, o seu feedback do quanto isso foi fácil ou difícil é super importante pra gente.

Integração com Kafka

Para conseguir testar que sua aplicação está ouvindo as mensagens do Kafka é importante que exista uma outra aplicação produzindo as mensagens.

Dentro do Kafka temos 3 principais conceitos:

  • Topic: um canal por onde as mensagens são enviadas ou consumidas;
  • Producer: aplicação que produz as mensagens para o tópico;
  • Consumer: aplicação que consome as mensagens do tópico;

A sua aplicação com Nest.js fará o papel de consumer e irá consumir mensagens do tópico hidra que será configurado de forma automática logo.

Para produzir as mensagens criamos um projeto em Node.js extremamente simples que funciona como uma CLI e está dentro da pasta packages/producer.

Configurando producer

Dentro da pasta do projeto producer vamos começar instalando as dependências do projeto com yarn e, logo após, você pode executar o comando yarn link.

Com isso você já deve conseguir executar o projeto de forma global no seu terminal:

producer --version

Esse comando deve retornar a versão atual do producer.

Agora vamos executar o comando producer setup que vai criar os tópicos hidra, ignite e experts dentro do Kafka (esse comando pode ser executado mais de uma vez pois não cria o mesmo tópico duas vezes).

Produzindo mensagens

Ainda no producer você pode produzir mensagens para o tópico do Kafka utilizando o comando producer send seguido do evento que quer disparar, por exemplo, producer send purchase.

⚠ É importante salientar que as mensagens enviadas pro Kafka que não forem consumidas por nenhuma aplicação são armazenadas em um banco de dados e enviadas novamente no futuro, então é legal testar esses comandos somente quanto sua aplicação consumidora já estiver executando. ⚠

Event Action
purchase Send a kafka message of a purchase
refund Send a kafka message of a refund

Exemplos de eventos

producer send purchase --product ignite
producer send purchase --product experts
producer send purchase --product ignite --purchase-id p-1 --customer-id c-1

producer send refund --purchase-id p-1

Formato das mensagens

Toda purchase contém dados como os seguintes:

{
  "id": "14245d40-8e83-4786-9e73-b52dba1f60e0",
  "customer": {
    "id": "4f1ba105-8455-4fe2-9ace-28aac3733797",
    "name": "Mattie Kohler",
    "email": "Donato.Stehr@yahoo.com",
    "address": { 
      "street": "Jonathan Plain", 
      "city": "Cartwrightburgh", 
      "state": "KS"
    }
  },
  "product": { 
    "id": "ignite", 
    "amount": 1980, 
    "type": "onetime"
  },
  "createdAt": "2021-03-22T17:21:06.246Z"
}

Todo refund contém dados como os seguintes:

{
  "id": "19c6b0f7-4bb2-49ec-85bf-00ff185d7ed8",
  "purchaseId": "14245d40-8e83-4786-9e73-b52dba1f60e0",
  "createdAt": "2021-03-22T17:22:32.471Z"
}

Servidor HTTP (GraphQL)

Uma das funcionalidades importantes dessa aplicação é um servidor HTTP feito com GraphQL.

Nesse servidor deve ser possível realizar 5 operações simples:

  • Listar todas vendas (com opção de trazer também dados dos clientes e seus endereços);
  • Buscar uma venda pelo ID (com opção de trazer também dados dos clientes e seus endereços);
  • Listar todos clientes (com opção de trazer também seus endereços);
  • Buscar um cliente pelo ID (com opção de trazer também seus endereços);
  • Cancelar uma compra, alterando seu status para "canceled";

Todas operações de listagem devem ter opção de paginação com um padrão de 10 itens por página;

Enviando mensagens com Kafka

Outra funcionalidade que a aplicação deve ter é de produzir mensagens no Kafka sempre que uma venda for compensada ou reembolsada liberando ou removendo acesso de um usuário a tal produto.

A funcionalidade de controlar o acesso do usuário não é responsabilidade sua, apenas se responsabilize por enviar as mensagens via Kafka.

As mensagens devem ser enviadas aos tópicos ignite e experts, sendo o tópico ignite para mensagens de vendas e reembolsos relacionadas ao Ignite e experts para o Experts Club.

Para testar se as mensagens enviadas pela sua aplicação estão chegando corretamente você pode utilizar o projeto consumer criado na pasta packages.

Configurando consumer

Dentro do projeto consumer instale as dependências com yarn e execute o link com yarn link.

Agora utilize o comando consumer setup para criar os tópicos do Kafka que sua aplicação usará para enviar as mensagens.

Agora você pode executar o comando para ouvir mensagens enviadas para qualquer tópico do Kafka:

consumer listen ignite
consumer listen experts

Dica: Você pode usar o consumer inclusive pra ouvir eventos enviados pelo projeto producer caso sua aplicação não esteja recebendo essas mensagens assim validando se o problema está no producer ou na sua aplicação:

consumer listen hidra.purchase
consumer listen hidra.refund

Boa sorte

Como explicado no documento, a ideia desse projeto é testar AS FERRAMENTAS abordadas aqui e não sua capacidade em desenvolver utilizando-as.

Por isso, sempre que tiver alguma dúvida sobre a ideia da POC e todo texto aqui colocado, chame a gente (Diego ou João)!

É super importante que você desenvolva a aplicação sempre em conjunto para que todas pessoas tenham a experiência completa de trabalhar com as ferramentas propostas.

About


Languages

Language:JavaScript 100.0%