{"id":16539504,"url":"https://github.com/al3rez/beers-srv","last_synced_at":"2026-01-12T00:14:08.352Z","repository":{"id":127306534,"uuid":"215943749","full_name":"al3rez/beers-srv","owner":"al3rez","description":"Enjoy serving 🍻 through micro-services using gRPC","archived":false,"fork":false,"pushed_at":"2023-02-25T02:53:58.000Z","size":58,"stargazers_count":2,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-20T15:55:40.823Z","etag":null,"topics":["ddd","golang","grpc"],"latest_commit_sha":null,"homepage":"","language":"Go","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/al3rez.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-18T04:52:46.000Z","updated_at":"2020-04-29T17:54:59.000Z","dependencies_parsed_at":"2024-01-29T10:32:21.569Z","dependency_job_id":null,"html_url":"https://github.com/al3rez/beers-srv","commit_stats":null,"previous_names":["azbshiri/beers"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/al3rez%2Fbeers-srv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/al3rez%2Fbeers-srv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/al3rez%2Fbeers-srv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/al3rez%2Fbeers-srv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/al3rez","download_url":"https://codeload.github.com/al3rez/beers-srv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219859408,"owners_count":16556036,"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":["ddd","golang","grpc"],"created_at":"2024-10-11T18:49:20.268Z","updated_at":"2025-10-28T14:31:16.785Z","avatar_url":"https://github.com/al3rez.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# beers\nEnjoy serving 🍻 through micro-services using gRPC  \n\u003cbr\u003e\n\u003cbr\u003e\n[![asciicast](https://asciinema.org/a/XXLhQTinGqJdn7F5YR00Rp171.svg)](https://asciinema.org/a/XXLhQTinGqJdn7F5YR00Rp171)\n## Stack\n\n- **CI/CD**: Github Actions (e.g Review, Release automation `goreleaser`, etc)\n- **Testing**: Go `testing` package\n- **Serialization**: Protocol Buffers `protobuf`\n- **OCI orchestration**: Kubernetes, Docker\n\n\n## Architecture\nFollowing DDD principles I've separated bounded contexts and behaviors (e.g. adding, removing, serializing, gRPC) into\nmultiple packages using service objects, database Layer abstraction, repository pattern, command-line interfaces so that\ndecoupling behaviors make both testing and shipping new features easier.\n\n## Installation\nInstalling `beers-srv` is easy, using go get you can install the cmd line app `beers-cli` to interact with gRPC server. First you'll need Google's Protocol Buffers installed.\n```\n$ brew install protobuf\n$ go get -u github.com/azbshiri/beers-srv/...\n```\n\n### Docker\nIf you have Docker already installed then you don't need Go or Protocol Buffers you just need to run below command:\n\n```\n$ docker build -t beers-srv:0.1.0 .\nSending build context to Docker daemon  360.4kB\nStep 1/11 : FROM golang:1.13-alpine as builder\n ---\u003e 4acab7f5278b\nStep 2/11 : COPY . /go/src/github.com/azbshiri/beers\n...\n\n$ docker run -d --rm --name=beers-srv beers-srv:0.1.0\n$ docker exec -i beers-srv grpc-health-probe -addr=:8000\nstatus: SERVING\n\n```\n\n\n## Testing\nI haven't used any external libraries for testing/diffing so if you already have the latest version Go installed,\njust simply run `go test -v ./...` :\n```\nok      github.com/azbshiri/beers-srv/pkg/adding    (cached)\n=== RUN   Test_Add\n=== RUN   Test_Add/adds_beer\n=== RUN   Test_Add/checks_against_blank_name\n=== RUN   Test_Add/fails_due_to_service\n--- PASS: Test_Add (0.00s)\n    --- PASS: Test_Add/adds_beer (0.00s)\n    --- PASS: Test_Add/checks_against_blank_name (0.00s)\n    --- PASS: Test_Add/fails_due_to_service (0.00s)\nPASS\nok \n```\n\n## Kubernetes\nDeploying gRPC applications to K8s and the best way to configure health checks is using `grpc-health-probe` and GRPC Health Checking Protocol\nhttps://kubernetes.io/blog/2018/10/01/health-checking-grpc-servers-on-kubernetes/\n\n```\n$ kubectl apply -f deployment.yml\n$ kubectl get svc beers-srv\nNAME        TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE\nbeers-srv   NodePort   10.110.71.154   \u003cnone\u003e        8000:30768/TCP   15m\n```\n\nexecuting “grpc_health_probe” will call our gRPC server over localhost (Cluster IP):\n\n```\n$ minikube status\nkubectl: Correctly Configured: pointing to minikube-vm at 192.168.122.118\n\n$ grpc-health-probe --addr=192.168.122.118:30768\nstatus: SERVING\n```\n\nkaboom!\n\n\n## Event sourcing\nI'd go with Google Pub/Sub API to keep track of events on the cluster in an event store and https://watermill.io/ API to make it easier to deal with events/subscribers.\n\n- BeerRemoved\n- BeerAdded\n- BeerNameChanged\netc\n\n\n## Cloud nativeness\nUsing Kubernetes and Docker you can easily run the application on cloud with ease scaling up/down, integrate different databases and, etc.\n\n## The Twelve-Factor App\n\n\u003e I. Codebase\nOne codebase tracked in revision control, many deploys\nII. Dependencies\nExplicitly declare and isolate dependencies\n\nUsing Go modules I've isolated dependencies as well as moved out shared code into separate codebase with semantic versioning also since this is a small micro-service I decided to use one branch `master` for deployment and build and adding features using separate branches using PRs.\n\n\u003e III. Config\nStore config in the environment\n\nThere's not much of a configuration in this micro-service, but I've used env variables to set up the minimum.\n\n\u003e IV. Backing services\nTreat backing services as attached resources\n\nThere's no backing services (database, etc) but otherwise still using env vars and service discovery tools one can easily decouple attached services and their communication.\n\n\u003e V. Build, release, run\nStrictly separate build and run stages\n\n`master` is now reliable stage for building and release also using GitHub actions I run linting, testing and building for each PR.\n\n\u003e VI. Processes\nExecute the app as one or more stateless processes\n\nSince I'm using in-memory allocation there's no database involved so this app is not stateless but because\nI've already implemented database abstraction layer and repository pattern it's just so easy to configure databases and other backing services using env vars / service discovery to make this app stateless. (e.g. store removing, adding into separate process pg, etc)\n\n\u003e VII. Port binding\nExport services via port binding\n\nBy setting `PORT` you can easily change port of services (in this case only gRPC server)\n\n\u003e VIII. Concurrency\nScale out via the process model\n\nOCI orchestration is a factor here as you can scale down/up easily on clusters (GCP, AWS) using Docker and K8s.\n\n\u003e IX. Disposability\nMaximize robustness with fast startup and graceful shutdown\n\nUsing K8s and Docker I've implemented gRPC health protocol so K8s can easily restart/replace service instances when needed.\n\n\u003e X. Dev/prod parity\nKeep development, staging, and production as similar as possible\n\nAs I have only one `master` branch and, many feature branches this is also true\n\n\u003e XI. Logs\nTreat logs as event streams\n\nUnfortunately I haven't had time to make this consistent but, I guess in some cases I'm treating logs like streams?!\n\n\u003e XII. Admin processes\nRun admin/management tasks as one-off processes\n\nWhen run using Docker it's simple as running `docker exec` to do admin tasks also when developing using `beers-cli` and `grpc-health-probe` to make sure everything is working fine.\n\n\n## Things that are missed \n\n- [ ] Move protocol buffers generation/linting to Github actions\n- [ ] Fix GoReleaser on Github actions (checkout action doesn't sync tags)\n- [ ] Do dependency injection for logging and make it consistent\n- [ ] More human-friendly errors when dealing with \n- [ ] Add GCP/AWS integration using Terraform\n- [ ] Manage protocol buffers using [buf](https://buf.build/docs/introduction?ref=producthunt) or [gunk](https://github.com/gunk/gunk)\n- [ ] Service discovery using etcd, consul or etc\n- [x] Implement fault-tolerant mechanisms https://github.com/afex/hystrix-go \n- [ ] Move data storage to a stateful service \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fal3rez%2Fbeers-srv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fal3rez%2Fbeers-srv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fal3rez%2Fbeers-srv/lists"}