{"id":24,"date":"2020-05-02T10:39:00","date_gmt":"2020-05-02T13:39:00","guid":{"rendered":"https:\/\/dumba.dev.br\/?p=24"},"modified":"2026-01-05T10:45:12","modified_gmt":"2026-01-05T13:45:12","slug":"comunicacao-entre-api-net-core-usando-rebus-e-rabbitmq","status":"publish","type":"post","link":"https:\/\/dumba.dev.br\/index.php\/2020\/05\/02\/comunicacao-entre-api-net-core-usando-rebus-e-rabbitmq\/","title":{"rendered":"Comunica\u00e7\u00e3o entre API .NET Core usando REBUS e RabbitMQ"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>O que \u00e9 REBUS?<\/strong>&nbsp;Segundo o Git Hub do REBUS, \u00e9 uma \u201cimplementa\u00e7\u00e3o de um barramento de servi\u00e7o enxuto\u201d, ou seja, faz toda a comunica\u00e7\u00e3o com sua fila de mensageria (RabbitMQ, MSMQ, Azure Service Bus, etc.). Ele faz toda a parte de envio e escuta de sua fila de mensageria.&nbsp;<strong>O projeto.<\/strong>&nbsp;Foi criado uma POC com uma API de pedidos e uma API de estoque. Ao efetuar o pedido, uma mensagem \u00e9 enviada para a API de estoque para que remova a quantidade do item do seu estoque. Se tudo der certo a API estoque envia uma mensagem a API de pedidos informando que esta tudo Ok, caso contrario, estoque envia uma mensagem a API de pedidos informando que existe uma inconsist\u00eancia. Temos 3 eventos nesse processo.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Retirar item do estoque<\/li>\n\n\n\n<li>Confirmar retirada estoque<\/li>\n\n\n\n<li>Informar inconsist\u00eancia<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Foi criado um docker-compose para facilitar e subir o banco de dados em MySql e o RabbitMQ. Va a pasta Docker do projeto com seu terminal e digite \u201c<em>docker-compose up<\/em>\u201d (Tenha o docker instalado na sua maquina). Caso n\u00e3o queria o Docker, fique a vontade para instalar o MySql e o RabbitMQ em sua maquina, ou fazer como desejar. :D. Para criar o banco de dados do projeto, v\u00e1 a pasta de cada projeto (Pedidos.Api e Estoque.Api) com o seu terminal e rode o migrations com o comando: \u201c<em>dotnet ef database update<\/em>\u201d. Assim o seu banco de dados ser\u00e1 constru\u00eddo e populado.&nbsp;<strong>Configurando o REBUS.<\/strong>&nbsp;Para utiliza\u00e7\u00e3o do REBUS \u00e9 preciso baixar os pacotes.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">&lt;PackageReference Include=\"Rebus\" Version=\"6.1.0\" \/&gt;\n&lt;PackageReference Include=\"Rebus.RabbitMQ\" Version=\"6.0.0\" \/&gt;\n&lt;PackageReference Include=\"Rebus.ServiceProvider\" Version=\"5.0.3\" \/&gt;\n&lt;PackageReference Include=\"Rebus.Wire\" Version=\"5.0.0\" \/&gt;<\/pre>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>API Estoque<\/strong><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">No projeto de estoque, vamos receber um evento para retirar item do estoque. Precisamos criar o evento e o handler para executar esse evento.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vemos nessa classe uma simples implementa\u00e7\u00e3o da mensagem que precisamos para retirar o item do estoque. Ela contem o Numero do Pedido e uma lista de itens com o ID do produto e a quantidade a ser retirada.&nbsp;<strong>Handler<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">    public class RemoverEstoqueEventHandler : IHandleMessages&lt;RemoverEstoqueEvent&gt;\n    {\n        readonly IProdutoRepository _produtoRepository;\n        readonly IBus _bus;\n\n        public RemoverEstoqueEventHandler(IProdutoRepository produtoRepository, IBus bus)\n        {\n            _produtoRepository = produtoRepository;\n            _bus = bus;\n        }\n\n        public Task Handle(RemoverEstoqueEvent message)\n        {\n            \/\/busca a lista de produtos que deve baixar o estoque.\n            foreach(var item in message.Itens)\n            {\n                var produto = _produtoRepository.ObterPorId(item.ProdutoID);\n\n                \/\/Caso o produto nao foi encontrado lanco um evento para o pedido de inconformidade.\n                if (produto == null)\n                {\n                    _bus.Publish(new EstoqueInconsistenteEvent(message.NumeroPedido, \"Produto nao encontrato para o id informado.\"));\n                    return Task.CompletedTask;\n                }\n\n                produto.DiminuirQuantidadeEstoque(item.Quantidade);\n\n                \/\/Vefico se o estoque ficou correto.\n                if (!produto.EhValido())\n                {\n                    _bus.Publish(new EstoqueInconsistenteEvent(message.NumeroPedido, string.Join(\"| \", produto.Erros)));\n                    return Task.CompletedTask;\n                }\n\n                _produtoRepository.Alterar(produto);\n            }\n\n            \/\/Grava a baixa do estoque.\n            _produtoRepository.Gravar();\n\n            _bus.Publish(new EstoqueFinalizadoEvent(message.NumeroPedido));\n\n            return Task.CompletedTask;\n        }\n    }<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">O Handler, implementa a interface&nbsp;<em>IHandlerMensages<\/em>&nbsp;que faz parte do pacote do Rebus. Na interface deve informar o evento correspondente.&nbsp;<em>IHandlerMensages&lt;RemoverEstoqueEvent&gt;<\/em>&nbsp;Essa interface exige que se implemente o Handler.&nbsp;<em>&nbsp;public Task Handle(RemoverEstoqueEvent message)<\/em>&nbsp;Nesse m\u00e9todo \u00e9 onde ficar\u00e1 todo o seu c\u00f3digo referente a esse evento. Lembrando que aqui e somente um exemplo. Pode ser referenciados servi\u00e7os de dom\u00ednios, servi\u00e7o de aplica\u00e7\u00e3o ou qualquer outra coisa relevante ao seu negocio ou arquitetura implantada. Nesse Handler, eu simplesmente valido se o ID do produto existe no banco de dados e se a quantidade de estoque n\u00e3o ficou abaixo de zero.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var produto = _produtoRepository.ObterPorId(item.ProdutoID);\n\n\/\/Caso o produto nao foi encontrado lanco um evento para o pedido de inconformidade.\nif (produto == null)\n{\n    _bus.Publish(new EstoqueInconsistenteEvent(message.NumeroPedido, \"Produto nao encontrato para o id informado.\"));\n    return Task.CompletedTask;\n}\n\nproduto.DiminuirQuantidadeEstoque(item.Quantidade);\n\n\/\/Vefico se o estoque ficou correto.\nif (!produto.EhValido())\n{\n    _bus.Publish(new EstoqueInconsistenteEvent(message.NumeroPedido, string.Join(\"| \", produto.Erros)));\n    return Task.CompletedTask;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Caso alguma inconsist\u00eancia ocorra eu envio outro evento ao sistema com o Numero do Pedido e o motivo da inconsist\u00eancia.&nbsp;<em>_bus.Publish(new EstoqueInconsistenteEvent(message.NumeroPedido, &#8220;Produto nao encontrato para o id informado.&#8221;));<\/em>&nbsp;Caso tudo esteja correto, eu envio outro evento&nbsp;<em>_bus.Publish(new EstoqueFinalizadoEvent(message.NumeroPedido));<\/em>&nbsp;Esses eventos v\u00e3o para a fila RabbitMQ para processamento na API de pedidos.&nbsp;<strong>Arquivo Setup do API Estoque.<\/strong>&nbsp;No arquivo setup devemos configurar o REBUS. No m\u00e9todo&nbsp;<em>public void ConfigureServices(IServiceCollection services)&nbsp;<\/em>adicione o rebus.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">            var fila = \"fila_pedido\";\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; services.AddRebus(c =&gt; c.Transport(t =&gt; t.UseRabbitMq(Configuration.GetConnectionString(\"RabbitConnection\"), fila)));\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; services.AutoRegisterHandlersFromAssemblyOf&lt;RemoverEstoqueEventHandler&gt;();<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Informamos ao REBUS que estamos usando o RabbitMQ para transporte de nossas mensagens, na&nbsp;<strong>fila_pedido<\/strong>. No m\u00e9todo&nbsp;<em>public void Configure(IApplicationBuilder app, IWebHostEnvironment env), v<\/em>amos configurar o que o REBUS vai esperar na fila.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">app.ApplicationServices.UseRebus(c =&gt;\n{\n    c.Subscribe&lt;RemoverEstoqueEvent&gt;().Wait();\n});\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ao cair na fila qualquer mensagem de&nbsp;<em>RemoverEstoqueEvent<\/em>&nbsp;ele vai automaticamente chamar o handler&nbsp;<em>RemoverEstoqueEventHandler.<\/em>&nbsp;&nbsp;<\/p>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>API Pedidos<\/strong><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Para o projetos de Pedidos, temos um evento que deveremos enviar (<em>RemoverEstoqueEvent<\/em>) e dois eventos que podemos receber (<em>EstoqueFinalizadoEvent<\/em>&nbsp;e&nbsp;<em>EstoqueInconsistenteEvent<\/em>). Na controller de pedidos, ao incluir o pedido nos lan\u00e7amos o evento para remover o item do estoque.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[HttpPost(\"\")]\npublic async Task&lt;IActionResult&gt; Incluir(Model.Pedido pedido)\n{\n    _pedidoRepository.Incluir(pedido);\n\n    var evento = new RemoverEstoqueEvent(pedido.Numero);\n\n    foreach (var item in pedido.Itens)\n    {\n        evento.Itens.Add(new RemoverEstoqueItem(item.ProdutoID, item.Quantidade));\n    }\n\n    await _bus.Publish(evento);\n\n    return Ok($\"Pedido {pedido.Numero} incluido com sucesso.\");\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note que estamos utilizando a interface IBus do REBUS para disparar os eventos.&nbsp;<em>await _bus.Publish(evento);<\/em>&nbsp;Isso far\u00e1 com que o evento enviado caia na fila do RabbitMQ para que a API Estoque receba a mensagem. Para que a API Pedidos receba as mensagens de estoque, fazemos como foi criado na API de Estoque, so que aqui em Pedidos, temos dois Handlers, pois podemos receber duas mensagens (<em>EstoqueFinalizadoEvent<\/em>&nbsp;e&nbsp;<em>EstoqueInconsistenteEvent<\/em>). Em pedido eu chamei de&nbsp;<em>PeditoEventHandler&nbsp;<\/em>no qual informo os dois eventos que devo receber.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public class PedidoEventHandler : \n        IHandleMessages&lt;EstoqueFinalizadoEvent&gt;,\n        IHandleMessages&lt;EstoqueInconsistenteEvent&gt;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">No&nbsp;<em>EstoqueFinalizadoEvent<\/em>&nbsp;eu somente informo o Numero do Pedido para finalizar o pedido.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public Task Handle(EstoqueFinalizadoEvent message)\n{\n    var pedido = _pedidoRepository.ObterPorId(message.NumeroPedido);\n    pedido.Finalizar();\n    _pedidoRepository.Alterar(pedido);\n\n    return Task.CompletedTask;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">No&nbsp;<em>EstoqueInconsistenteEvent<\/em>&nbsp;eu cancelo o pedido e informo o motivo da inconsist\u00eancia.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">public Task Handle(EstoqueInconsistenteEvent message)\n{\n    var pedido = _pedidoRepository.ObterPorId(message.NumeroPedido);\n    pedido.Cancelar(message.MotivoCancelamento);\n    _pedidoRepository.Alterar(pedido);\n\n    return Task.CompletedTask;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Arquivo de Setup<\/strong>&nbsp;Aqui teremos uma configura\u00e7\u00e3o bem parecida com o da API Estoque, somente que vamos fazer a inje\u00e7\u00e3o de depend\u00eancia para o Handler de pedidos e escutar na fila os dois eventos que temos.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">var fila = \"fila_pedido\";\n\nservices.AddRebus(c =&gt; c\n    .Transport(t =&gt; t.UseRabbitMq(Configuration.GetConnectionString(\"RabbitConnection\"), fila)) \/\/Configura o RabbitMQ\n);\n\/\/Injeta as dependencias para o Handler de pedidos\nservices.AutoRegisterHandlersFromAssemblyOf&lt;PedidoEventHandler&gt;();<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">app.ApplicationServices.UseRebus(c =&gt;\n{\n    c.Subscribe&lt;EstoqueFinalizadoEvent&gt;().Wait();\n    c.Subscribe&lt;EstoqueInconsistenteEvent&gt;().Wait();\n});<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Conclus\u00e3o<\/strong>\u00a0<br><br>Tentei mostrar o quanto pode ser simples configurar uma escuta e escrita de fila usando APIs, mas n\u00e3o se enganem quanto a complexidade de uma arquitetura baseada em Microsservi\u00e7os. E como diria o\u00a0<a href=\"https:\/\/www.elemarjr.com\/pt\/\" target=\"_blank\" rel=\"noreferrer noopener\">Elemar Junior<\/a>, \u201ccomplexidade \u00e9 custo\u201d. O REBUS \u00e9 bem eficiente, com ele podemos criar SAGAs, gravar as etapas em um banco de dados f\u00edsico ou em mem\u00f3ria (Redis), configurar logs e muito mais. Aqui vera a documenta\u00e7\u00e3o do projeto que e bem interessante. Lembrando que todo o projeto esta em meu\u00a0<a href=\"https:\/\/github.com\/danilodumba\/microservices-rebus\" target=\"_blank\" rel=\"noreferrer noopener\">Git Hub<\/a>\u00a0e se trata somente de uma POC, n\u00e3o levando em conta padr\u00f5es de projetos ou qualquer outra arquitetura. Qualquer duvida n\u00e3o hesite em me mandar um e-mail, terei o prazer em conversar sobre esse artigo ou qualquer outra tecnologia.\u00a0<a href=\"mailto:dsdumba@gmail.com\">dsdumba@gmail.com<\/a>. Obrigado pela leitura e tamo junto!! [\/av_textblock]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>O que \u00e9 REBUS?&nbsp;Segundo o Git Hub do REBUS, \u00e9 uma \u201cimplementa\u00e7\u00e3o de um barramento de servi\u00e7o enxuto\u201d, ou seja, faz toda a comunica\u00e7\u00e3o com sua fila de mensageria (RabbitMQ, MSMQ, Azure Service Bus, etc.). Ele faz toda a parte de envio e escuta de sua fila de mensageria.&nbsp;O projeto.&nbsp;Foi criado uma POC com uma [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":26,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,7],"tags":[5,4,8,10,9],"class_list":["post-24","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-microsservicos","tag-net","tag-c","tag-mensageria","tag-rabbitmq","tag-rebus"],"_links":{"self":[{"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/posts\/24","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/comments?post=24"}],"version-history":[{"count":1,"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/posts\/24\/revisions"}],"predecessor-version":[{"id":25,"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/posts\/24\/revisions\/25"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/media\/26"}],"wp:attachment":[{"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/media?parent=24"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/categories?post=24"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dumba.dev.br\/index.php\/wp-json\/wp\/v2\/tags?post=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}