{"id":15648906,"url":"https://github.com/marciojg/microservice-architecture","last_synced_at":"2026-03-10T17:05:22.316Z","repository":{"id":49262064,"uuid":"373878953","full_name":"marciojg/microservice-architecture","owner":"marciojg","description":"Este projeto é um exemplo de uma solução de \"e-commerce\" usando padrões de arquitetura, com 2 principais, que são: SAGA with Choreography e Event Sourcing.","archived":false,"fork":false,"pushed_at":"2025-10-29T05:48:13.000Z","size":493,"stargazers_count":2,"open_issues_count":197,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-29T07:29:18.040Z","etag":null,"topics":["kafka","microservices","my-apps","postgresql","rails","redis-queue","rspec","ruby-on-rails","sagas"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marciojg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"support_service/.gitattributes","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-06-04T15:07:23.000Z","updated_at":"2024-11-25T10:39:44.000Z","dependencies_parsed_at":"2024-01-09T16:02:02.124Z","dependency_job_id":"ce3e973d-e856-4b85-887e-978f7113c0da","html_url":"https://github.com/marciojg/microservice-architecture","commit_stats":{"total_commits":46,"total_committers":1,"mean_commits":46.0,"dds":0.0,"last_synced_commit":"84406957845d2c3afdfffe9a1d9fca59519e5bc7"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/marciojg/microservice-architecture","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marciojg%2Fmicroservice-architecture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marciojg%2Fmicroservice-architecture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marciojg%2Fmicroservice-architecture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marciojg%2Fmicroservice-architecture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marciojg","download_url":"https://codeload.github.com/marciojg/microservice-architecture/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marciojg%2Fmicroservice-architecture/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30343820,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T15:55:29.454Z","status":"ssl_error","status_checked_at":"2026-03-10T15:54:58.440Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["kafka","microservices","my-apps","postgresql","rails","redis-queue","rspec","ruby-on-rails","sagas"],"created_at":"2024-10-03T12:27:01.972Z","updated_at":"2026-03-10T17:05:22.297Z","avatar_url":"https://github.com/marciojg.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Order Service](https://github.com/marciojg/microservice-architecture/actions/workflows/order_service.yml/badge.svg?branch=main\u0026event=push)](https://github.com/marciojg/microservice-architecture/actions/workflows/order_service.yml)\n[![license](https://img.shields.io/github/license/marciojg/microservice-architecture.svg)]()\n\nEste projeto é um exemplo de uma solução de \"e-commerce\" usando padrões de arquitetura, com 2 principais, que são: [SAGA with Choreography](https://microservices.io/patterns/data/saga.html) e [Event Sourcing](https://microservices.io/patterns/data/event-sourcing.html).\n\nEle foi criado visando 4 pilares.\n\n- Resiliência\n\\\nNeste projeto foram usados alguns artifícios para manter a resiliência dos serviços, como:\n\n  - [Circuit Breaker](https://microservices.io/patterns/reliability/circuit-breaker.html):\n    - A comunicação entre os serviços e o kafka. [Producers](./order_service/config/delivery_boy.rb) e [Consumers](./order_service/config/racecar.rb).\n    - A comunicação entre o serviço de frete e a api do [Viacep](./freight_service/app/services/via_cep_service.rb).\n  - Uso do [Redis](https://redis.io/) para guardar cache de informações entre serviços.\n  - [Comunicação assíncrona](https://www.mitrais.com/news-updates/asynchronous-communication-between-microservices-with-apache-kafka/) entre os serviços.\n\n- [Mensageria](https://microservices.io/patterns/data/event-sourcing.html)\n\\\nCom o objetivo de manter a máxima resiliência da solução e o mais alto nível possível de disponibilidade foi usado [Kafka](https://kafka.apache.org/) como um message broker o que permite a comunicação entre os serviços de maneira assíncrona.\n\n- [Gerenciamento de Configuração](https://microservices.io/patterns/externalized-configuration.html)\n\\\nNo nosso cenário não foi possível uma implementação aprofundada por uma limitação na linguagem usada no serviço. De todo modo, foi implementado um exemplo de solução usando [ETCD](https://etcd.io/) como serviço que responde chave/valor e o serviço de produtos [capturando dados](./product_service/config/delivery_boy.rb) de comunicação com o Kafka através de uma chamada ao etcd.\n\n- [Service Discovery](https://microservices.io/patterns/client-side-discovery.html)\n\\\nNo nosso cenário não foi identificado uma necessidade latente de possuirmos uma implementação deste pilar, pois nenhum serviço conversa com outro diretamente. Ou seja, como a comunicação entre os serviços é assíncrona, vimos que este pilar foi \"atendido\" quando ativamos o Kafka.\n\\\n\\\nEntretando, uma maneira de atender a este pilar de maneira elegante seria migrar nosso projeto hoje em [docker-compose](https://docs.docker.com/compose/) para [kubernetes](https://kubernetes.io/pt-br/) que nos entregaria soluções de service disovery muito eficiente e de fácil configuração.\n\n---\n---\n\n# Motivadores\n\n- [PROBLEMA PROPOSTO 1](./PROBLEMA-PROPOSTO-1.md)\n- [PROBLEMA PROPOSTO 2](./PROBLEMA-PROPOSTO-2.md)\n\n---\n---\n\n# Arquitetura do projeto\n\n![Arquitetura do projeto](./architecture-service-tcd-amazon.jpg)\n\n---\n---\n\n# Vídeo do projeto\n[Vídeo completo](https://www.loom.com/share/4c6401db87fb4cd5b7d6a4e727d86e1b)\n\\\n![](https://cdn.loom.com/sessions/thumbnails/6c4451ffae364fafb445c689010ea1f5-with-play.gif)\n\n---\n---\n\n# Link dos serviços\n\n- [KAFDROP](http://localhost:19000)\n- [PRODUCT_SERVICE](http://localhost:1001/api-docs/index.html)\n- [WISHLIST_SERVICE](http://localhost:1002/api-docs/index.html)\n- [CART_SERVICE](http://localhost:1006/api-docs/index.html)\n- [ORDER_SERVICE](http://localhost:1004/api-docs/index.html)\n- [FREIGHT_SERVICE](http://localhost:1005/api-docs/index.html)\n- [SUPPORT_SERVICE](http://localhost:1003/api-docs/index.html)\n\n---\n---\n\n# Passos para execução do projeto\n\n### Subir o projeto\n\n```bash\nchmod +x start.sh\nsh start.sh\n```\n\n---\n### Criar categoria\n\n```bash\ncurl -X POST \"http://localhost:1001/categories\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"category\\\":{\\\"name\\\":\\\"Masculino Adulto\\\"}}\"\n```\n\n---\n### Criar 2 produtos\n\n```bash\ncurl -X POST \"http://localhost:1001/products\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"product\\\":{\\\"name\\\":\\\"Camisa Azul\\\",\\\"value\\\":16.097,\\\"category_id\\\":1}}\"\n```\n\n```bash\ncurl -X POST \"http://localhost:1001/products\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"product\\\":{\\\"name\\\":\\\"Camisa Vermelha\\\",\\\"value\\\":11.30,\\\"category_id\\\":1}}\"\n```\n\n---\n### Conferir produto postado no tópico do Kafka para montar um cache de itens no `wishlist_service` e `cart_service`\n\\\n[PRODUCTS_CHANNEL](http://localhost:19000/topic/PRODUCTS_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Visualizar os produtos de um determinado gênero\n\n```bash\ncurl -X GET \"http://localhost:1001/categories/1/products?popular=false\" -H  \"accept: application/json\"\n```\n\n---\n### Visualizar os detalhes de cada produto\n\n```bash\ncurl -X GET \"http://localhost:1001/products/1\" -H  \"accept: application/json\"\n```\n\n```bash\ncurl -X GET \"http://localhost:1001/products/2\" -H  \"accept: application/json\"\n```\n\n---\n### Buscar um produto por palavra-chave\n\n```bash\ncurl -X GET \"http://localhost:1001/products?popular=false\u0026q%5Bname_cont%5D=azul\" -H  \"accept: application/json\"\n```\n\n---\n### Marcar um item como mais visto\n\n```bash\ncurl -X GET \"http://localhost:1001/products/1\" -H  \"accept: application/json\"\n```\n\n---\n### Exibir os produtos mais vistos por categorias\n\n```bash\ncurl -X GET \"http://localhost:1001/categories/1/products?popular=true\" -H  \"accept: application/json\"\n```\n\n---\n### Conferir chaves criadas no Configuration Manager [ETCD](https://etcd.io/)\n\n```bash\ndocker-compose -f docker-compose-etcd.yml exec etcd /bin/sh -c \"etcdctl --endpoints http://etcd:2379 get development/product_service --prefix\"\n```\n\n---\n### Criar uma lista de desejo vazia\n\n```bash\ncurl -X POST \"http://localhost:1002/wishlists\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"wishlist\\\":{\\\"client_id\\\":100}}\"\n```\n\n---\n### Adicionar itens na sua lista de desejo\n\n```bash\ncurl -X POST \"http://localhost:1002/wishlists/1/items\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"item\\\":{\\\"product_id\\\":1}}\"\n```\n\n---\n### Tentar adicionar um item na lista de desejo com produto inválido\n\n```bash\ncurl -X POST \"http://localhost:1002/wishlists/1/items\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"item\\\":{\\\"product_id\\\":999}}\"\n```\n\n---\n### Conferir item da lista de desejo postado no tópico do Kafka para montar um cache de itens no `cart_service`\n\\\n[WISHLIST_ITEMS_CHANNEL](http://localhost:19000/topic/WISHLIST_ITEMS_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Adicionar um item no carrinho\n\n```bash\ncurl -X POST \"http://localhost:1006/carts/100/items\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"item\\\":{\\\"product_id\\\":2,\\\"amount\\\":3}}\"\n```\n\n---\n### Tentar adicionar um item no carrinho com produto inválido\n\n```bash\ncurl -X POST \"http://localhost:1006/carts/100/items\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"item\\\":{\\\"product_id\\\":99,\\\"amount\\\":3}}\"\n```\n\n---\n### Mover um item da lista de desejo para o carrinho\n\n```bash\ncurl -X POST \"http://localhost:1006/carts/100/items\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"item\\\":{\\\"wishlist_item_id\\\":1,\\\"amount\\\":5}}\"\n```\n\n---\n### Conferir item da lista de desejo postado no tópico do Kafka para ser removido da lista de desejo correspondente\n\\\n[DELETE_WISHLIST_ITEM_CHANNEL](http://localhost:19000/topic/DELETE_WISHLIST_ITEM_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Conferir que o item foi removido da `lista de desejo`\n\n```bash\ncurl -X GET \"http://localhost:1002/wishlists/1/items\" -H  \"accept: application/json\"\n```\n\n---\n### Conferir que o item foi marcado para ser removido na fila do kafka que mantem o cache de itens\n\\\n[WISHLIST_ITEMS_CHANNEL](http://localhost:19000/topic/WISHLIST_ITEMS_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Abrir um pedido\n\n```bash\ncurl -X POST \"http://localhost:1004/orders/open\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"order\\\":{\\\"cart_client_id\\\":100}}\"\n```\n\n---\n### Tentatar criar um pedido com um carrinho/cliente inválido\n\n```bash\ncurl -X POST \"http://localhost:1004/orders/open\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"order\\\":{\\\"cart_client_id\\\":225}}\"\n```\n\n---\n### Conferir pedido postado no tópico do Kafka para montar um cache de pedidos no `support_service`\n\\\n[ORDERS_CHANNEL](http://localhost:19000/topic/ORDERS_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Conferir que o pedido ao ser criado solicita o total de itens no carrinho para o serviço `cart_service`\n\\\n[TOTAL_ITEMS_CHANNEL](http://localhost:19000/topic/TOTAL_ITEMS_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Conferir a resposta do total de itens no carrinho feito pelo serviço `cart_service` para o serviço `order_service`\n\\\n[TOTAL_ITEMS_REPLY_CHANNEL](http://localhost:19000/topic/TOTAL_ITEMS_REPLY_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Verificar o valor total e a quantidade total de itens no pedido, que são calculados com base no que há no carrinho\n\n```bash\ncurl -X GET \"http://localhost:1004/orders/1\" -H  \"accept: application/json\"\n```\n\n---\n### Calcular o frete de uma compra com um CEP válido\n\n```bash\ncurl -X POST \"http://localhost:1004/orders/1/freight\" -H  \"accept: */*\" -H  \"Content-Type: application/json\" -d \"{\\\"freight\\\":{\\\"zip_code\\\":\\\"02512000\\\"}}\"\n```\n\n---\n### Tentar calcular o frete de uma compra com um CEP inválido\n\n```bash\ncurl -X POST \"http://localhost:1004/orders/1/freight\" -H  \"accept: */*\" -H  \"Content-Type: application/json\" -d \"{\\\"freight\\\":{\\\"zip_code\\\":\\\"02599999\\\"}}\"\n```\n\n---\n### Conferir o pedido cálculo de frete postado no tópico do Kafka para o serviço `freight_service`\n\\\n[CALCULATE_FREIGHT_CHANNEL](http://localhost:19000/topic/CALCULATE_FREIGHT_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Conferir o retorno do serviço `freight_service` postado no tópico referente ao pedido de cálculo de frete que será consumido pelo serviço `order_service`\n\\\n[CALCULATE_FREIGHT_REPLY_CHANNEL](http://localhost:19000/topic/CALCULATE_FREIGHT_REPLY_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Acompanhar os dados do seu pedido, com todos os valores calculados\n\n```bash\ncurl -X GET \"http://localhost:1004/orders/1\" -H  \"accept: application/json\"\n```\n\n---\n### Abrir um chamado técnico de algum problema que está acontecendo\n\n```bash\ncurl -X POST \"http://localhost:1003/tickets/open\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"ticket\\\":{\\\"description\\\":\\\"Problema X Y Z\\\",\\\"client_id\\\":100,\\\"order_id\\\":1}}\"\n```\n\n---\n### Encerrar um chamado técnico\n\n```bash\ncurl -X POST \"http://localhost:1003/tickets/closed\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"ticket\\\":{\\\"id\\\":1}}\"\n```\n\n---\n### Encerrar um pedido\n\n```bash\ncurl -X POST \"http://localhost:1004/orders/closed\" -H  \"accept: application/json\" -H  \"Content-Type: application/json\" -d \"{\\\"order\\\":{\\\"id\\\":1}}\"\n```\n\n---\n### Conferir carrinho postado no tópico do Kafka para que seus itens sejam removidos em `cart_service`\n\\\n[CART_ITEMS_REMOVE_CHANNEL](http://localhost:19000/topic/CART_ITEMS_REMOVE_CHANNEL/messages?partition=0\u0026offset=0\u0026count=100\u0026keyFormat=DEFAULT\u0026format=DEFAULT)\n\n---\n### Conferir carrinho vazio\n\n```bash\ncurl -X GET \"http://localhost:1006/carts/100/items\" -H  \"accept: application/json\"\n```\n\n---\n### Derrubar o projeto\n\n```bash\nchmod +x stop.sh\nsh stop.sh\n```\n\n---\n---\n\n# Links Úteis\n\n- https://bitbucket.org/tadeu-barbosa-cbds/fiap-microservices-exercicios/src/master/\n- http://stytex.de/blog/2016/01/18/spring-cloud-sidecar-applications/\n- https://github.com/yammer/circuitbox\n- https://github.com/jnunemaker/resilient\n- https://medium.com/onebyte-llc/distributed-systems-configuration-management-using-apache-zookeeper-2121b231a4a4\n- https://github.com/FlowerWrong/scc_ruby\n- https://github.com/davissp14/etcdv3-ruby\n- https://github.com/conduktor/kafka-stack-docker-compose\n- https://github.com/zendesk/delivery_boy\n- https://github.com/zendesk/ruby-kafka\n- https://github.com/zendesk/racecar\n- https://www.instaclustr.com/support/documentation/kafka/accessing-and-using-kafka/use-kafka-with-ruby\n- https://blog.blueapron.io/developing-with-kafka-and-rails-applications-783799e13489\n- https://medium.com/zendesk-engineering/kafka-on-ruby-fdab12302146\n- https://peaonunes.medium.com/circuitbox-how-to-circuit-breaker-in-ruby-3413fd9789e6\n- https://imasters.com.br/back-end/aprenda-a-aumentar-resiliencia-de-suas-aplicacoes-ruby\n\n## Para futuro\n- http://maratgaliev.com/rails-kafka\n- https://rom-rb.org/learn/\n- https://dry-rb.org/\n- https://github.com/karafka/karafka\n- https://github.com/ryanlecompte/redis_failover\n- http://stytex.de/blog/2016/01/18/spring-cloud-sidecar-applications\n- https://github.com/xetys/microservices-sidecar-example\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarciojg%2Fmicroservice-architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarciojg%2Fmicroservice-architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarciojg%2Fmicroservice-architecture/lists"}