Ports microservices
This project contains two simple microservices developed as a recruitment coding assignment.
Requirements
Overview
This repository contains two microservices:
- Ports service that exposes a gRPC API that allows to store and list Ports in persistence layer.
- Ingest service that allows to read Port resources from input JSON file and store them in Ports service via gRPC.
Ingest service reads resources from JSON file one-by-one using a stream, so it does not load all data to its memory and supports large files.
In current implementation the Ingest service writes resources to Ports service sequentially in order not to overload it.
Services are configured with environment variables:
Usage
Both services are containerized and can be run with Docker Compose:
- Run services in Docker containers:
docker-compose up
.
- Stop containers by press Ctrl+C.
- Clean up containers:
docker-compose down
.
Description
These are steps that should happen on a successful run:
- Docker compose spawns Ports service and Ingest service.
- Ingest service connects to Ports service via gRPC.
- Ingest service reads Port resources from ports.json file and transmits them to Ports service one-by-one.
- Each Ports resources received by Port service is stored in its in-memory storage.
- After processing all resources, Ingest service shuts down.
- Ports service continues to operate. It can be gracefully shut down by sending SIGTERM or SIGINT signals.
Note that the ports.json file used by Ingest service can be modified in docker-compose.yml by changing the volume path.
Stripped logs of a successful run are presented below:
➜ ports-microservices git:(master) docker-compose up
[+] Running 3/3
⠿ Network ports-microservices_default Created 0.0s
⠿ Container ports-microservices-portssvc-1 Created 0.1s
⠿ Container ports-microservices-ingestsvc-1 Created 0.1s
Attaching to ports-microservices-ingestsvc-1, ports-microservices-portssvc-1
ports-microservices-portssvc-1 | time="2022-09-19T13:19:57Z" level=debug msg="Creating ports server" config="{GRPCServerAddress::9090}" logger=ports-server
ports-microservices-portssvc-1 | time="2022-09-19T13:19:57Z" level=info msg="Starting gRPC Ports server" address="[::]:9090" logger=ports-server
ports-microservices-ingestsvc-1 | time="2022-09-19T13:19:57Z" level=debug msg="Creating ingest service" config="{PortsFilePath:/app/ports.json PortsServiceAddress:portssvc:9090}" logger=ingest-service
ports-microservices-ingestsvc-1 | time="2022-09-19T13:19:57Z" level=debug msg="Dialing gRPC" logger=ports-client server-address="portssvc:9090"
ports-microservices-ingestsvc-1 | time="2022-09-19T13:19:57Z" level=debug msg="Storing port in ports service" logger=ingest-service port-id=AEAJM
ports-microservices-portssvc-1 | time="2022-09-19T13:19:57Z" level=debug msg="Storing port" logger=ports-service port-id=AEAJM
[...]
ports-microservices-portssvc-1 | time="2022-09-19T13:19:58Z" level=debug msg="Storing port" logger=in-memory-ports-repo port="&{ZWUTA Mutare Mutare Zimbabwe [] [] [32.650351 -18.9757714] Manicaland Africa/Harare [ZWUTA] }"
ports-microservices-ingestsvc-1 | time="2022-09-19T13:19:58Z" level=info msg="Ingest service finished successfully"
ports-microservices-ingestsvc-1 exited with code 0
Development
Development tools:
Development commands:
- Build binaries and Docker images; test and lint code:
make dev-check
- Build binaries to build directory:
make build
- Build Docker image of the Ports service:
make docker-build
- Run tests:
make test
- Run tests with race detector:
make test-race
- Run static code analysis:
make lint
- Format source code:
make fmt
- Regenerate the source code:
make generate