https://github.com/lucasvmiguel/stock-api
A Stock API is a REST API written in Go where products can be created, read, updated and deleted
https://github.com/lucasvmiguel/stock-api
chi go postgresql rest-api
Last synced: 10 months ago
JSON representation
A Stock API is a REST API written in Go where products can be created, read, updated and deleted
- Host: GitHub
- URL: https://github.com/lucasvmiguel/stock-api
- Owner: lucasvmiguel
- Created: 2022-07-08T10:14:56.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-07-29T12:26:24.000Z (over 2 years ago)
- Last Synced: 2023-09-05T02:56:55.258Z (over 2 years ago)
- Topics: chi, go, postgresql, rest-api
- Language: Go
- Homepage:
- Size: 421 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Stock API
[](https://github.com/lucasvmiguel/stock-api/actions/workflows/build-and-test.yml)
## Description
A Stock API is a REST API written in Go where products can be created, read, updated and deleted.
Note: _This API has been configured for `development` environment. To use in a `production` environment, further setup will be required._
## Installing the app
**Requirements:**
- [Go](https://go.dev/) (>= 1.20)
- [Docker](https://www.docker.com/)
- [Docker Compose](https://docs.docker.com/compose/install/)
To install the go modules required to run the application, run the following command:
```bash
git clone git@github.com:lucasvmiguel/stock-api.git
cd stock-api
make install
```
## Running the app
1. Open a terminal and run the following command to start the persistence (database) required:
```bash
make persistence-up
```
2. In another terminal, start the application with the following command:
```bash
make run
```
## Testing
### Unit test
```
make test-unit
```
### Integration test
1. Open a terminal and run the following command to start the persistence (database) required:
```bash
make persistence-up
```
2. In another terminal, run the integration test with the following command:
```bash
make test-integration
```
### Stress test
**Requirements:**
- [Apache AB](https://httpd.apache.org/docs/2.4/programs/ab.html)
1. Open a terminal and run the following command to start the persistence (database) required:
```bash
make persistence-up
```
2. In a new terminal, start the application with the following command:
```bash
make run
```
3. In another terminal, run the stress test with the following command
```bash
make test-stress
```
## Configuration
- To configure how the app will run, check the following file: [.env](.env)
- To configure how the app will be built and released, check the following file: [Makefile](Makefile)
## Architecture
This section describes what are the goals of the system and some of its design and implementation.
### Requirements
The following list shows all user requirements implemented by the system.
- As a user, I can fetch all products using a REST API.
- As a user, I can fetch a paginated list of products using a REST API.
- As a user, I can fetch a product by its id using a REST API.
- As a user, I can create a product using a REST API.
- As a user, I can update some fields (`name` and/or `code`) of a product by its id using a REST API.
- As a user, I can delete a product by its id using a REST API.
### Schema
The following picture shows all the entities of the system.

### System Design
The following pictures shows some of the details of how the system is designed and implemented.


### Folder/File structure
- `/cmd`: Main applications for this project.
- `/cmd/api`: Package responsible for starting the API application.
- `/cmd/api/starter`: Package containing all code required for starting the API application. (eg: config, routes, etc)
- `/internal`: Private application and library code.
- `/internal/product`: Product domain, where every code related to product should be placed. (Inspired by [DDD](https://en.wikipedia.org/wiki/Domain-driven_design))
- `/pkg`: Library code that's ok to use by external applications (eg: `/pkg/mypubliclib`).
- `/test`: Integration tests that run with external apps. (eg: database)
- `/.github`: CI/CD from Github.
- `docker-compose.yml`: Used to spin up the persistence layer in development and testing.
- `.env`: configures project.
- `Makefile`: Project's executable tasks.
Note: _inspired by https://github.com/golang-standards/project-layout_
### Stack
- Language: [Go](https://go.dev/)
- API/REST framework: [chi](https://github.com/go-chi/chi)
- Database ORM: [GORM](https://gorm.io/)
- Config reader: [godotenv](https://github.com/joho/godotenv)
- Database: [Postgres](https://www.postgresql.org/)
- Message Queue: [Asynq](https://github.com/hibiken/asynq)
## API Docs
In this section is described the REST API's endpoints (URL, request, response, etc).
Create product
Endpoint that creates a product
#### Request
```
Endpoint: [POST] /api/v1/products
Headers:
Content-Type: application/json
Body:
{
"name": "Product name",
"stock_quantity": 10
}
```
#### Response
**Success**
```
Status: 201
Body:
{
"id": 1,
"name": "Product name",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 10,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
```
**Bad Request**
```
Status: 400
```
**Internal Server Error**
```
Status: 500
```
Get products paginated
Endpoint to get products paginated
#### Request
##### Query Parameters
- `cursor`: use the response's `next_cursor` field
- `limit`: limit of products to be returned (min=1, max=100)
```
Endpoint: [GET] /api/v1/products?limit=10&cursor=2
Headers:
Content-Type: application/json
```
#### Response
**Success**
```
Status: 200
Body:
{
"items": [
{
"id": 1,
"name": "foo",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 1,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
],
"next_cursor": 2
}
```
**Bad Request**
```
Status: 400
```
**Internal Server Error**
```
Status: 500
```
Get all products
Endpoint to get all products (does not have pagination)
#### Request
```
Endpoint: [GET] /api/v1/products/all
Headers:
Content-Type: application/json
```
#### Response
**Success**
```
Status: 200
Body:
[
{
"id": 1,
"name": "foo",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 1,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
]
```
**Internal Server Error**
```
Status: 500
```
Get product by id
Endpoint to get a product by id
#### Request
```
Endpoint: [GET] /api/v1/products/{id}
Headers:
Content-Type: application/json
```
#### Response
**Success**
```
Status: 200
Body:
{
"id": 1,
"name": "foo",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 1,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
```
**Not Found**
```
Status: 404
```
**Internal Server Error**
```
Status: 500
```
Update product by id
Endpoint that updates a product by id
#### Request
```
Endpoint: [PUT] /api/v1/products/{id}
Headers:
Content-Type: application/json
Body:
{
"name": "new product name",
"stock_quantity": 5
}
```
#### Response
**Success**
```
Status: 200
Body:
{
"id": 1,
"name": "new product name",
"code": "70a17d32-a670-4396-9706-bd0940152fc7",
"stock_quantity": 5,
"created_at": "2022-07-08T18:53:57.936433+01:00",
"updated_at": "2022-07-08T18:53:57.936433+01:00"
}
```
**Bad Request**
```
Status: 400
```
**Not Found**
```
Status: 404
```
**Internal Server Error**
```
Status: 500
```
Delete product by id
Endpoint to delete a product by id
#### Request
```
Endpoint: [DELETE] /api/v1/products/{id}
Headers:
Content-Type: application/json
```
#### Response
**Success**
```
Status: 204
```
**Not Found**
```
Status: 404
```
**Internal Server Error**
```
Status: 500
```
## Configuration
A file called `.env` has all config used in the project.
In the future, a service like [Doppler](https://www.doppler.com/) or [Vault](https://www.vaultproject.io/) could (and should) be used in the project.
## CI/CD
The project uses Github CI to run tests, builds (and possibly deployments). You can see the badge below:
[](https://github.com/lucasvmiguel/stock-api/actions/workflows/build-and-test.yml)
Steps:
1. Set up Go
2. Build
3. Unit Test
4. Integration Test
5. Log in to the Container registry (Github)
6. Build and push Docker images
## Important notes
- command `make docker-run` in `development` will only work correctly if the container's network is configured right. (More info [here](https://docs.docker.com/config/containers/container-networking/))
## Roadmap
- `Improvement`: Add [Google's wire DI library](https://github.com/google/wire) to the project.
- `Improvement`: If it's needed to add more entities (eg: [Product](internal/product/entity/product.go)), we might need to centralize all entities in just one package. (Something like a `entity` package) That way, we would prevent cycle dependencies. (Check [this link](https://www.reddit.com/r/golang/comments/vcy5xq/ddd_file_structure_cyclic_dependencies/))
- `Improvement`: API docs are being described on the Readme. However, [OpenAPI](https://swagger.io/specification/) might be a good improvement in the future.
- `Improvement`: Using a secret management service like [Doppler](https://www.doppler.com/) or [Vault](https://www.vaultproject.io/)