First of all, I am super thrilled to announce my very first open source project. (#🔥)
This is just the beginning, and I'm planning to be more involved in
open source projects at least in the next couple of months.
So, without further ado,
I introduce you to Goreen-tea 🍵
A boilerplate project that focused on data-intensive (database heavy) microservice.
Heavily inspired around the idea of application-centric architecture like clean architecture by Robert Martin.
Clone it and setup a new project:
git clone https://gitlab.com/altiano/goreen-tea.git --depth 1
cd goreen-tea
bash ./init.sh <base-url> <project-name>
# e.g. bash ./init.sh gitlab.com/altiano awesomeness-api
Goal
My goal is to quickly jump into the project requirements,
without having to spend much time to setup the same old thing over and over again.
It is to be more productive.
The boilerplate should be very simple,
packed with some modern best practices
and of course quite flexible for changes in the future as new technologies arrived.
Restaurant order sample
I already set up a sample scenario of kinda like my expectation of being productive of using this project. It is about ordering system in a restaurant.
The requirement are as follow:
- It should be able to record a customer order (CO), which has following specs
- Who they are (for the sake of simplicity, we'll use the customer email).
- What they order, at least one.
- From whom the they heard about the restaurant, we'll use referral code.
- What will be their own referral code to give to the other.
- It also should be able to assigned the waiter for an order.
- Depending of how "valuable" the order is and the waiters availability, It may be assigned a waiter with higher rating.
- The customer that give their referral code will be notified via email when it is used.
- It would be nice if the restaurant knows the number of customers.
App package implementation
Here I define that all the above requirements will happen in a one go.
So we give it a name : onsiteOrder.go
in the app package.
The four major steps are:
- The creation of CO record (A)
- The waiter selection to serve the order (B)
- Referral code notification (C)
- Live tracking stats (D)
I put a label at the end so that we can see the relation of each step with the domain that is responsible for a more detailed implementation.
Domain package implementation
Then, I define the domain package as below:
-
CustomerOrder
- will be responsible to create CO record and generate its own referral code (A)
- notify the referral code owner via email (C)
- notify a customer who will be their waiter (B)
-
Waiter
- Pick a top waiter currently available (B)
- or to pick a normal waiter (B)
- and able to increase the total serve of a waiter if they are chosen (B)
-
AssistanceCordinator
A domain doesn't necessarily mean a real business entity.
There may be times that you need to perform cross-domain calls as a single operation, meaning it would result in an inconsistent state if one call success the the other failed.
Think of it kinda like a transaction.
Here I define an auxiliary domain that responsible for waiter assignment.
This domain will depends on the CustomerOrder
& Waiter
(B)
-
VisitorCounter
(what do think? 🤷♂️)
At this point, I highly suggest you to look at the sample code so that it will become clearer.
Running the project
- The example use MongoDB as its database (I like MongoDB).
If you happen to have docker running and haven't install MongoDB yet,
you can use the
docker-compose.yaml
. - I already setup a sample waiter list, just run
.misc/mongo-playground/seed_waiters.js
in your MongoDB shell. - In it, there is also Jaeger as the tracing backend but it is optional. If you never used some kind of tracing, I would highly recommended you learn a little bit more about jaeger. Tracing itself is an important part when you project goes live.
- You should also have
.env
file in the project root directory like this:
APP_PORT=8888 # to which port the application will run
MONGO_URI=mongodb://localhost:27017 # your mongodb connection-string
MONGO_DB_NAME=golang-boilerplate # your mongdob collection name
JEAGER_URL=http://localhost:14268/api/traces # Optional if jaeger not present
Run it with go run main.go
,
Try it with http request like this:
POST http://localhost:8888/customerOrder
{
"Email": "satoshi@domain.com",
"Orders": ["satay", "fried rice", "meatball", "green tea"],
"ReferralCode": 0, // indicates satoshi not use any referral code
}
Core architecture
A peek at what inside.. 🔭
Some of the features that I haven't mention yet are:
- Unit testing with go-mock
- Dependency injection with google wire
- VS code snippets, tasks and postman-like http testing
- Dockerfile
- K8S manifest
- GitLab CI
- Open telemetry with jaeger
- Rest API with iris
To describe them one by one would be really time consuming.
And it is not the purpose of this introduction article either.
See them for yourself, and feel free to ask question to me, directly, anytime.
So, looking forward.. 🌄
I'd like to include these features in the next release:
- Data store
- MongoDB seeding
- MySQL support
- Redis
- Servers
- GRPC
- GraphQL
- Messaging
- Kafka
- NATS
As I said in the beginning,
this is just the beginning,
I'd love to hear some feedbacks to improve this project.
Thank you for your time.
Original posted on : https://blog.altiano.dev/goreen-tea-introduction/
Top comments (1)
Very nice! Thx ^^