Salve, Deus, beleza? Continuamos essa saga aqui no Domain Driven Design. Na última aula, nós criamos o nosso evento de integração aqui, que é o Partner Created, mas já no contexto de integração. Ele é bem diferente de um evento de domínio, porque a gente vai colocar ali o nome do evento, o payload. É como se a gente estivesse transferindo uma mensagem oficial ali para o outro subdomínio, que vai ler esse evento, vai receber esse evento que aconteceu. Então, a gente estava questionando no final da aula passada se a gente sabe ler, registrar aqui um handler quando o evento acontece, mas a questão é, vou publicar direto isso já na mensageria ou vou ser mais resiliente? Porque se essa publicação falhar, a mensageria estiver fora do ar, o que vai acontecer? A gente vai perder esse evento de integração, não vai ser publicado ali. Aconteceu um erro, você devolveu que o partner foi criado, o parceiro foi criado no banco de dados, mas o evento em si não se perdeu. Então, nós vamos trabalhar aqui, aproveitando o evento de integração, com o evento em si não se perdeu. Então, nós vamos trabalhar aqui, aproveitando o evento de integração, com um pattern que é muito utilizado em microserviços, que é o Transational Outbox. Com esse pattern aqui, então, antes da gente publicar na mensageria que a gente vai usar, que vai ser o RabbitMQ, eu já aviso de antemão, nós vamos armazenar localmente e permitir que um job em background faça essa publicação lá. Pode demorar mais um pouquinho. Tem um problema nesse contexto ali? A gente conversou com os domain experts. Demorar alguns segundos para enviar um e-mail lá para o usuário, até alguns minutos generosos? Não. Então, a gente pode usar esse padrão. Então, a gente vai criar uma fila local, que vai fazer esse armazenamento, mas para trabalhar com Transaction Outbox, eu posso até trabalhar com o meu banco de dados, não tem problema nenhum. Eu vou trabalhar com um sistema de filas local utilizando o Redis, porque o Nest já tem uma integração pronta, então a gente já usa aqui. Acho que eu já tenho isso aqui. Deixa eu pegar todos os... Eu quero instalar aqui tudo de uma vez. É o BooJS, que é uma lib da comunidade Node que a gente habilita esse sistema de uma vez. É o Bool.js, que é uma lib da comunidade Node, que a gente habilita esse sistema de filas. Então, esse... npm install aqui, a gente vai instalar a biblioteca aqui que se integra com o Nest e o próprio Bool.js. Aproveitando aqui a oportunidade, eu já vou colocar dois outros containers de pé, então agora fica um pouquinho mais complexo a gente vai trabalhar o Redis que vai ficar armazenado todo os eventos de integração, aí você pode pensar assim mas o Redis trabalha em memória se ele crachar, acontecer qualquer coisa, a gente pede, não tá em produção, a gente ativa o modo de em memória se ele crachar, acontecer qualquer coisa. A gente pede não. Em produção, a gente ativa o modo de storage dele. Se ele cair lá, vai ter um storage com todos os eventos. Quando ele voltar, o jobzinho que a gente vai ter ali com o Node vai continuar publicando o que não foi publicado. Então, eu vou habilitar aqui uma imagem do Redis, sempre colocando uma porta. Eu não estou rodando a minha aplicação Node dentro ali do Docker, então tem que habilitar uma porta para fora, o WrappedMQ é a mesma coisa, a porta 15672 habilita uma aplicação web que a gente pode gerenciar o WrappedMQ, o WrappedMQ está exatamente nessa porta aqui beleza então uma vez que a gente fez essa instalação, agora exatamente nessa porta aqui. Beleza. Então, uma vez que a gente fez essa instalação, agora a gente precisa jogar aqui, fazer uma integração com esse Bool.js. Já tem tanto módulo aqui que ele foi até para lá. Banco de dados primeiro, aí eu vou colocar o Bool.module for root. Aí tem aqui o reduce. O host vai ser localhost e a porta, achei que o compile ia preencher aqui a meia 379. Tá. Aí agora, dentro do nosso módulo de eventos, nós vamos precisar criar a instância, ele dá a fila, que vai ser justamente o armazenamento lá dentro do Redis, que o jobzinho do BOLJS vai ficar olhando lá para ver se tem novos jobs. Então, aqui na parte do EventsMod, deixa eu fechar esse core aqui por enquanto a gente já está com um módulo que tem muitas coisas vou colocar ele depois aqui do depois de tudo vai ser o bool module editor queue e aqui eu vou dar o nome da minha fila. Então, vou registrar aqui. Integration events. É um nome mais do que sugestivo. Show de bola. Então, com isso aqui feito, vamos rodar, pelo menos, a nossa aplicação. Deixa eu ver se não estou rodando em outro lugar aqui, tem dois terminais aí npm run start dev ele vai dar um erro justamente porque eu vou ter que subir aqui o meu docker compose de novo com redis e com o reptmq, o reptmq já fica ali, então é só fazer um Docker Compose Up novamente, subindo ali o MySQL e o ReptMq, o Redis deve ter sido bem rápido e nem vai ser mostrado aqui. Então vamos rodar aqui o nosso projeto e ele está dando um erro de default, isso aqui é uma questão de TypeScript, deixa eu colocar aqui uma instrução que é o S interoperability que é o S interoperability pra ele poder trabalhar com módulos antigos aqui, depois que a gente fez essas instalações e deu zica lá, mas o que eu quero saber aqui é se o bool module carregou se tivesse dado qualquer problema aqui, ele ia dar um erro. Então agora, o que eu vou fazer aqui dentro do módulo de eventos? A gente vai chegar aqui e pegar o integration events kiwi, que é a nossa fila local, que é do tipo queue. Do bool, está ali do bool, que eu importo lá em cima. E eu vou falar aqui que eu vou trabalhar sempre com todo o dado que eu tiver na minha fila vai ser um integration event. Tipo de bola. o dado que eu tiver na minha fila vai ser um integration event. De boa. Aí aqui embaixo, eu vou chamar o domain event manager, editor. Eu quero registrar, quando acontecer o partner created.name, nós vamos chamar aqui... Primeiro, vamos gerar o nosso evento de integração. Então, integration event vai ser igual a new partner. Created integration event, passando o evento. Então, eu gerei o evento de integração, já está lá do jeito que eu quero. Aí eu chamo o meu this integration event que eu ia ir fazendo um add desse dado e posicionando ele lá na fila. Esse é o primeiro passo. Pronto. Então agora toda vez que a gente criar um partner, ele vai publicar na nossa fila local e eu vou criar um jobzinho para publicar no RabbitMQ. Vamos carregar aqui novamente, que parece que ele deu um erro ali. Ele está falando que, ah, eu esqueci de fazer uma coisa aqui em cima. Na verdade, esse serviço tem que ter um decorator ainda em cima Para funcionar Que é o mesmo nomezinho da fila que a gente Registrou ali em cima, que é o Integration Events Eu estava falando aqui que o módulo Na verdade que o serviço Ele não conseguiu identificar Que serviço era esse Show de bola Então Vamos criar aqui o nosso publicador no ReptMQ. A gente vai ter que instalar aqui, na verdade, uma outra lib ainda, que é... Agora é com ReptMQ. Isso aqui é um detalhe importante sobre o Nest porque o Nest já tem suporte para o Raptime Q mas no caso da integração dele eu prefiro usar uma outra lib que a comunidade usa bastante, que é essa aqui, que ela permite uma comunicação melhor ali, trabalhando com os tipos de tópicos diferentes eu posso trabalhar com UDC Card e outras coisas assim, que o Nest, por padrão, não vai permitir. A integração dele com o WebT é mais simples. Então, aqui ele está dando questão com a versão do Nest. Eu vou colocar o "-f", que a Lib aqui ainda tem que fazer uma atualização, mas essa versão aqui vai funcionar com o Nest. Então, ele vai mostrar esses errinhos aqui, show de bola. Aí agora, a gente vai ter que criar um módulo para o ReptMQ. Aí ele vai perguntar onde que eu quero criar. Vou criar aqui. Que é a nossa aplicação principal. Então, no nosso novo módulo aqui do ReptMQ, a gente já tem vários módulos aqui na nossa aplicação. Eu vou copiar as configurações aqui, apesar que não é grande. É só pra gente poder ganhar um tempo aqui. Esse módulo vai ser global, para a gente conseguir usar o serviço de publicação do Revit MQ em qualquer lugar. Então, aqui eu vou importar o da biblioteca, mas tem um nome nosso que o MQ é todo minúsculo. Então, aqui a gente vai fazer um for root, passando a referência do próprio módulo, Aqui a gente vai fazer um for root passando a referência do próprio módulo, passando a URI de comunicação de autenticação ali com o App Team Q, que é usuário e senha, é admin, admin. Aí eu passo aqui que o nosso próprio módulo vai ficar importado dentro dessa configuração e eu vou expor o módulo do ReptMQ. Isso aqui vai fazer com que o serviço do ReptMQ fique exposto. Isso aqui é uma configuração, não quero entrar em detalhes do Nest, mas a gente precisa fazer dessa forma. Aí agora que eu tenho o ReptMQ funcionando, ele já está integrado aqui, aqui nessa linha, nós vamos chegar aqui no domain events, eu quero criar um serviço aqui. Inclusive dá para a gente poder... Eu vou criar ele do zero vou chamar ele de integration events .publisher.ts que é o nosso publicador então é uma classe que vai ter integration events publisher Então, é uma classe que vai ter integration events publisher. Ele vai receber aqui no construtor o serviço do ReptMQ que a gente vai publicar. Então, vou colocar aqui um private amqp-connection, é exatamente isso aqui, em porto ali da lib. MQP Connection é exatamente isso aqui, imposta ali da Lib. E eu vou colocar aqui o método handle, que é o método que vai ser ativado pelo job quando ele receber o evento e a gente vai publicar. Então, aqui eu recebo o job com os dados do próprio job, importando ali do bool. Eu estou lidando aqui com qualquer evento de integração então coloca esse generic para que eu posso lidar aqui com os dados tem o async aqui um return para falar que deu tudo certo se não deu tudo certo ele pode ser eu posso retentar mais tarde depois aí eu vou fazer um this amqp-publish lá no ReptMq. Eu quero publicar num amq. Pode ser numa topic ou numa direct, porque numa topic a gente pode permitir que várias filas recebam isso. Se tem que é direct também. Vou colocar um direct para não complicar aqui. E aí eu estou publicando aqui no routing key, que vai ser o próprio nome do evento. Então, em job data, eu tenho os dados do evento, que é o próprio evento de integração. eu tenho os dados do evento que é o próprio evento de integração. Então, eu estou publicando com esse nome aqui, a Routing Key, que a Exchange vai redirecionar, e os dados do próprio evento que é o Job Data. Ficou de bola. Isso aqui precisa ter um await. Aqui, preciso de um process como decorator em cima e aqui um processor para falar qual que é a fila que a gente vai ler aqui. Isso aqui precisa ser registrado Aqui no nosso provedor Então eu estou colocando no módulo de eventos Ali para poder fazer essa gerência Aqui E está errado Esse nome na verdade Publisher Maravilha Agora eu estou rodando aqui na primeira linha Vamos rodar aqui A nossa aplicação Olha, já consegui conectar com sucesso ali no ReptMQ Não temos nenhum errinho, tudo certo Maravilha pessoal, então vamos fazer aqui, a gente tem que acessar o ReptMQ. Deixa eu tirar todas essas coisas daqui. Então eu vou acessar aqui localhost na porta 15672. Aí tem o Revit MQ aqui. A interface do Revit. Desse tamanho aqui já está bom, né? Já tem a Exchange e a MQ Direct que eu vou conectar. Mas vamos supor que eu tenho lá a minha fila de e-mails vou colocar aqui e-mails adicionei uma nova fila aí eu vou fazer o bind dela com o nosso roteador então aqui vai ser a amq direct e a routing key vai ser o próprio partner created que é o que a gente quer ouvir E a routing key vai ser o próprio partner created, que é o que a gente quer ouvir. Então, está feito aqui o nosso bind. A gente vai ver a mensagem chegando aqui. Então, vamos fazer aqui o teste. Vou publicar... Ou melhor, vou cadastrar um novo parceiro. Será que já chegou para cá? Aparentemente não. Então tem alguma coisa que a gente comeu bola aqui. Vamos ver se a gente... Aqui está certo. Ele vai adicionar lá bonitinho. Vamos ver se ele está chegando aqui só para desencargo. Integration Events. a gente faz um novo partner aqui, tá, ele está chegando ali. Então, agora a gente tem que ver se ele está chegando aqui. Deixa eu ver se o nomezinho aqui está igual que a gente determinou ali em cima. Então, o nome aqui da fila tem que estar com o mesmo nome ali. Então ele está. Então aqui vamos ver se o job... Vou fazer um console.log aqui para ver se está chegando ali. O partner. Ele está chegando ali. Ah, na verdade o nosso nome está certo, por isso que a mensagem não chegou lá, porque o nome do nosso evento poderia ter um nome menor também se eu quisesse. Eu coloquei assim só para... A gente tem um exemplo aqui, mas nomes menores vão ser melhores eu poderia deixar o próprio partner created como no event name ali então vamos lá, aqui vem o nome, bind beleza, aí eu volto aqui pra fila e a gente publica novamente então é só cadastrar o novo partner. Chegou uma mensagem aqui, agora a gente vai ver essa mensagem. Então, vamos fazer aqui um getMessages. Está aqui a nossa mensagem de integração, feita com todo esse conceito do DDD, com o nome específico, com o payload, que é o ID e o nome do partner, a versão do evento e ocorreu em determinada data. é um transactional outbox para a gente poder fazer essa publicação porque imagina só, o AppChemical está fora do ar e etc a gente coloca numa fila local, pode ser com o seu banco de dados, pode ser com qualquer coisa do seu framework e aí esse jobzinho em background que vai fazer a publicação, imagina que às vezes a latência com o AppChemical e a comunicação demora-se um pouco então colocando o local, vai ser bem mais rápido. Eu devolvo ali a resposta HTTP para o usuário mais rapidamente. Depois, um jobzinho ali vai fazer essa publicação. Então, a comunicação entre os subdomínios sendo assíncrona, a gente consegue desacoplá-los bem mais, ter um processo que eu posso escalar essas duas aplicações. A gente está falando aqui num caso de microserviços. Quando eu trabalho com assíncrona, é o melhor dos mundos, porque eu não fico preso aos outros domínios que eu tenho. Apesar que a gente tem aqui uma certa prisão na hora de fazer o pagamento, porque a gente depende de um sistema de terceiro. Mas aí vem ali um anti-corruption layer justamente para poder evitar que o domínio de pagamentos vaze para dentro do nosso domínio e também até uma certa inteligência ali para poder avaliar vários gateways, qual que está funcionando, qual que está com menor latência, enfim. Na próxima aula, a gente termina o processo de fazer no e-mail, mas a gente já tem aqui um evento de integração funcionando. Então, pessoal, é isso aí. E até a próxima.