Skip to content

Laelapa/CompanyRegistry

Repository files navigation

Company Registry API

A Go REST API designed to demonstrate a layered, configurable, and decoupled architecture. This service manages company records and user identities, utilizing PostgreSQL for persistence and Kafka for event propagation, docker & docker compose for streamlined deployments, ci workflows & linting for code quality, easy configurability, and type-safe database access with sqlc and pgx.

Architecture

The application is structured to decouple the transport layer, business logic, and data access layers, enabling strict separation of concerns.

Layered Design

  • Business Logic Layers:
    • Services Layer (internal/service): Defines its own interface(Ports) that other layers need to implement to interact with it. Implements business logic and orchestrates data flow.
    • Domain Layer (internal/domain): Contains pure entity definitions and domain-specific errors. This layer has no external dependencies.
  • Data Access Layer:
    • Adapters (internal/repository/adapters): Concrete implementations that satisfy the interfaces set by the service layer. They wrap the repository functions generated by sqlc.
    • Queries (internal/queries): Hand-typed SQL queries that get fed to sqlc to generate type-safe go functions that get evaluated at compile-time, foregoing the disadvantages of loosely-typed solutions like ORMs.
  • Transport Layer (internal/routes/handlers): Handles HTTP requests, validation of the initial request, and response marshaling. It depends only on the Service layer.

Notable Features

  • Secure Authentication:

    • User registration with bcrypt password hashing.
    • JWT-based stateless authentication.
    • Middleware for protected API routes (internal/middleware/auth.go).
  • Event Publishing: for all mutating operations via Kafka. Designed again with the port & adapter mentality, implementing the interfaces that the service layer defines. (internal/events/kafka.go)

  • Company Management: Full CRUD capabilities for company records.

  • Observability:

    • Structured logging with uber-go/zap.
    • Request logging through middleware with comprehensive sanitization for user-controlled elements.
  • API Documentation: Integrated Swagger UI serving an OpenAPI specification.

  • Type-Safe SQL: Database interactions generated with sqlc instead of an ORM, maintaining explicitness and compile-time query verification.

  • Extensive Configuration living in the .env file as well as working defaults set inside the compose files and the (internal/config) package of the application.

Getting Started

Prerequisites

  • Docker & Docker Compose for deployment and demo-ing
  • Go for local development
  • sqlc & goose for database & query development

Docker Image for Deployment

The Dockerfile contained in the repository produces a very lean docker image ready for production. It is a two-stage build process where the final Alpine-based docker image essentially only contains the compiled binary.

If you are interested in running the whole project, databases and brokers and all, locally for development or to demo it keep reading.


Quick Start - Get the project up and running

Clone the repository:

git clone https://github.com/Laelapa/CompanyRegistry.git
cd CompanyRegistry

Set up a full deployment, containerized and local with:

docker compose up

You get:

  • a postgresql with migrations applied,
  • a configured kafka,
  • a kafka ui @ localhost:8081,
  • the Company Registry application,
    • with a swagger ui @ localhost:8080/docs,

everything configured, connected, and ready to go.


To take it down do Ctrl+C

To delete the containers but persist the database & kafka data do:

docker compose down

To completely wipe the volumes too and be ready for a fresh start do:

docker compose down -v

Setup for Local Development

To set up all the peripheral systems (db, kafka, kafka ui) you will run:

docker compose -f compose-peripherals.yaml up

The locally compiled Go program (it's the next step) should connect and communicate with those fine in its default configuration.


To compile the Go program do:

go mod tidy
go build -o company-registry ./cmd/api

Make sure you have the .env file in your project directory, and consider if you want to change anything in the configuration before you compile.


For quick development cycles, to compile & execute without creating a binary file use:

go run ./cmd/api

Setup for Database Development

If you need to touch SQL queries you will also need sqlc to regenerate the Go wrappers:

Install it with go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest and run it simply with sqlc generate from the project's root folder.


If you intend to touch the database layout too then you will need pressly/goose to manage your migrations.

Get it with go install github.com/pressly/goose/v3/cmd/goose@latest

To run it first pull the .env file into your shell's context with source .env so goose can have access to GOOSE_DBSTRING, or you can set it yourself through the commandline. Read more here: https://pressly.github.io/goose/documentation/cli-commands/

To run the up migrations simply run goose up and you're done.

Linting

Run golangci-lint run to execute the linter config defined in the yml

  • or

Set up a github workflow(.github/workflows) to have it check whenever you push/pull code into a specific branch.


Thank you very much for showing interest in my project!

About

A Go REST API designed to demonstrate a layered, configurable, and decoupled architecture.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors