{"id":19872279,"url":"https://github.com/rafaelrok/ms-order-pattern-saga-orchestrator","last_synced_at":"2025-08-03T16:32:18.790Z","repository":{"id":200887197,"uuid":"706460954","full_name":"rafaelrok/ms-order-pattern-saga-orchestrator","owner":"rafaelrok","description":"Projeto de microservices no padrão Saga de maneira de gerenciar a consistência de dados entre microservices em cenários de transação distribuída1. Uma saga é uma sequência de transações que atualiza cada serviço e publica uma mensagem ou evento para disparar a próxima etapa de transação utilizando o kafka.","archived":false,"fork":false,"pushed_at":"2024-05-14T11:41:42.000Z","size":6101,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-12T16:14:56.952Z","etag":null,"topics":["api-rest","docker","docker-compose","java","kafka","kafka-consumer","kafka-producer","micro","postgresql","redpanda","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rafaelrok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-10-18T02:07:57.000Z","updated_at":"2024-10-06T15:29:58.000Z","dependencies_parsed_at":"2023-10-22T19:29:20.635Z","dependency_job_id":"ec032e16-0813-4f23-855c-2428f415ed7d","html_url":"https://github.com/rafaelrok/ms-order-pattern-saga-orchestrator","commit_stats":{"total_commits":23,"total_committers":1,"mean_commits":23.0,"dds":0.0,"last_synced_commit":"4795e81c4e0ae9ad0c753df3bf867dd54ab35dc0"},"previous_names":["rafaelrok/ms-order-sales-pattern-saga","rafaelrok/ms-order-pattern-saga-orchestrator"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelrok%2Fms-order-pattern-saga-orchestrator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelrok%2Fms-order-pattern-saga-orchestrator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelrok%2Fms-order-pattern-saga-orchestrator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelrok%2Fms-order-pattern-saga-orchestrator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rafaelrok","download_url":"https://codeload.github.com/rafaelrok/ms-order-pattern-saga-orchestrator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233505859,"owners_count":18686397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-rest","docker","docker-compose","java","kafka","kafka-consumer","kafka-producer","micro","postgresql","redpanda","spring-boot"],"created_at":"2024-11-12T16:15:01.423Z","updated_at":"2025-01-11T16:32:32.805Z","avatar_url":"https://github.com/rafaelrok.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cp align=\"center\"\u003e ms-order-sales-pattern-saga\r\n\u003cp align=\"center\"\u003e\r\n     \u003cimg alt=\"GitHub language count\" src=\"https://img.shields.io/github/commit-activity/t/rafaelrok/ms-order-pattern-saga-orchestrator\r\n\"\u003e\r\n     \u003cimg alt=\"Repository size\" src=\"https://img.shields.io/github/repo-size/rafaelrok/ms-order-pattern-saga-orchestrator\r\n\"\u003e\r\n     \u003ca href=\"https://twitter.com/RafaelV38440615\"\u003e\r\n      \u003cimg alt=\"Siga no Twitter\" src=\"https://img.shields.io/twitter/url?url=https://github.com/rafaelrok/quick-barber/edit/main/README.md\"\u003e\r\n     \u003c/a\u003e  \r\n     \u003ca href=\"https://github.com/quick-barber/README.md/commits/master\"\u003e\r\n      \u003cimg alt=\"GitHub last commit\" src=\"https://img.shields.io/github/last-commit/rafaelrok/ms-order-pattern-saga-orchestrator/main\r\n\"\u003e\r\n     \u003c/a\u003e\r\n     \u003ca href=\"https://github.com/rafaelrok/ms-order-pattern-saga-orchestrator/blob/main/LICENSE\"\u003e\r\n      \u003cimg alt=\"License\" src=\"https://img.shields.io/hexpm/l/apa?logo=apache\"\u003e\r\n     \u003c/a\u003e  \r\n     \u003ca href=\"https://github.com/tgmarinho/README-ecoleta/stargazers\"\u003e\r\n      \u003cimg alt=\"Stargazers\" src=\"https://img.shields.io/github/stars/rafaelrok/ms-order-pattern-saga-orchestrator\r\n\"\u003e\r\n     \u003c/a\u003e\r\n     \u003ca href=\"https://medium.com/@rafael\"\u003e\r\n      \u003cimg alt=\"medium\" src=\"https://img.shields.io/twitter/url?label=Medium\u0026logo=medium\u0026style=social\u0026url=https%3A%2F%2Fmedium.com%2F%40rafael.\"\u003e\r\n     \u003c/a\u003e\r\n  \u003c/p\u003e\r\n\r\n---\r\n\r\n![Arquitetura](resources/Design%20Pattern%20Saga.gif)\r\n\r\n\u003eO projeto é um sistema de microservices desenvolvido em Java com Spring Boot, com objetivo de gerir ordens de serviços e manipulação de estoque de forma distribuída. Uma abordagem central nesse projeto é a aplicação do ‘design’ pattern Saga e a utilização do Apache Kafka como meio de comunicação entre os microservices.\r\n\r\n\u003e**Arquitetura de Microservices:** O sistema é composto por vários microservices que desempenham funções específicas, como a criação de ordens de serviço, o processamento de pagamentos, a atualização do estoque e assim por diante. Cada microservice é responsável por uma parte do processo, permitindo escalabilidade e flexibilidade.\r\n\r\n\u003e**‘Design’ Pattern Saga:** O padrão Saga é aplicado para garantir a consistência e atomicidade das transações distribuídas. Quando uma ordem de serviço é criada, por exemplo, uma sequência de etapas é acionada, e em caso de erro em qualquer uma dessas etapas, é possível reverter ou compensar as ações já realizadas, mantendo o sistema num estado consistente.\r\n\r\n\u003e**Kafka como Middleware:** O Apache Kafka é utilizado como um middleware de mensagens para facilitar a comunicação assíncrona entre os microservices. Ele permite que os eventos sejam publicados e consumidos de forma confiável, garantindo que as mensagens sejam entregues aos consumidores, mesmo em cenários de alta carga.\r\n\r\n\u003e**Fluxo de Operações Típico:** Quando um cliente cria uma ordem de serviço, o microservice correspondente publica um evento no Kafka informando essa ação. Outros microservices, como o de pagamento e o de gestão de estoque, assinam esses eventos e realizam as suas operações específicas. Se algo der errado em qualquer etapa, o padrão Saga é acionado para garantir a consistência dos dados.\r\n\r\n\u003e**Benefícios do Projeto:** Esse projeto de microservices oferece escalabilidade, resiliência e flexibilidade, uma vez que os serviços podem ser dimensionados individualmente. Além disso, o uso do ‘design’ pattern Saga garante a consistência em ambientes distribuídos, e o Kafka facilita a comunicação entre os microservices de maneira eficaz.\r\n\r\nEm resumo, representa uma implementação robusta e altamente técnica de um sistema de microservices para gestão de ordens de serviço e estoque, aplicando o ‘design’ pattern Saga e utilizando o Apache Kafka para comunicação assíncrona entre os serviços. Esse projeto é uma demonstração de boas práticas no desenvolvimento de sistemas distribuídos com Java e Spring Boot.\r\n\r\n### Sumário:\r\n\r\n* [Tecnologias](#tecnologias)\r\n* [Ferramentas utilizadas](#ferramentas-utilizadas)\r\n* [Arquitetura Proposta](#arquitetura-proposta)\r\n* [Execução do projeto](#execu%C3%A7%C3%A3o-do-projeto)\r\n    * [01 - Execução geral via docker-compose](#01---execu%C3%A7%C3%A3o-geral-via-docker-compose)\r\n    * [02 - Execução geral via automação com script em Python](#02---execu%C3%A7%C3%A3o-geral-via-automa%C3%A7%C3%A3o-com-script-em-python)\r\n    * [03 - Executando os serviços de bancos de dados e Message Broker](#03---executando-os-servi%C3%A7os-de-bancos-de-dados-e-message-broker)\r\n    * [04 - Executando manualmente via CLI](#04---executando-manualmente-via-cli)\r\n* [Acessando a aplicação](#acessando-a-aplica%C3%A7%C3%A3o)\r\n* [Acessando tópicos com Redpanda Console](#acessando-t%C3%B3picos-com-redpanda-console)\r\n* [Dados da API](#dados-da-api)\r\n    * [Produtos registrados e seu estoque](#produtos-registrados-e-seu-estoque)\r\n    * [Endpoint para iniciar a saga](#endpoint-para-iniciar-a-saga)\r\n    * [Endpoint para visualizar a saga](#endpoint-para-visualizar-a-saga)\r\n    * [Acesso ao MongoDB](#acesso-ao-mongodb)\r\n\r\n## Tecnologias\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\n* **Java 17**\r\n* **Spring Boot 3**\r\n* **Apache Kafka**\r\n* **API REST**\r\n* **PostgreSQL**\r\n* **MongoDB**\r\n* **Docker**\r\n* **docker-compose**\r\n* **Redpanda Console**\r\n\r\n# Ferramentas utilizadas\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\n* **IntelliJ IDEA**\r\n* **Docker**\r\n* **Gradle**\r\n\r\n# Arquitetura Proposta\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\nNesse projeto desenvolvi a seguinte aquitetura:\r\n\r\n![Arquitetura](resources/Orchestration.png)\r\n\r\nArquitetura contem teremos 5 serviços:\r\n\r\n* **Order-Service**: microsserviço responsável apenas por gerar um pedido inicial, e receber uma notificação. Aqui que teremos endpoints REST para inciar o processo e recuperar os dados dos eventos. O banco de dados utilizado será o MongoDB.\r\n* **Orchestrator-Service**: microsserviço responsável por orquestrar todo o fluxo de execução da Saga, ele que saberá qual microsserviço foi executado e em qual estado, e para qual será o próximo microsserviço a ser enviado, este microsserviço também irá salvar o processo dos eventos. Este serviço não possui banco de dados.\r\n* **Product-Service**: microsserviço responsável por validar se o produto informado no pedido existe e está válido. Este microsserviço guardará a validação de um produto para o ID de um pedido. O banco de dados utilizado será o PostgreSQL.\r\n* **Payment-Service**: microsserviço responsável por realizar um pagamento com base nos valores unitários e quantidades informadas no pedido. Este microsserviço guardará a informação de pagamento de um pedido. O banco de dados utilizado será o PostgreSQL.\r\n* **Inventory-Service**: microsserviço responsável por realizar a baixa do estoque dos produtos de um pedido. Este microsserviço guardará a informação da baixa de um produto para o ID de um pedido. O banco de dados utilizado será o PostgreSQL.\r\n\r\nTodos os serviços da arquitetura irão subir através do arquivo **docker-compose.yml**.\r\n\r\n## Execução do projeto\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\nHá várias maneiras de executar os projetos:\r\n\r\n1. Executando tudo via `docker-compose`\r\n2. Executando tudo via `script` de automação que eu disponibilizei (`build.py`)\r\n3. Executando apenas os serviços de bancos de dados e message broker (Kafka) separadamente\r\n4. Executando as aplicações manualmente via CLI (`java -jar` ou `gradle bootRun` ou via IntelliJ)\r\n\r\nPara rodar as aplicações, será necessário ter instalado:\r\n\r\n* **Docker**\r\n* **Java 17**\r\n* **Gradle 7.6 ou superior**\r\n\r\n### 01 - Execução geral via docker-compose\r\n\r\n[Voltar ao nível anterior](#execu%C3%A7%C3%A3o-do-projeto)\r\n\r\nBasta executar o comando no diretório raiz do repositório:\r\n\r\n`docker-compose up --build -d`\r\n\r\n**Obs.: para rodar tudo desta maneira, é necessário realizar o build das 5 aplicações, veja nos passos abaixo sobre como fazer isto.**\r\n\r\n### 02 - Execução geral via automação com script em Python\r\n\r\n[Voltar ao nível anterior](#execu%C3%A7%C3%A3o-do-projeto)\r\n\r\nBasta executar o arquivo `build.py`. Para isto, **é necessário ter o Python 3 instalado**.\r\n\r\nPara executar, basta apenas executar o seguinte comando no diretório raiz do repositório:\r\n\r\n`python build.py`\r\n\r\nSerá realizado o `build` de todas as aplicações, removidos todos os containers e em sequência, será rodado o `docker-compose`.\r\n\r\n### 03 - Executando os serviços de bancos de dados e Message Broker\r\n\r\n[Voltar ao nível anterior](#execu%C3%A7%C3%A3o-do-projeto)\r\n\r\nPara ser possível executar os serviços de bancos de dados e Message Broker, como MongoDB, PostgreSQL e Apache Kafka, basta ir ao diretório raiz do repositório, onde encontra-se o arquivo `docker-compose.yml` e executar o comando:\r\n\r\n`docker-compose up --build -d order-db kafka product-db payment-db inventory-db`\r\n\r\nComo queremos rodar apenas os serviços de bancos de dados e Message Broker, é necessário informá-los no comando do `docker-compose`, caso contrário, as aplicações irão subir também.\r\n\r\nPara parar todos os containers, basta rodar:\r\n\r\n`docker-compose down`\r\n\r\nOu então:\r\n\r\n`docker stop ($docker ps -aq)`\r\n`docker container prune -f`\r\n\r\n### 04 - Executando manualmente via CLI\r\n\r\n[Voltar ao nível anterior](#execu%C3%A7%C3%A3o-do-projeto)\r\n\r\nAntes da execução do projeto, realize o `build` da aplicação indo no diretório raiz e executando o comando:\r\n\r\n`gradle build -x test`\r\n\r\nPara executar os projetos com Gradle, basta entrar no diretório raiz de cada projeto, e executar o comando:\r\n\r\n`gradle bootRun`\r\n\r\nOu então, entrar no diretório: `build/libs` e executar o comando:\r\n\r\n`java -jar nome_do_jar.jar`\r\n\r\n## Acessando a aplicação\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\nPara acessar as aplicações e realizar um pedido, basta acessar a URL:\r\n\r\nhttp://localhost:3000/swagger-ui.html\r\n\r\nVocê chegará nesta página:\r\n\r\n![Swagger](resources/Documentacao.png)\r\n\r\nAs aplicações executarão nas seguintes portas:\r\n\r\n* Order-Service: 3000\r\n* Orchestrator-Service: 8080\r\n* Product-Service: 8090\r\n* Payment-Service: 8091\r\n* Inventory-Service: 8092\r\n* Apache Kafka: 9092\r\n* Redpanda Console: 8081\r\n* PostgreSQL (Product-DB): 5432\r\n* PostgreSQL (Payment-DB): 5433\r\n* PostgreSQL (Inventory-DB): 5434\r\n* MongoDB (Order-DB): 27017\r\n\r\n## Acessando tópicos com Redpanda Console\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\nPara acessar o Redpanda Console e visualizar tópicos e publicar eventos, basta acessar:\r\n\r\nhttp://localhost:8081\r\n\r\nVocê chegará nesta página:\r\n\r\n![Redpanda](resources/Redpanda%20Kafka.png)\r\n\r\n## Dados da API\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\nÉ necessário conhecer o payload de envio ao fluxo da saga, assim como os produtos cadastrados e as suas quantidades.\r\n\r\n### Produtos registrados e seu estoque\r\n\r\n[Voltar ao nível anterior](#dados-da-api)\r\n\r\nExistem 3 produtos iniciais cadastrados no serviço `product-service` e as suas quantidades disponíveis em `inventory-service`:\r\n\r\n* **COMIC_BOOKS** (4 em estoque)\r\n* **BOOKS** (2 em estoque)\r\n* **MOVIES** (5 em estoque)\r\n* **MUSIC** (9 em estoque)\r\n\r\n### Endpoint para iniciar a saga:\r\n\r\n[Voltar ao nível anterior](#dados-da-api)\r\n\r\n**POST** http://localhost:3000/api/order\r\n\r\nPayload:\r\n\r\n```json\r\n{\r\n  \"products\": [\r\n    {\r\n      \"product\": {\r\n        \"code\": \"COMIC_BOOKS\",\r\n        \"unitValue\": 15.50\r\n      },\r\n      \"quantity\": 3\r\n    },\r\n    {\r\n      \"product\": {\r\n        \"code\": \"BOOKS\",\r\n        \"unitValue\": 9.90\r\n      },\r\n      \"quantity\": 1\r\n    }\r\n  ]\r\n}\r\n```\r\n\r\nResposta:\r\n\r\n```json\r\n{\r\n  \"id\": \"64429e987a8b646915b3735f\",\r\n  \"products\": [\r\n    {\r\n      \"product\": {\r\n        \"code\": \"COMIC_BOOKS\",\r\n        \"unitValue\": 15.5\r\n      },\r\n      \"quantity\": 3\r\n    },\r\n    {\r\n      \"product\": {\r\n        \"code\": \"BOOKS\",\r\n        \"unitValue\": 9.9\r\n      },\r\n      \"quantity\": 1\r\n    }\r\n  ],\r\n  \"createdAt\": \"2023-04-21T14:32:56.335943085\",\r\n  \"transactionId\": \"1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519\"\r\n}\r\n```\r\n\r\n### Endpoint para visualizar a saga:\r\n\r\n[Voltar ao nível anterior](#dados-da-api)\r\n\r\nÉ possível recuperar os dados da saga pelo **orderId** ou pelo **transactionId**, o resultado será o mesmo:\r\n\r\n**GET** http://localhost:3000/api/event?orderId=64429e987a8b646915b3735f\r\n\r\n**GET** http://localhost:3000/api/event?transactionId=1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519\r\n\r\nResposta:\r\n\r\n```json\r\n{\r\n  \"id\": \"64429e9a7a8b646915b37360\",\r\n  \"transactionId\": \"1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519\",\r\n  \"orderId\": \"64429e987a8b646915b3735f\",\r\n  \"payload\": {\r\n    \"id\": \"64429e987a8b646915b3735f\",\r\n    \"products\": [\r\n      {\r\n        \"product\": {\r\n          \"code\": \"COMIC_BOOKS\",\r\n          \"unitValue\": 15.5\r\n        },\r\n        \"quantity\": 3\r\n      },\r\n      {\r\n        \"product\": {\r\n          \"code\": \"BOOKS\",\r\n          \"unitValue\": 9.9\r\n        },\r\n        \"quantity\": 1\r\n      }\r\n    ],\r\n    \"totalAmount\": 56.40,\r\n    \"totalItems\": 4,\r\n    \"createdAt\": \"2023-04-21T14:32:56.335943085\",\r\n    \"transactionId\": \"1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519\"\r\n  },\r\n  \"source\": \"ORCHESTRATOR\",\r\n  \"status\": \"SUCCESS\",\r\n  \"eventHistory\": [\r\n    {\r\n      \"source\": \"ORCHESTRATOR\",\r\n      \"status\": \"SUCCESS\",\r\n      \"message\": \"Saga started!\",\r\n      \"createdAt\": \"2023-04-21T14:32:56.78770516\"\r\n    },\r\n    {\r\n      \"source\": \"PRODUCT_SERVICE\",\r\n      \"status\": \"SUCCESS\",\r\n      \"message\": \"Products are validated successfully!\",\r\n      \"createdAt\": \"2023-04-21T14:32:57.169378616\"\r\n    },\r\n    {\r\n      \"source\": \"PAYMENT_SERVICE\",\r\n      \"status\": \"SUCCESS\",\r\n      \"message\": \"Payment realized successfully!\",\r\n      \"createdAt\": \"2023-04-21T14:32:57.617624655\"\r\n    },\r\n    {\r\n      \"source\": \"INVENTORY_SERVICE\",\r\n      \"status\": \"SUCCESS\",\r\n      \"message\": \"Inventory updated successfully!\",\r\n      \"createdAt\": \"2023-04-21T14:32:58.139176809\"\r\n    },\r\n    {\r\n      \"source\": \"ORCHESTRATOR\",\r\n      \"status\": \"SUCCESS\",\r\n      \"message\": \"Saga finished successfully!\",\r\n      \"createdAt\": \"2023-04-21T14:32:58.248630293\"\r\n    }\r\n  ],\r\n  \"createdAt\": \"2023-04-21T14:32:58.28\"\r\n}\r\n```\r\n\r\n### Acesso ao MongoDB\r\n\r\n[Voltar ao início](#sum%C3%A1rio)\r\n\r\nPara conectar-se ao MongoDB via linha de comando (cli) diretamente do docker-compose, basta executar o comando abaixo:\r\n\r\n**docker exec -it order-db mongosh \"mongodb://admin:[sua senha]@localhost:27017\"**\r\n\r\nPara listar os bancos de dados existentes:\r\n\r\n**show dbs**\r\n\r\nPara selecionar um banco de dados:\r\n\r\n**use admin**\r\n\r\nPara visualizar as collections do banco:\r\n\r\n**show collections**\r\n\r\nPara realizar queries e validar se os dados existem:\r\n\r\n**db.order.find()**\r\n\r\n**db.event.find()**\r\n\r\n**db.order.find(id=ObjectId(\"65006786d715e21bd38d1634\"))**\r\n\r\n**db.order.find({ \"products.product.code\": \"COMIC_BOOKS\"})**\r\n\r\n---\r\n## Desenvolvedor\r\n\r\n\u003ctable\u003e\r\n  \u003ctr\u003e\r\n    \u003ctd align=\"center\"\u003e\r\n      \u003ca href=\"#\"\u003e\r\n        \u003cimg src=\"https://avatars.githubusercontent.com/u/8467131?v=4\" width=\"100px;\" alt=\"Foto do Rafael Vieira no GitHub\"/\u003e\u003cbr\u003e\r\n        \u003csub\u003e\r\n          \u003cb\u003eRafael Vieira dos Santos\u003c/b\u003e\r\n        \u003c/sub\u003e\r\n      \u003c/a\u003e\r\n    \u003c/td\u003e\r\n  \u003c/tr\u003e\r\n\u003c/table\u003e\r\n\u003ctable\u003e\r\n  \u003ctr\u003e\r\n    \u003ca href=\"https://www.linkedin.com/in/rafaelvieira-s/\"\u003e\r\n      \u003cimg alt=\"linkedin\" src=\"https://img.shields.io/twitter/url?label=Linkedin\u0026logo=linkedin\u0026style=social\u0026url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Frafaelvieira-s%2F\"\u003e\r\n    \u003c/a\u003e\r\n    \u003ca href=\"https://medium.com/@rafael\"\u003e\r\n      \u003cimg alt=\"medium\" src=\"https://img.shields.io/twitter/url?label=Medium\u0026logo=medium\u0026style=social\u0026url=https%3A%2F%2Fmedium.com%2F%40rafael.\"\u003e\r\n    \u003c/a\u003e\r\n    \u003ca href = \"mailto:rafaelrok25@gmail.com\"\u003e\r\n      \u003cimg alt=\"gmail\" src=\"https://img.shields.io/twitter/url?label=gmail\u0026logo=gmail\u0026style=social\u0026url=https%3A%2F%2Fmail.google.com%2F\"\u003e\r\n    \u003c/a\u003e\r\n  \u003c/tr\u003e\r\n\u003c/table\u003e\r\n\r\n## 📝 Licença\r\n\r\nEsse projeto está sob licença. Observe o arquivo [LICENÇA](LICENSE.md) para mais detalhes.\r\n\r\n[⬆ Voltar ao topo](#projeto-ms-order-sales-pattern-saga)\u003cbr\u003e\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelrok%2Fms-order-pattern-saga-orchestrator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frafaelrok%2Fms-order-pattern-saga-orchestrator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelrok%2Fms-order-pattern-saga-orchestrator/lists"}