Skip to content

Latest commit

 

History

History
263 lines (202 loc) · 9.48 KB

File metadata and controls

263 lines (202 loc) · 9.48 KB

Library Service Documentation

🇷🇺 Документация на русском

Overview

The Library service is a Go-based application for managing books and authors through a REST-to-gRPC API, now integrated with a PostgreSQL database and an outbox pattern for asynchronous event handling. Initially developed with an in-memory storage solution, this project has evolved to incorporate persistent storage and transactional consistency, with plans for further enhancements.

The implementation adheres to the go-clean-template structure and follows specific technological and testing requirements outlined in the assignments.


Features

  • Book Management:

    • Add a new book (POST /v1/library/book).
    • Update an existing book (PUT /v1/library/book).
    • Retrieve book information by ID (GET /v1/library/book/{id}).
  • Author Management:

    • Register a new author (POST /v1/library/author).
    • Update author information (PUT /v1/library/author).
    • Retrieve author information by ID (GET /v1/library/author/{id}).
    • Retrieve all books by a specific author (GET /v1/library/author_books/{author_id}).
  • Validation:

    • Book and author IDs are UUIDs, generated automatically by the database (uuid_generate_v4()).
    • Author names must match the regex ^[A-Za-z0-9]+( [A-Za-z0-9]+)*$ and have a length between 1 and 512 characters.
    • Additional validation aligns with tests and common sense.
  • Database Integration:

    • PostgreSQL database with tables for author, book, and author_book (many-to-many relationship).
    • Automatic timestamp updates via triggers (created_at, updated_at).
    • Indexes on author.name and book.name for efficient queries.
    • Cascade deletion in author_book to maintain consistency.
  • Outbox Pattern:

    • Asynchronous event handling for book and author creation.
    • outbox table stores events with statuses (CREATED, IN_PROGRESS, SUCCESS).
    • Sends POST requests to configured URLs (OUTBOX_AUTHOR_SEND_URL, OUTBOX_BOOK_SEND_URL) with AuthorID or BookID.
  • Transactional Consistency:

    • Uses pgx for database operations with transaction support.
    • Implements a Transactor interface for atomic operations.
  • Logging: Structured logging with zap.

  • Signal Handling: Graceful shutdown on SIGINT and SIGTERM.


Project Structure

The project follows the go-clean-template structure. Key components include:


API Specification

The API, defined in library.proto, includes created_at and updated_at fields for books. Endpoints:

Method Endpoint Description
POST /v1/library/book Add a new book
PUT /v1/library/book Update an existing book
GET /v1/library/book/{id} Get book details by ID
POST /v1/library/author Register a new author
PUT /v1/library/author Update author information
GET /v1/library/author/{id} Get author details by ID
GET /v1/library/author_books/{author_id} Get all books by an author

View the API in Swagger Editor using swagger.json.


Database Schema

The PostgreSQL database includes the following tables:

  • author:

    • id: UUID (primary key, auto-generated).
    • name: Text (validated, indexed).
    • created_at, updated_at: Timestamps (updated via trigger).
  • book:

    • id: UUID (primary key, auto-generated).
    • name: Text (indexed).
    • created_at, updated_at: Timestamps (updated via trigger).
  • author_book:

    • author_id, book_id: UUIDs (composite primary key, foreign keys with ON DELETE CASCADE).
    • Index on book_id for efficient queries.
  • outbox:

    • idempotency_key: Text (primary key).
    • data: JSONB (event payload).
    • status: Enum (CREATED, IN_PROGRESS, SUCCESS).
    • kind: Integer (event type).
    • created_at, updated_at: Timestamps.

Migrations are stored in db/migrations and applied via migrate.go.


Technology Stack


Environment Variables

The service uses the following environment variables:

Variable Description
GRPC_PORT gRPC server port
GRPC_GATEWAY_PORT REST-to-gRPC gateway port
POSTGRES_HOST PostgreSQL host
POSTGRES_PORT PostgreSQL port
POSTGRES_DB Database name
POSTGRES_USER Database user
POSTGRES_PASSWORD Database password
POSTGRES_MAX_CONN Maximum database connections
OUTBOX_ENABLED Enable/disable outbox
OUTBOX_WORKERS Number of outbox workers
OUTBOX_BATCH_SIZE Batch size for outbox processing
OUTBOX_WAIT_TIME_MS Wait time between outbox batches (ms)
OUTBOX_IN_PROGRESS_TTL_MS TTL for in-progress outbox messages (ms)
OUTBOX_AUTHOR_SEND_URL URL for author event POST requests
OUTBOX_BOOK_SEND_URL URL for book event POST requests

Example PostgreSQL URL:

postgres://user:password@host:port/dbname?sslmode=disable&pool_max_conns=10

Development Setup

Prerequisites

  • Go (latest stable version).
  • protoc for gRPC code generation.
  • Docker for PostgreSQL.
  • WSL (recommended for Windows).
  • make.

Installation

  1. Clone the repository:

    git clone <repository-url>
    cd library
  2. Install dependencies:

    go mod tidy
  3. Generate code and mocks:

    make generate

Running PostgreSQL

  1. Start the database:

    docker-compose up -d
  2. Apply migrations:

    go run db/migrations/migrate.go
  3. Manage containers:

    docker ps -a                    # List containers
    docker stop <container-id>      # Stop container
    docker rm <container-id>        # Remove container
    docker volume ls                # List volumes
    docker volume rm <volume-name>  # Remove volume

Running the Service

  1. Set environment variables:

    export GRPC_PORT=50051
    export GRPC_GATEWAY_PORT=8080
    export POSTGRES_HOST=localhost
    export POSTGRES_PORT=5432
    export POSTGRES_DB=library
    export POSTGRES_USER=postgres
    export POSTGRES_PASSWORD=postgres
    export POSTGRES_MAX_CONN=10
    export OUTBOX_ENABLED=true
    export OUTBOX_WORKERS=2
    export OUTBOX_BATCH_SIZE=10
    export OUTBOX_WAIT_TIME_MS=1000
    export OUTBOX_IN_PROGRESS_TTL_MS=60000
    export OUTBOX_AUTHOR_SEND_URL=http://example.com/author
    export OUTBOX_BOOK_SEND_URL=http://example.com/book
  2. Build and run:

    make build
    go run cmd/library/main.go

Testing

Run all tests:

make test

Run linter:

make lint

Run full cycle (lint + tests):

make all

Update integration tests:

make update

References