{"id":23095187,"url":"https://github.com/pauluswi/rhine","last_synced_at":"2026-05-07T00:33:39.563Z","repository":{"id":57655599,"uuid":"456297663","full_name":"pauluswi/rhine","owner":"pauluswi","description":"Is a microservice that implements hexagonal architecture approach to handle transaction history creation and retrieval. ","archived":false,"fork":false,"pushed_at":"2022-02-08T01:27:00.000Z","size":3512,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-09T07:35:17.256Z","etag":null,"topics":["fintech","go","golang","hexagonal-architecture","jwt","kafka","microservice","postgresql","redis"],"latest_commit_sha":null,"homepage":"","language":"Go","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/pauluswi.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":null,"security":null,"support":null}},"created_at":"2022-02-06T23:17:43.000Z","updated_at":"2022-02-20T22:48:07.000Z","dependencies_parsed_at":"2022-09-01T00:51:02.107Z","dependency_job_id":null,"html_url":"https://github.com/pauluswi/rhine","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/pauluswi%2Frhine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauluswi%2Frhine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauluswi%2Frhine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pauluswi%2Frhine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pauluswi","download_url":"https://codeload.github.com/pauluswi/rhine/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247063970,"owners_count":20877526,"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":["fintech","go","golang","hexagonal-architecture","jwt","kafka","microservice","postgresql","redis"],"created_at":"2024-12-16T22:19:51.644Z","updated_at":"2026-05-07T00:33:34.542Z","avatar_url":"https://github.com/pauluswi.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rhine\nIs a microservice that implementing hexagonal architecture to handle transaction history creation and retrieval. \n\n[![Go](https://github.com/pauluswi/rhine/actions/workflows/build.yml/badge.svg)](https://github.com/pauluswi/rhine/actions/workflows/build.yml)\n\n## Architecture\n\n![General Architecture](./General.JPG)\n\n## Tech Stack\n\n1. Kafka for message broker\n3. Redis for result caching\n4. Postgres for data persistance\n5. Go Ozzo for HTTP endpoint router\n6. Docker to implement containerization\n\n## Activity Diagram\n\n![Save](./Rhine-Save.JPG)\n\n![Get](./Rhine-Get.JPG)\n\n## Project Layout\n\nrhine uses the following project layout:\n \n```\n.\n├── cmd                  main applications of the project\n│   └── server           the API server application\n├── config               configuration files for different environments\n├── internal             private application and library code\n│   ├── trxhistory       transaction history-related features\n│   ├── auth             authentication feature\n│   ├── config           configuration library\n│   ├── entity           entity definitions and domain logic\n│   ├── errors           error types and handling\n│   ├── healthcheck      healthcheck feature\n│   └── test             helpers for testing purpose\n├── migrations           database migrations\n├── pkg                  public library code\n│   ├── accesslog        access log middleware\n│   ├── graceful         graceful shutdown of HTTP server\n│   ├── log              structured and context-aware logger\n│   └── pagination       paginated list\n└── testdata             test data scripts\n```\n\nThe top level directories `cmd`, `internal`, `pkg` are commonly found in other popular Go projects, as explained in\n[Standard Go Project Layout](https://github.com/golang-standards/project-layout).\n\nWithin `internal` and `pkg`, packages are structured by features in order to achieve the so-called\n[screaming architecture](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html). For example, \nthe `paytoken` directory contains the application logic related with the payment token feature. \n\nWithin each feature package, code are organized in layers (API, service, repository), following the dependency guidelines\nas described in the [clean architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html).\n\n# Getting Started\n\n```shell\n# download the repo\ngit clone https://github.com/pauluswi/rhine.git\n\ncd rhine\n\n# start a PostgreSQL database server in a Docker container\nmake db-start\n\n# seed the database with some test data\nmake testdata\n\n# run the RESTful API server\nmake run\n```\n\nAt this time, you have a RESTful API server running at `http://127.0.0.1:8080`. \nIt provides the following endpoints:\n\n* `GET /healthcheck`: a healthcheck service provided for health checking purpose (needed when implementing a server cluster)\n* `POST /v1/login`: authenticates a user and generates a JWT\n* `POST /v1/save`: store a transaction history into Kafka and then Postgres\n* `GET /v1/get/:id`: retrieve a transaction history from Redis or Postgres\n\nTry the URL `http://localhost:8080/healthcheck` in a browser, and you should see something like `\"OK v1.0.0\"` displayed.\n\nIf you have `cURL` or some API client tools (e.g. [Postman](https://www.getpostman.com/)), you may try the following \nmore complex scenarios:\n\n```shell\n# authenticate the user via: POST /v1/login\ncurl -X POST -H \"Content-Type: application/json\" -d '{\"username\": \"demo\", \"password\": \"pass\"}' http://localhost:8080/v1/login\n# should return a JWT token like: {\"token\":\"...JWT token here...\"}\n\n# with the above JWT token, access the album resources, such as: GET /v1/xxx\n# start example\ncurl -X GET -H \"Authorization: Bearer ...JWT token here...\" http://localhost:8080/v1/xxx\n# end example \n\n# with the above JWT token, hit a endpoint to save a transaction history\ncurl -X POST -H \"Content-Type: application/json\" -d '{\"customer_id\": \"08110001\"}' -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDE0NjQ2OTksImlkIjoiMTAwIiwibmFtZSI6ImRlbW8ifQ.WYS5mX_UGUWu4nf_u-FHBpkLKKSf2YL3xwdBzqooYbU\" http://localhost:8080/v1/save\n\n# with the above JWT token, hit a endpoint to save a transaction history\ncurl -X POST -H \"Content-Type: application/json\" -d '{\"id\": 2, \t\"trx_id\": \"222222\", \"customer_id\": \"08110001\", \"cd\":\"c\", \t\"status\":\"0\", \"amount\":20001}' -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDE0NjQ2OTksImlkIjoiMTAwIiwibmFtZSI6ImRlbW8ifQ.WYS5mX_UGUWu4nf_u-FHBpkLKKSf2YL3xwdBzqooYbU\" http://localhost:8080/v1/save\n\n# with the above JWT token, hit a endpoint to get a transaction history by passing ID parameter\ncurl -X GET -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDE0NjQ2OTksImlkIjoiMTAwIiwibmFtZSI6ImRlbW8ifQ.WYS5mX_UGUWu4nf_u-FHBpkLKKSf2YL3xwdBzqooYbU\" http://localhost:8080/v1/get/1\n\n```\n\n## Updating Database Schema\n\nThe starter kit uses [database migration](https://en.wikipedia.org/wiki/Schema_migration) to manage the changes of the \ndatabase schema over the whole project development phase. The following commands are commonly used with regard to database\nschema changes:\n\n```shell\n# Execute new migrations made by you or other team members.\n# Usually you should run this command each time after you pull new code from the code repo. \nmake migrate\n\n# Create a new database migration.\n# In the generated `migrations/*.up.sql` file, write the SQL statements that implement the schema changes.\n# In the `*.down.sql` file, write the SQL statements that revert the schema changes.\nmake migrate-new\n\n# Revert the last database migration.\n# This is often used when a migration has some issues and needs to be reverted.\nmake migrate-down\n\n# Clean up the database and rerun the migrations from the very beginning.\n# Note that this command will first erase all data and tables in the database, and then\n# run all migrations. \nmake migrate-reset\n```\n\n\n### Managing Configurations\n\nThe application configuration is represented in `internal/config/config.go`. When the application starts,\nit loads the configuration from a configuration file as well as environment variables. The path to the configuration \nfile is specified via the `-config` command line argument which defaults to `./config/local.yml`. Configurations\nspecified in environment variables should be named with the `APP_` prefix and in upper case. When a configuration\nis specified in both a configuration file and an environment variable, the latter takes precedence. \n\nThe `config` directory contains the configuration files named after different environments. For example,\n`config/local.yml` corresponds to the local development environment and is used when running the application \nvia `make run`.\n\nDo not keep secrets in the configuration files. Provide them via environment variables instead. For example,\nyou should provide `Config.DSN` using the `APP_DSN` environment variable. Secrets can be populated from a secret\nstorage (e.g. HashiCorp Vault) into environment variables in a bootstrap script (e.g. `cmd/server/entryscript.sh`)\n\n## Unit Testing and Its Coverage\n\nFor testability purpose, unit testings are provided.\nWe can use golang test package.\n\n```shell\n$ go test -v ./... -race -coverprofile=coverage.out\n\n```\n\n## Deployment\n\nThe application can be run as a docker container. You can use `make build-docker` to build the application \ninto a docker image. The docker container starts with the `cmd/server/entryscript.sh` script which reads \nthe `APP_ENV` environment variable to determine which configuration file to use. For example,\nif `APP_ENV` is `qa`, the application will be started with the `config/qa.yml` configuration file.\n\nYou can also run `make build` to build an executable binary named `server`. Then start the API server using the following\ncommand,\n\n```shell\n./server -config=./config/prod.yml\n```\n\n## Reference\n\nGo RESTful API (Boilerplate)\nhttps://github.com/qiangxue/go-rest-api\n\nHexagonal-Architecture by Alistair Cockburn \nhttps://alistair.cockburn.us/hexagonal-architecture/\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauluswi%2Frhine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpauluswi%2Frhine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpauluswi%2Frhine/lists"}