{"id":18537298,"url":"https://github.com/helpwave/services","last_synced_at":"2025-04-09T17:36:57.660Z","repository":{"id":65559509,"uuid":"578554538","full_name":"helpwave/services","owner":"helpwave","description":"helpwave's microservices","archived":false,"fork":false,"pushed_at":"2024-10-29T08:10:25.000Z","size":6631,"stargazers_count":13,"open_issues_count":56,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-29T09:26:39.034Z","etag":null,"topics":["dapr","docker","dockerfile","domain-driven-design","event-driven","event-sourcing","go","golang","hacktoberfest","healthcare","microservice","service"],"latest_commit_sha":null,"homepage":"https://staging.api.helpwave.de/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/helpwave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-15T10:33:22.000Z","updated_at":"2024-10-28T16:11:32.000Z","dependencies_parsed_at":"2024-03-17T21:45:08.076Z","dependency_job_id":"97b73be6-47fc-4543-aeb5-4ce5af41a098","html_url":"https://github.com/helpwave/services","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/helpwave%2Fservices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helpwave%2Fservices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helpwave%2Fservices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helpwave%2Fservices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/helpwave","download_url":"https://codeload.github.com/helpwave/services/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248078267,"owners_count":21044080,"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":["dapr","docker","dockerfile","domain-driven-design","event-driven","event-sourcing","go","golang","hacktoberfest","healthcare","microservice","service"],"created_at":"2024-11-06T19:37:45.522Z","updated_at":"2025-04-09T17:36:57.648Z","avatar_url":"https://github.com/helpwave.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# services\n\nhelpwave's microservices\n\n## Getting started\n\n\u003e [!NOTE]\n\u003e Make sure you have [Git](https://git-scm.com/), [Docker](https://docs.docker.com/) and [Docker Compose](https://docs.docker.com/compose/)\n\u003e installed on your system.\n\n\u003e [!NOTE]\n\u003e There seem to be service-discovery issues on Windows Hosts.\n\n### Using Docker Compose next to your IDE\n\nUsing this setup, you use your editor of choice on your system and start the docker compose stack next to it.\nThe main downside to this is that your IDE will use your local toolchain and dependencies, which may not be in sync.\n\n\u003e [!TIP]\n\u003e `./up.sh -d` starts the compose stack in the background\n\n1. Clone the repo locally\n\t```bash\n\t$ git clone git@github.com:helpwave/services.git\n\t```\n2. Start the docker compose stack using the `$ ./up.sh` script\n3. Start your IDE of choice and start hacking!\n4. You can use the tools installed in the dev docker container by opening a shell on it:\n   ```bash\n   $ ./dev.sh\n   # you are now in the container\n   $ psql -d user-svc\n   ```\n\nNext Steps: [Read on here](#development)\n\n### Using Development Containers\n\nYou can start your IDE and Docker Compose together using Dev Containers.\nThis will install a backend client for your IDE in the `devcontainer` container, which it uses instead of your local setup.\n\n\u003e [!IMPORTANT]\n\u003e [Development Containers](https://containers.dev/) is still relatively new technology.\n\u003e Things are likely to change and/or break.\n\n\u003e [!WARNING]\n\u003e Even though containers are a somewhat isolated environment,\n\u003e the devcontainer has access to the host's docker socket.\n\u003e This means malicious code can still mess with your system.\n\u003e Just like on your host system (assuming your user is in the docker group), everything could run as root, if it tried hard enough.\n\u003e For example by spawning a new container, which mounts `/` and runs `rf -rf /`.\n\u003e You can disable docker-out-of-docker by setting `DOCKER_SOCK` in `dev`'s `.env` to `/dev/null`.\n\n#### Development Containers and IntelliJ ([GoLand](https://www.jetbrains.com/de-de/go/))\n\n[Relevant Docs](https://www.jetbrains.com/help/go/connect-to-devcontainer.html#start_container_from_product)\n\n1. Start GoLand and close any open projects.\n2. Alternatively, start [JetBrains Gateway](https://www.jetbrains.com/remote-development/gateway/).\n3. Make sure your docker setup is correctly configured\n4. Under \"Remote Development\" -\u003e \"Dev Containers\" create a new Dev Container\n5. Copy in `git@github.com:helpwave/services.git` and select your branch of choice.\n6. Alternatively, click on \"From Local Project\" and navigate to a local copy of the repo's `.devcontainer/devcontainer.json`\n7. Wait, follow further instructions, and select the editor you want to launch (likely GoLand)\n8. GoLand will start *in* a docker container, you can start hacking!\n9. Use the usual GoLand UI to open a terminal, where you will find a bunch of tools pre-installed for you.\n10. Next time, you can find the Dev Container ready to start.\n\nNext Steps: [Read on here](#development)\n\n#### Development Containers and VSCode\n\n1. Clone the Repo and open it in VSCode\n2. On the lower left, click on the remote development icon\n3. Select \"Reopen in Container\"\n4. VSCode will restart *in* a docker container, you can start hacking!\n5. Use the VSCode UI to open a terminal, where you will find a bunch of tools pre-installed for you.\n6. Closing VSCode will *not* stop the docker compose stack. You can do that manually, close VSCode and navigate to `dev`, there, run `docker compose down`.\n\n## Development\n\nFollowing the steps above, you should now have a docker compose stack running and are able to execute commands in the `dev-devcontainer-1` container.\n\nTo see what compose actually starts, we recommend a look into the [docker-compose.yaml](https://github.com/helpwave/services/blob/main/dev/docker-compose.yaml), but here is the gist:\n\n* Dependencies (e.g., Redis, Postgres and EventStore)\n* `apisix`\n* `services`\n* `devcontainer`\n\nOf particular interest are the `services` and `devcontainer` containers. The former starts all go services using [air](https://github.com/air-verse/air), a tool that automatically recompiles and restarts the service on reload.\nThe latter gives you a playground for development with all the tools you need. As it is in the docker network you can use the names of the other (docker compose) services as hostnames (i.e., `postgres` will be resolved to the container in which the postgres instance is running on).\n**It also has access to docker.** This means you can, for example, read the services logs like this: `docker compose logs services -f`, and start / stop / restart containers.\n\nA lot of ports will be allocated on your host system for additional debugging. Have a look at the [table below](#ports) for more information.\n\n### Networking\n\nThe microservices are tied together using [dapr](https://dapr.io/). Most services provide a grpc API, as defined by the Protobufs in `/proto`.\n[Here](https://buf.build/helpwave/services) you can find the proto's documentation.\n\nWe provide one unified entrypoint for clients in form of the API-gateway [APISIX](https://apisix.apache.org/). It exposes a [grpc-web](https://github.com/grpc/grpc-web) api for http-only clients (i.e., web), but falls back to a grpc proxy for those clients that support it (i.e., mobile).\n\n#### How do I talk to a service?\n\n##### Using helpwave/web\n\nThe frontend is a great way to test regressions. Hop over to [the web repo](https://github.com/helpwave/web) to find out how to set it up and point it to APISIX (HTTP).\n\n##### Using APISIX over grpc-web\n\nUsing this approach, you are closest to the actual calls made by the frontends. \n\nTODO: We are still looking for a tool that works well for this :/\n\n##### Directly\n\n\u003chttps://github.com/fullstorydev/grpcurl\u003e\n\n```bash\ngrpcurl --plaintext \\\n\t-H \"Authorization: Bearer \u003c...\u003e\" \\\n\t-d '{}' \\\n\tlocalhost:3004 \\\n\tservices.tasks_svc.v1.WardService/GetWards\n```\n\n## Ports\n\n| Service       | Port  | Protocol                |\n|---------------|-------|-------------------------|\n| user-svc      | 3002  | gRPC                    |\n| tasks-svc     | 3004  | gRPC                    |\n| property-svc  | 3005  | gRPC                    |\n| updates-svc   | 3006  | gRPC                    |\n| APISIX (dapr) | 3500  | http                    |\n| APISIX (dapr) | 35001 | grpc                    |\n| APISIX        | 9080  | http  (mostly grcp-web) |\n| APISIX        | 9433  | https (mostly grcp-web) |\n| APISIX        | 9090  | http  (control api)     |\n| APISIX        | 9091  | http  (prometheus)      |\n| postgres      | 5432  |                         |\n| redis         | 6379  |                         |\n| eventstore    | 2113  |                         |\n| jaeger (UI)   | 16686 | http                    |\n| jaeger (OTLP) | 4317  | grpc                    |\n| SpiceDB       | 50051 | grpc                    |\n\n### Scripts\n\nThese scripts can be run on your local machine:\n\n* `shell.sh` - Opens a Shell in the devcontainer\n* `up.sh` - Starts the docker compose stack, accepts `docker compose up` arguments. Your IDE might do this for you!\n* `down.sh` - Shuts down the docker compose stack, accepts `docker compose down` arguments\n\nThese scripts can be run in the devcontainer:\n\n* `protos.sh`: Lint and Generate protos\n* `migrate.sh`: [migrate.sh](#migratesh---running-migratemigrate-inside-docker)\n* `models.sh`: [models.sh](#modelssh---generate-models-from-sql-queries)\n* `lint.sh`: Lint go code\n* `tidy.sh`: Runs `go mod tidy` across the workspace. Recommended to run after modifying any dependencies.\n\nExample:\n\n```bash\n$ ./shell.sh protos.sh\n\n# or\n$ ./shell.sh\n$ ./proto.sh\n```\n\nFrom the shell, you can use go commands, like `go test ./...` in a service's directory.\nGo tests are used both for unit tests and more complex (and time-consuming) integration tests simulating a user story.\nThese spin up fresh containers for external dependencies, like EventStore, using [testcontainers](https://github.com/testcontainers/testcontainers-go).\nIt makes use of the same docker socket mounted to the development environment.\n\n## Fake token\n\nWhen working with services that use auth, instead of dealing with JWTs, you can make use of fake tokens.\nA fake token is only the claims part of a JWT, which are defined [here](libs/common/auth.go#L37).\nYou can create your own by simply base64-encoding your json claims.\n\nUse the environment variable `INSECURE_FAKE_TOKEN_ENABLE=true` for a service to accept fake-tokens.\nOnly do this in development environments!\n\nFake tokens are used just like JWTs: As bearer tokens in the Authorization header of your gRPC requests.\n\nHere is an example fake-token that can be used as the bearer authorization token.\n```text\neyJzdWIiOiIxODE1OTcxMy01ZDRlLTRhZDUtOTRhZC1mYmI2YmIxNDc5ODQiLCJlbWFpbCI6Im1heC5tdXN0ZXJtYW5uQGhlbHB3YXZlLmRlIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsIm5hbWUiOiJNYXggTXVzdGVybWFubiIsInByZWZlcnJlZF91c2VybmFtZSI6Im1heC5tdXN0ZXJtYW5uIiwiZ2l2ZW5fbmFtZSI6Ik1heCIsImZhbWlseV9uYW1lIjoiTXVzdGVybWFubiIsIm9yZ2FuaXphdGlvbiI6eyJpZCI6IjNiMjVjNmY1LTQ3MDUtNDA3NC05ZmM2LWE1MGMyOGViYTQwNiIsIm5hbWUiOiJoZWxwd2F2ZSB0ZXN0In19\n---\n# decoded\n{\n  \"sub\": \"18159713-5d4e-4ad5-94ad-fbb6bb147984\",\n  \"email\": \"max.mustermann@helpwave.de\",\n  \"email_verified\": true,\n  \"name\": \"Max Mustermann\",\n  \"preferred_username\": \"max.mustermann\",\n  \"given_name\": \"Max\",\n  \"family_name\": \"Mustermann\",\n  \"organization\": {\n    \"id\": \"3b25c6f5-4705-4074-9fc6-a50c28eba406\",\n    \"name\": \"helpwave test\"\n  }\n}\n````\n\n## Docker images\n\nYou can build a docker image for a service using `make`:\n\n```bash\nmake \u003cservicename\u003e\n```\n\n e.g.:\n\n```bash\n make user-svc\n```\n\nEach service should have a Makefile, that includes the root's Makefile.\nIn the context of a service directory you should be able to use\n\n```bash\n make this\n```\n\nto build the corresponding docker image as well.\n\n### Docker Images\n\n#### dev-go\n\nThe dev-go image is a common development environment for go services. It includes go and a whole lot of tools and dependencies.\nWhen updating the Dockerfile, also increase the `DEV_TAG` variable in the `up.sh` file.\n\n#### dev-go-custom\n\nFor this image we only provide a Dockerfile, you can not pull it from the registry.\nIt is built by docker-compose using your uid and gid as build arguments to reduce friction when it comes to mounted files.\n\nThe other function of this image is to allow customization of the dev container.\nFeel free to install custom tooling (e.g. zsh, nano, ...) there.\nPlease mind the instructions at the top of the Dockerfile though.\nIf you think a tool might be useful to others, install it in the dev-go image instead.\n\n#### Dockerfile.apisix\n\nThis image includes our APISX configuration and the daprd process. As in `Dockerfile.standalone`,\nthese two processes are running side by side in the container via [hivemind](https://github.com/DarthSim/hivemind). \n\n#### Dockerfile.service\n\nThis image contains \"just\" the service. The Dapr sidecar needs to be deployed separately.\n\n#### Dockerfile.standalone\n\nThis image contains the service including the daprd sidecar. These two processes are running\nside by side in the container via [hivemind](https://github.com/DarthSim/hivemind).\n\n## Migrations\n\nWe use [migrate](https://github.com/golang-migrate/migrate) to handle changes to our database tables\nIt uses change versioning, e.g.\n\n* `000009_some_name.up.sql` contains all changes from version 8 to 9\n* `000009_some_name.down.sql` contains all changes from version 9 to 8 in reverse order from\n\n```bash\nmigrate -path services/\u003cservice\u003e/migrations/ -database postgres://postgres:postgres@localhost:5432/\u003cservice\u003e?sslmode=disable up [version]\nmigrate -path services/\u003cservice\u003e/migrations/ -database postgres://postgres:postgres@localhost:5432/\u003cservice\u003e?sslmode=disable down [version]\n```\n\n### `migrate.sh` - Running migrate/migrate inside docker\n\n_Recommended_\n\nIf you don't want to install migrate/migrate directly on your machine, you can use our `migrate.sh` script.\nThis script automatically discovers the migration folder and env file and passes them alongside\nyou arguments into migrate/migrate running in a container.\n\n`migrate.sh` will use the database setup of the passed service. Therefore, a .env file is required.\n\n#### Usage\n\n`./migrate.sh \u003cservice\u003e [... arguments for migrate/migrate]`\n\n* `\u003cservice\u003e` must be one of the services inside `/services/`\n* `[... arguments for migrate/migrate]` gets passed directly to migrate/migrate\n\n\n#### Examples\n\n* Migrate the tasks-svc database all the way up `./migrate.sh tasks-svc up`\n* Migrate the tasks-svc database one down: `./migrate.sh tasks-svc down 1`\n* Current migration version of the tasks-svc database: `./migrate.sh tasks-svc version`\n\n#### desired\n\nAdditionally, the script allows you to query the highest available migration version\nbased on the migration files available in the service:\n\n```bash\n./migrate \u003cservice\u003e desired\n```\n\n### `./models.sh` - Generate models from SQL Queries\n\n\u003e [!IMPORTANT]\n\u003e Requires a running database, it's best to run `devenv up` before running this script.\n\nWe use [sqlc](https://docs.sqlc.dev/en/latest/), a compiler that generates go functions based on SQL queries and a schema.\nThis script\n\n1. Makes sure the database is fully migrated up (see migration.sh)\n2. Generates a `schema.sql` using pg_dump\n3. Invokes sqlc to generate go code based on a `sqlc.yaml`\n\n\u003e [!TIP]\n\u003e The `schema.sql` is also a great place to familiarize yourself with the data model(s)!\n\nUsage:\n\n* `./models.sh \u003csome-svc\u003e` generates models for a specific service\n* `./models.sh models` generates models for all services\n\n## Enviroment variables\n\nEvery service should contain a `.env.example` file which should be copied to a usable `.env` file\n\nDefault Variables:\n\n```bash\n# The mode used, options available\n#  development, production\nMODE=development\n\n# The following levels are available:\n#  trace, debug, info, warn, error, fatal, panic\nLOG_LEVEL=debug\n\n# The port on which the the service will listen on (default: 8080)\nPORT=8080\n\n# The address, where a metrics (prometheus) server will be started on,\n# if missing, no metrics server will be started!\n#   e.g: \"0.0.0.0:2112\", \":8080\"\nMETRICS_ADDR=\n\n# Database related configurations\nPOSTGRES_HOST=localhost\nPOSTGRES_PORT=5432\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=postgres\nPOSTGRES_DB=postgres\n\n# EventStoreDB related configurations\nEVENTSTORE_CS=esdb://admin:changeit@localhost:2113?tls=false\n\n# For development purposes\nINSECURE_FAKE_TOKEN_ENABLE=true\nOAUTH_CLIENT_ID=425f8b8d-c786-4ff7-b2bf-e52f505fb588\n\n# Variables with the prefix \"SECRETSTORE_\" will be catched up by the current env secret store\nSECRETSTORE_REDIS_HOST=localhost\nSECRETSTORE_REDIS_USERNAME=\nSECRETSTORE_REDIS_PASSWORD=\n\n# Telemetry Related Configurations\n\n# skips opentelemetry setup\nOTEL_DISABLE=false\n\n# one of \"zipkin\", otlp\", \"otlp_http\"\n# for additional configuration for each exporter see their documentation:\n# - otlp: https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc@v1.21.0\n# - otlp_http: https://pkg.go.dev/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp@v1.21.0\n# - zipkin: only provides OTEL_EXPORTER_ZIPKIN_ENDPOINT with default \"http://localhost:9411/api/v2/spans\"\nOTEL_TRACE_EXPORTER=otlp\n\n# the language to fallback to for users that\n# don't provide a (valid) language header\n# must be a valid BCP 47 string\nFALLBACK_LANGUAGE=en\n```\n\n## Temporary advises\n\n### Example for service to service communication via Dapr and gRPC\n\n```go\n// ...\n\ndaprClient := common.MustNewDaprGRPCClient()\n\norganizationSvc := user_svc.NewOrganizationServiceClient(daprClient.GrpcClientConn())\nctx, cancel := common.PrepCtxForSvcToSvcCall(ctx, \"user-svc\")\ndefer cancel()\n\nres, err := organizationSvc.CreateOrganizationForUser(ctx, \u0026user_svc.CreateOrganizationForUserRequest{\n\tLongName:     fmt.Sprintf(\"%s personal organization\", payload.Nickname),\n\tShortName:    payload.Nickname,\n\tContactEmail: payload.Email,\n\tIsPersonal:   true,\n\tUserId:       userID.String(),\n})\n\nif err != nil {\n\treturn nil, status.Error(codes.Internal, err.Error())\n}\n```\n\n### Arm versioning\n\n[We disarmed the versioning for pre-production.](https://github.com/helpwave/services/issues/125).\nTo arm the versioning, search for \"arm-versioning\" in the codebase.\n\n## Archived Services\n\n- impulse-svc ([9bbe537](https://github.com/helpwave/services/commit/9bbe53744dc2650bc99b21e0894c1a9bc42f6f12))\n- task-svc ([cf58338](https://github.com/helpwave/services/commit/cf583382e4ac96d4756c7a1100b26a5c8154c477))\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelpwave%2Fservices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhelpwave%2Fservices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelpwave%2Fservices/lists"}