Hi, I'm Sun. This is my Dcard's 2023 backend intern homework.
- Go 1.20
- PostgreSQL 15.2
- Set up environment configurations
cp .env.example .env
cp docker-compose.yml.prod.example docker-compose.yml # There are two example files (development and production for different situation)
# edit `.env` and `docker-compose.yml` before continue
- Create and Start containers
docker-compose up -d
- Run migrations
Install golang-migrate and run commands below. (install it first)
migrate -database postgres://postgres:{password}@db:5432/postgres?sslmode=disable -source file://migrations up # change the password here
# and run for testing database
migrate -database postgres://postgres:{password}@db:5432/testing?sslmode=disable -source file://migrations up # change the password here
Done! the application is running!
- change
.env
file from:
...
DB_DATABASE=postgres
...
to:
...
DB_DATABASE=testing
...
- enter the container
go
, and run test
go test -p 1 -count 1 ./...
{
"key": "head1"
}
http status: 201
{
"key": "node1",
"value": "content",
"prev": "head1"
}
http status: 201
Get head by key.
{
"key": "head1",
"next": "node1",
"created_at": "2023-04-05T14:20:59.206051Z",
"updated_at": "2023-04-05T14:20:59.206051Z"
}
Get node by key.
{
"key": "node1",
"value": "some content",
"next": "node2",
"created_at": "2023-04-05T14:01:43.666822Z",
"updated_at": "2023-04-05T14:01:43.666822Z"
}
http status: 204
http status: 204
Why use PostgreSQL for this key-value system?
First. Because in the system, the two neighboring nodes are linked together. So we can benefit from the cascade
feature in relational database. For example, if there are nodes like:
NodeA -> NodeB -> NodeC
When we delete NodeC
, we need to update NodeB
's link after deletion successful. But we have linked two node in our database. So we can do it by simply set cascade
as set null on delete
.
Second. Because the structure of the table is fixed. We can use the same schema to finish this system.
Base on the reason above, I choose the relational database. And I want to use PostgreSQL instead of MySQL (or other relational db) at this time because it has more feature than MySQL (although not used this time). So I thought it's a good idea to give it a try on a simple project.
There are some more features I plan to do, but there is no time QQ
- Use migration
- Refactor with DI
- Add a reverse proxy in front of the application
- More formal API documents
- Automation testing by GitHub Actions
- Package Release by GitHub Actions
- Use gRPC instead of RESTful API
- Stress testing and benchmark