individual wallet where each wallet may has multiple cards

Summary

This project was made especially as a requirement for passing the technical test in Spenmo. It is a simple golang application that allows us to create a team/individual wallet where each wallet may has multiple cards.

In the docs folder, you can find the schema of the database and the api collection (I use Insomnia) for the project.

Constraints and Assumptions

  • Client makes a read or write request
  • Service does processing, stores data, then returns the results
  • Service needs to evolve from serving a small amount of users to a lot of users
  • Service has high availability

System Design Plan

The project is written in golang and uses the following technologies:

  • Gokit (a toolkit for microservices)
  • PostgreSQL (database)

The uses of Gokit was decided since its design is well suited with modern software design like elegant monolith and microservices. Aside from that, it is also a toolkit that I am familiar with. Since Gokit also support the separation of concerns, the project can be easily divided into multiple layers based on the Service Layer pattern. The project is divided into the following layer groups:

  • Transport layer, which is responsible for the communication between the application and the rest of the internet (HTTP, Grpc, etc).
  • Endpoint layer, which is responsible in implementing the transport into a business logic, with endpoint we can have two different transport to access a specific business logic.
  • Service layer, which is responsible for the business logic.

The implementation of all those layers abide to the Clean Code architecture and Hexagonal architecture.

Starts As Monolith

For the sake of simplicity, the project is assumed to be a monolith. This means that we can run the project as a single service, either as a static binary in a vps or as a container in docker. We can even put the database in a similar box.

When we need to scale it, we can do vertical scalling by adding more power. Since the resources are limited (a single box), we can easily monitor the metrics of the box to determine bottlenecks.

Starts As Microservice

Once the users grow, we can deploy each part of the project as a microservice. We can start scaling each service horizontally based on its traffic. Deploying the services as containers will make the scaling easier.

We separate each table on the previous database into a separate database. Each service will own its own database and other services cannot directly access the database. Each service can also be splitted into multiple services based on its task, read or write (CQRS pattern). This will allow us to use a different database between the read (replica) and write (master) services.

Since the project has grown into multiple services, we also need to make sure the services can only be accessed from a single gateway and use a private subnet for everything else. We can use an API Gateway for this.

Observability Plan

If money is not the problem and we don't have enough resources to setup a monitoring system, we can just use a hosted monitoring system like Datadog or New Relic.

We can also use a local monitoring system like Prometheus or InfluxDB. Based on the comparison of the monitoring system on the Prometheus page, I will choose Prometheus instead of InfluxDB. The reason is that I prefer to use another tool for logging like ELK instead of using InfluxDB for both use cases. Quoted from the Prometheus page, Prometheus has "more powerful query language, alerting, and notification functionality". It also has "higher availability and uptime for graphing and alerting".

Based on above use case, I already included a requestId metadata on each request that comes in and comes out into/from the service. We can just use it to trace and/or identify the request between all related microservices.

An example of prometheus implementation can be seen by accessing "/metrics" endpoint.

Relational Tables

Relational Tables

Setup database

Make sure the postgres has been up and running. If it is not, we can run it in the docker:

docker run --name postgres-svc-spenmo -p 5432:5432 \
    -e POSTGRES_DB=spenmo \
    -e POSTGRES_USER=user \
    -e POSTGRES_PASSWORD=password \
    -v ~/Tmp/postgres_data:/var/lib/postgresql/data \
    -d postgres:13.2-alpine

or

docker start <container_id>

Install golang-migrate:

brew install golang-migrate

Migrate the current schema:

export POSTGRESQL_URL='postgres://user:[email protected]:5432/spenmo?sslmode=disable'
migrate -database ${POSTGRESQL_URL} -path config/db/migrations up

Common error:

error: Dirty database version 2. Fix and force version.

Solution:

migrate -database ${POSTGRESQL_URL} -path config/db/migrations force <version - 1>

Run the app

Use Makefile with hot reload enabled (air will automatically installed):

make watch

Use Makefile with hot reload disabled:

make run

Run the main go file:

go run cmd/main.go

For other options, we can use make help:

❯ make help

Usage:
  make <target>

Targets:
  build              Build your project and put the output binary in build/spenmo-test
  clean              Remove build related file
  docker-build       Use the dockerfile to build the container (name: spenmo-test)
  docker-release     Release the container "spenmo-test" with tag latest and 0.0.1
  help               Show this help message
  lint               Run all available linters
  lint-dockerfile    Lint the Dockerfile using 'hadolint/hadolint'
  lint-go            Lint all go files using 'golangci/golangci-lint'
  test               Run the tests of the project
  test-unit          Run the unit tests of the project
  test-integration   Run the integration tests of the project
  vendor             Copy all packages needed to support builds and tests into the vendor directory
  watch              Run the code with 'cosmtrek/air' to have automatic reload on changes

Testing

Unfortunately, in this current version, I am only able to finish the integration part of the testing that will test the service part of the project. That's why, the only working Make target is test-integration. Since the only working test is the integration test, I didn't include the test in the Gitlab CI yaml file (it needs a working PostgreSQL). Below is the command to trigger the test and the current status of the test:

❯ make test-integration
go test -race -run ".Integration" ./...
?       gitlab.com/renodesper/spenmo-test/cmd                             [no test files]
?       gitlab.com/renodesper/spenmo-test/endpoint                        [no test files]
?       gitlab.com/renodesper/spenmo-test/middleware                      [no test files]
?       gitlab.com/renodesper/spenmo-test/middleware/recover              [no test files]
?       gitlab.com/renodesper/spenmo-test/repository                      [no test files]
?       gitlab.com/renodesper/spenmo-test/repository/postgre              [no test files]
ok      gitlab.com/renodesper/spenmo-test/service               (cached)
ok      gitlab.com/renodesper/spenmo-test/transport/http        (cached)  [no tests to run]
?       gitlab.com/renodesper/spenmo-test/util/card                       [no test files]
?       gitlab.com/renodesper/spenmo-test/util/constant                   [no test files]
?       gitlab.com/renodesper/spenmo-test/util/ctx                        [no test files]
?       gitlab.com/renodesper/spenmo-test/util/error                      [no test files]
?       gitlab.com/renodesper/spenmo-test/util/errors                     [no test files]
?       gitlab.com/renodesper/spenmo-test/util/logger                     [no test files]
?       gitlab.com/renodesper/spenmo-test/util/logger/noop                [no test files]
?       gitlab.com/renodesper/spenmo-test/util/logger/zap                 [no test files]
?       gitlab.com/renodesper/spenmo-test/util/response                   [no test files]
Owner
Boy Sandy Gladies Arriezona
https://bitbucket.org/renodesper https://gitlab.com/renodesper
Boy Sandy Gladies Arriezona
Similar Resources

Help to release a project which especially has multiple git repositories

This project aims to help to release a project which especially has multiple git repositories. Installation Install it to a Kubernetes cluster. You ca

Dec 15, 2022

Flexible E-Commerce Framework on top of Flamingo. Used to build E-Commerce "Portals" and connect it with the help of individual Adapters to other services.

Flamingo Commerce With "Flamingo Commerce" you get your toolkit for building fast and flexible commerce experience applications. A demoshop using the

Dec 31, 2022

Openldap (LDAP) binding for Golang (go) ; no more support ; you may have a look at https://github.com/go-ldap/ldap

OpenLDAP this is Openldap binding in GO language. I don't work any more with golang, so, please fork this project. Installation : Installation is easy

Mar 4, 2021

FactorLog is a logging infrastructure for Go that provides numerous logging functions for whatever your style may be

FactorLog is a logging infrastructure for Go that provides numerous logging functions for whatever your style may be

FactorLog FactorLog is a fast logging infrastructure for Go that provides numerous logging functions for whatever your style may be. It could easily b

Aug 3, 2022

Takes a full name and splits it into individual name parts

gonameparts gonameparts splits a human name into individual parts. This is useful when dealing with external data sources that provide names as a sing

Sep 27, 2022

The Monogon Project Monorepo. May contain traces of peanuts and a pure Go Linux userland.

This is the main repository containing the source code for the Monogon Project.

Jan 6, 2023

High-Performance Shortlink ( Short URL ) app creator in Golang. For privacy reasons, you may prefer to host your own short URL app and this is the one to use.

High-Performance Shortlink ( Short URL ) app creator in Golang. For privacy reasons, you may prefer to host your own short URL app and this is the one to use.

About The Project Shortlink App in Golang Multiple Node based Architecture to create and scale at ease Highly performant key-value storage system Cent

Jan 3, 2023

gophertunnel is composed of several packages that may be of use for creating Minecraft related tools

gophertunnel is composed of several packages that may be of use for creating Minecraft related tools

gophertunnel is composed of several packages that may be of use for creating Minecraft related tools. A brief overview of all packages may be found here.

Dec 31, 2022

Scans a file or folder recursively for jar files that may be vulnerable to Log4Shell

Velocity A Minecraft server proxy with unparalleled server support, scalability, and flexibility. Velocity is licensed under the GPLv3 license. Goals

Jan 7, 2023

Individual practice & tutorials of GoLang

golang-practice Individual practice & tutorials of GoLang Local Client steps: cd pwd Create a module and outline relevant dependencies as necessary go

Jan 6, 2022

Golisp-wtf - A lisp interpreter (still just a parser) implementation in golang. You may yell "What the fuck!?.." when you see the shitty code.

R6RS Scheme Lisp dialect interpreter This is an implementation of a subset of R6RS Scheme Lisp dialect in golang. The work is still in progress. At th

Jan 7, 2022

Splits heat 1 from the feature race to make it easy to upload multi-heat races to simracerhub as individual races

simracerhub_heat_splitter Splits heat 1 from the feature race to make it easy to upload multi-heat races to simracerhub as individual races Install Yo

Jan 9, 2022

A reimplementation of the TinyGo drivers package for communicating with multiples of the same (supported) devices on one individual I2C bus.

tinygo-multi-i2c A reimplementation of the TinyGo drivers package for communicating with multiples of the same (supported) devices on one individual I

Mar 10, 2022

Cue cards in your terminal

Cue cards in your terminal

Cue Cue cards in your terminal. Usage Make some colon (:) separated cue cards in a plain text file. Press Spacebar: You can flip a card by pressing sp

Nov 29, 2022

Golang libraries for generating QR codes for Smart Health Cards representing COVID-19 Immunizations

Golang libraries for generating QR codes for Smart Health Cards representing COVID-19 Immunizations

go-smarthealthcards Golang libraries for generating QR codes for Smart Health Cards representing COVID-19 Immunizations. Usage Individual Libraries Yo

Dec 5, 2021

wtf? paranormal twitter.com activity using Twitter Cards. Migros.tr #DoITYourself

GTKE - go-tweet-kart-ele wtf? paranormal twitter.com activity using Twitter Cards. Migros.tr #DoITYourself Just for fun. Go. # You have go. go install

Dec 7, 2021

A little tool to create small QR code cards for vaccination/test proof.

Icedream's fancy vaccination/test certificate card tool This is just a tool I wrote to transform my vaccine certificate QR codes into something I can

Dec 16, 2021

66 is two player game played with playing cards and from now on you can play it from browser with your friends.

altmis-alti 66 is two player game played with playing cards and this project provides multiplayer game space from browser. How to run? Clone the proje

Feb 1, 2022

Golang Web server to draw cards from The Tarot of the Silicon Dawn

Silicon Dawn I made this so I can pull random cards on my phone and review the text. I originally designed this for use in Pythonista Then I rewrote i

Dec 17, 2021
Payment abstraction library - one interface for multiple payment processors ( inspired by Ruby's ActiveMerchant )

Sleet Payment abstraction library - interact with different Payment Service Providers (PsP) with one unified interface. Installation go get github.com

Dec 28, 2022
Assanlab - JSON input data with counts on how many times you showed an ad on each individual domain

JSON input data with counts on how many times you showed an ad on each individua

Dec 31, 2021
Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

Dec 29, 2022
The Hyperscale InputFilter library provides a simple inputfilter chaining mechanism by which multiple filters and validator may be applied to a single datum in a user-defined order.

Hyperscale InputFilter Branch Status Coverage master The Hyperscale InputFilter library provides a simple inputfilter chaining mechanism by which mult

Oct 20, 2021
Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

kubectl-slice: split Kubernetes YAMLs into files kubectl-slice is a neat tool that allows you to split a single multi-YAML Kubernetes manifest into mu

Jan 3, 2023
Ethereum-vanity-wallet - A fork of https://github.com/meehow/ethereum-vanity-wallet but the key can be exported to a JSON keystore file

ethereum-vanity-wallet See https://github.com/meehow/ethereum-vanity-wallet This version: doesn't display the private key let's you interactively expo

Jan 2, 2022
The Bhojpur Wallet is a platform-as-a-service product used as a Wallet Engine based on the Bhojpur.NET Platform for application delivery.

Bhojpur Wallet - Data Processing Engine The Bhojpur Wallet is a platform-as-a-service used as a Service Engine based on the Bhojpur.NET Platform. It l

Sep 26, 2022
Scp-wallet-api - Backend for SCP Wallet app

SCP Wallet API Backend for SCP Wallet app. It exposes a simplified REST API whic

Jan 31, 2022
Personal-Solana-Wallet - Create your personal wallet on Solana blockchain

Personal Wallet on Solana using Go ♾️ Setting up environment Installation of Cob

Nov 9, 2022
Peerster refers to a gossip-based P2P system composed of multiple peers interacting with each other

Peerster design Peerster refers to a gossip-based P2P system composed of multiple peers interacting with each other. A peer refers to an autonomous en

Jan 22, 2022