This repository contains the code for the technical test for Deporvillage.
This documentation could be accessed in a Notion page.
- Go v1.17+
- This project has been designed as a single Go module.
- Go Modules is provided to manage dependencies.
- Docker folder to deploy service in containers.
- Top level folders are created following standard project layout for Golang:
- Internal folder structure follows DDD and Hexagonal Architecture principles:
- Shared and Product contexts.
- Domain, application and infrastructure layers.
- Product aggregate as main data model.
- Repository pattern for data management.
- Value objects to validate SKU format.
- Tests are close to executable code.
-
Due to these requirements:
- The Application must write a de-duplicated list of these numbers to a log file in no particular order.
- Your Application may not for any part of its operation use or require the use of external systems, for example Apache Kafka or Redis.
I have not implemented a solution with an external database like MySQL or PostgreSQL and persist info with a log file.
The sentence "Use only the standard lib, except for the database drivers." was a little confusing for me with that.
-
The service intends to continue growing and expanding, so a clean architecture is important to allow this in the future.
-
The service will be exec in a Linux environment with Docker containers. This is important for above line of code, because Windows OS not support Kill function.
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
-
Input with zeroes that exceed 9 characters are consider invalids.
Go Modules is provided to manage dependencies, but the project in the current state does not require any external dependency.
Service use standard library only.
For installing a go module, just exec:
go get package_url
For clean and install dependencies in the code, exec:
go mod tidy
To execute the application, just run:
go run cmd/api/main.go
To build it into a executable:
go build cmd/api/main.go
./main
The project provides a Makefile with some commands to easy-way management of Docker files.
It calculates which Docker-Compose files are executed in base to ENV variable.
If not provided, ENV variable is development by default. Possible values are test, debug, development, staging and production.
To run it, just execute:
make start ENV=env
To run it, building images, execute:
make start-build ENV=env
To stop it, execute:
make stop ENV=env
To build containers without cache, execute:
make build ENV=env
For developing more code into project, it is recommended to launch Makefile commands with ENV=development.
It gets dev-api.Dockerfile to create api service, which provides a Golang image where air package is installed to exec service with live reload.
To see more: https://github.com/cosmtrek/air
make start ENV=development
Makefile commands set development ENV by default if not provided.
For debugging existing code from project, it is recommended to launch Makefile commands with ENV=debug.
It gets debug-api.Dockerfile to create api service, which provides a Golang image where delve package is installed to exec service with a debugger on port 40000.
To see more: https://github.com/go-delve/delve
make start ENV=debug
For VS Code users, a configuration is provided to debug with Delve into launch.json of .vscode folder.
For launching project in a production environment, it is recommended to launch Makefile commands with ENV=production.
It gets prod-api.Dockerfile to create api service, which provides a Golang alpine image where a single executable file is generated to be launched.
make start ENV=production
- Important service configuration parameters is taken from environment variables.
- If some param is not defined in environment variables, Docker Compose files set a default value.
- In last instance, if the service can not take the value from env variable (launched without Docker for example), a default value is defined in code.
To set a env variable, just run:
export API_PORT=value
To execute all tests with coverage, just run:
go test -cover ./...
To watch live results of tests in the browser with a very cool UI.
GoConvey - Go testing in the browser
To experience the client side, any TCP client is valid to connect to service, send data and watch complete workflow.
For example, netcat utility is used in tests:
nc 127.0.0.1 4000
Then, test to write some product SKU and see how the client is disconnected.
- If the input has a valid format and it does not exist before, it will be persisted in the log file into tmp/products.log, and will count as unique product.
- If the input has a valid format but is exists before, it will count as duplicated product.
- If the input has an invalid format, it will count as invalid product.
- If the input is exactly terminate, all clients are disconnected and server is shutting down immediately.
In cmd/client
, I provide a short go program with a TCP client that generates random strings and send it to server, reconnecting all time and repeating the process every 2 seconds.
There is a flag for generating valid product SKUs. Otherwise, inputs will be invalid by default.
go run cmd/client/main.go