{"id":20180403,"url":"https://github.com/ppcamp/go-grpc-microservices","last_synced_at":"2025-05-07T03:30:31.017Z","repository":{"id":37864491,"uuid":"480475396","full_name":"ppcamp/go-grpc-microservices","owner":"ppcamp","description":"This repository shows a way of implement microservices in golang using gRPC.","archived":true,"fork":false,"pushed_at":"2022-06-22T15:58:09.000Z","size":264,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-03T05:43:44.786Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/ppcamp.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}},"created_at":"2022-04-11T17:06:36.000Z","updated_at":"2024-05-19T17:47:21.000Z","dependencies_parsed_at":"2022-08-18T04:51:01.897Z","dependency_job_id":null,"html_url":"https://github.com/ppcamp/go-grpc-microservices","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppcamp%2Fgo-grpc-microservices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppcamp%2Fgo-grpc-microservices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppcamp%2Fgo-grpc-microservices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppcamp%2Fgo-grpc-microservices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ppcamp","download_url":"https://codeload.github.com/ppcamp/go-grpc-microservices/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252806321,"owners_count":21807188,"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":[],"created_at":"2024-11-14T02:30:40.496Z","updated_at":"2025-05-07T03:30:30.648Z","avatar_url":"https://github.com/ppcamp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-grpc-microservice-stream\r\n\r\nmicroservices needed:\r\n[go-user-crud](https://github.com/ppcamp/go-user-crud),\r\n[go-authentication](https://github.com/ppcamp/go-authentication)\r\n\r\n## Todo\r\n\r\nERROR: [transport] transport: http2Server.operateHeaders parsed a :connection header which makes a request malformed as per the HTTP/2 spec\r\nThere's a lack of documentation for this. https://kennethjenkins.net/posts/go-nginx-grpc/.\r\nTherefore, I choosed envoy\r\n\r\n\r\nhttps://stackoverflow.com/questions/10175812/how-to-generate-a-self-signed-ssl-certificate-using-openssl\r\n\r\n### Needed\r\n\r\n- [ ] Fix workflows\r\n- [ ] Improve general doc\r\n- [ ] Improve user doc\r\n- [ ] Test workflow (using general approach)\r\n\r\n### Improvements\r\n\r\n- [ ] Add two factor for user, generating QR code\r\n- [ ] Add tests\r\n- [ ] Add [validations] to each use case\r\n- [ ] Allow to run query without use transactions\r\n- [ ] Add error status codes and return BaseResponseObject (treat on handler)\r\n- [ ] Add a way to rollback microservices\r\n- [ ] Start article and create a new tag to the final Part 1\r\n- [ ] Add logging middleware with RequestId (sent by orchstrator)\r\n\r\n\r\n## Directory plan\r\n\r\n- Phase #1: Simplest microservice\r\n  This microservice will not handle with tech errors, it'll be syncronous and\r\n  will not have any compensation procedure to handle with business failures\r\n\r\n- Phase #2: Use a Saga orchistration pattern\r\n  By now, the microservices will not communicate between them, instead, it'll\r\n  exist a single service that will be responsible to orchistrate the business\r\n  flow. With this approach, the microservices will not impact in the others\r\n  directly, and you'll have a centrilized point of error. You need to implement\r\n  a compensation for business errors too.\r\n\r\n- Phase #3: Transform the compensations into events approach\r\n  With this improvement, we'll be able to retry on rollbacks that failed due to\r\n  tech errors and we still keep the syncronous creation, therefore, we'll be\r\n  long pooling (or using websocket) with client.\r\n\r\n\r\n## How to execute?\r\n\r\nFirst of all, create the images of each module by typing:\r\n\r\n```bash\r\n# generate the local image. To see other options, type `make help`\r\nmake docker\r\n```\r\n\r\nIf the images generated, then you type\r\n\r\n```bash\r\ndocker-compose up -d\r\n```\r\n\r\nAfter that you can test the applications with\r\n[Bloom gRPC client](https://github.com/bloomrpc/bloomrpc/releases/tag/1.5.3)\r\n\r\n\r\n```bash\r\ndocker-compose up -d\r\n```\r\n\r\n## How this microservices works?\r\n\r\n### Ideal scenario\r\n\r\nWith this, you only have to map the external connections with internal services,\r\nit also gives you possibility to change in only one place, i.e, it makes the\r\ncode more decoupled\r\n\r\n\r\n```mermaid\r\ngraph LR;\r\n  w((world)) -- request --\u003e api{{Api Gateway}};\r\n  api -- validate --\u003e a(authentication);\r\n\r\n  a --\u003e if{If} -- valid --\u003e b(authorization);\r\n  b --\u003e iif{If} -- valid --\u003e c(user);\r\n\r\n  if{If} -- not valid, return --\u003e api;\r\n  iif{If} -- not valid, return --\u003e api;\r\n\r\n  c --\u003e s[/Does operation/]\r\n```\r\n\r\n\r\n## Dev\r\n\r\n### How these repositories works internally?\r\n\r\n```mermaid\r\ngraph LR;\r\n  world -- incoming --\u003e cmd;\r\n  cmd -- outcoming --\u003e world;\r\n  cmd -- use --\u003e configs;\r\n  cmd -- may use --\u003e utils;\r\n  cmd -- calls --\u003e controllers;\r\n  controllers -- calls --\u003e services;\r\n  controllers -- may use --\u003e utils;\r\n  services -- may use --\u003e repositories \u0026 utils;\r\n  repositories -- may use --\u003e utils;\r\n```\r\n\r\n- `cmd`: Initialize the applications modules\r\n- `configs`: Holds the data that will be used to setup services, controllers and the application itself\r\n- `controllers`: It holds the delivery layer (HTTP, graphQL, gRPC and go on)\r\n- `repositories`: Keeps all places that store/retrieve data, which means cache; database and others approaches\r\n- `services`: It holds the business logic, it also must implement ways of inject repositories into the use cases\r\n- `utils`: Every method that it's not properly dependent of a business logic\r\n\r\n\r\n#### The ***\"handle middleware mechanism\"***\r\n\r\n\r\nThe `Handler Decorator` is an outcoming layer for the controllers.\r\nWith this approach you can commit/rollback transactions and set status codes and\r\nanother response parameters that you may like.\r\n\r\nIn this application, the handler only does commit/rollback with transactions an\r\nreturn the parsed non-transactions use cases, however, it's such a good approach\r\n'cause, in HTTP Rest client, for example, when using **gin** framework, you can\r\nreturn always a Response base object from your use cases and using them, set\r\nstatus codes, body responses, default headers and go on, working like a pseudo\r\nmiddleware.\r\n\r\n\r\n```mermaid\r\ngraph LR;\r\n  cmd -- calls --\u003e controllers;\r\n\r\n  controllers -- calls --\u003e h[Handler decorator];\r\n  h -- that manage the requests/connection to --\u003e services;\r\n\r\n  services -. import base from .-\u003e Handler;\r\n\r\n  controllers -- inject Handler/deps into --\u003e services;\r\n  cmd -. inject .-\u003e Handler -. into .-\u003e controllers;\r\n```\r\n\r\n\r\nThe `services/base` is the base objects that makes the controller decorator work\r\nand it must be inherited by every service.\r\n\r\nThe `controllers/base` is the proper Handler itself, it defines the objects that\r\ncan be injected and take care of the databases transactions\r\n\r\n\r\nThe class diagram of this approach can be seen below:\r\n```mermaid\r\nclassDiagram\r\n\r\nBaseBusiness \u003c-- AnyService : can use\r\nBaseBusiness : Context context.Context\r\nBaseBusiness : SetContext(ctx context.Context)\r\nBaseBusiness : Execute(in In) (response *Out, err error)\r\nBaseBusiness \u003c.. TransactionBusiness : import\r\nTransactionBusiness \u003c-- AnyService : can use\r\nTransactionBusiness : SetTransaction(tr Strg)\r\nTransactionBusiness : BaseBusiness\r\nTransactionBusiness : Transaction Strg\r\nAnyService: BaseBusiness | TransactionBusiness\r\n```\r\n\r\n\r\n\u003c!-- Links --\u003e\r\n\r\n[validations]: https://github.com/go-playground/validator\r\n\r\n\r\nhttps://stackoverflow.com/questions/65897760/how-to-disable-route-timeout-in-envoy\r\nhttps://github.com/improbable-eng/grpc-web\r\nhttps://github.com/kubernetes/ingress-nginx/issues/8086\r\nhttps://www.nginx.com/blog/deploying-nginx-plus-as-an-api-gateway-part-3-publishing-grpc-services/","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppcamp%2Fgo-grpc-microservices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fppcamp%2Fgo-grpc-microservices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppcamp%2Fgo-grpc-microservices/lists"}