Skip to main content

Prerequisites

Quick Setup with Docker Compose

The easiest way to get started is using our Docker Compose setup:
# Clone the repository
git clone https://github.com/flexprice/flexprice
cd flexprice

# Set up the complete development environment
make dev-setup
This command will:
  1. Start all required infrastructure (PostgreSQL, Kafka, ClickHouse, Temporal)
  2. Build the Flexprice application image
  3. Run database migrations and initialize Kafka
  4. Start all Flexprice services (API, Consumer, Worker)

Accessing Services

Once setup is complete, you can access:

Useful Commands

# Restart only the Flexprice services
make restart-flexprice

# Stop all services
make down

# Clean everything and start fresh
make clean-start

# Build the Flexprice image separately
make build-image

# Start only the Flexprice services
make start-flexprice

Running Without Docker

If you prefer to run the application directly:
# Start the required infrastructure
docker compose up -d postgres kafka clickhouse temporal temporal-ui

# Run the application locally
go run cmd/server/main.go

Project Structure

Flexprice follows a clean architecture pattern with clear separation of concerns:
internal/
├── domain/
│   ├── events/
│   │   ├── model.go         # Core event domain model
│   │   ├── repository.go    # Repository interface
│   └── meter/
│       ├── model.go         # Core meter domain model
│       ├── repository.go    # Repository interface
├── repository/
│   ├── clickhouse/
│   │   └── event.go
│   ├── postgres/
│   │   └── meter.go
│   └── factory.go          # Factory for creating repositories
├── service/
│   ├── event.go            # Event service implementation
│   └── meter.go            # Meter service implementation
├── api/
│   ├── v1/
│   │   ├── events.go       # Event API implementation
│   │   └── meter.go        # Meter API implementation
│   ├── dto/
│   │   ├── event.go
│   │   └── meter.go
│   └── router.go           # API router implementation
└── cmd/server/
    └── main.go             # Server application entry point
└── docs/
    └── ...                 # Documentation files
    ├── swagger
    │   ├── swagger.yaml    # Generated Swagger API specifications

Layer Responsibilities

Domain Layer

  • Contains core business logic and domain models
  • Defines interfaces for repositories
  • No dependencies on external packages or other layers

Repository Layer

  • Implements data access interfaces defined in domain
  • Handles database operations

Service Layer

  • Orchestrates business operations
  • Implements business logic
  • Uses repository interfaces for data access
  • Handles cross-cutting concerns

API Layer

  • Handles HTTP requests/responses
  • Converts between DTOs and domain models
  • No business logic, only request validation and response formatting

Key Design Principles

  1. Dependency Rule: Dependencies only point inward. Domain layer has no outward dependencies.
  2. Interface Segregation: Repository interfaces are defined in domain layer but implemented in repository layer.
  3. Dependency Injection: Using fx for clean dependency management.
  4. Separation of Concerns: Each layer has a specific responsibility.

Example Flow

For an event ingestion:
  1. API Layer (/api/v1/events.go) receives HTTP request
  2. Converts DTO to domain model
  3. Calls service layer
  4. Service layer (/service/event_service.go) handles business logic
  5. Repository layer persists data
  6. Response flows back through the layers

Adding New Features

  1. Define domain models and interfaces in domain layer
  2. Implement repository interfaces if needed
  3. Add service layer logic
  4. Create API handlers and DTOs
  5. Register routes and dependencies

Testing

We use testutil package to create test data and setup test environment.

Testing Guidelines

Unit Tests

  • Each package should have corresponding *_test.go files
  • Use table-driven tests when testing multiple scenarios
  • Mock external dependencies using interfaces
  • Aim for >80% test coverage for critical paths

Integration Tests

  • Place integration tests in a separate integration package
  • Use test containers for database tests
  • Integration tests should use the same config structure as production

Running Tests

Use the following make commands:
make test             # Run all tests
make test-verbose     # Run all tests with verbose output
make test-coverage    # Run all tests and generate coverage report

Development Credentials

PostgreSQL

  • Host: localhost
  • Port: 5432
  • Database: flexprice
  • Username: flexprice
  • Password: flexprice123

ClickHouse

  • Host: localhost
  • Port: 9000
  • Database: flexprice
  • Username: flexprice
  • Password: flexprice123

Kafka

API Documentation

The API documentation is available in OpenAPI 3.0 format at docs/swagger/swagger-3-0.json.

Setting up Postman Collection

  1. Open Postman
  2. Click on “Import” in the top left
  3. Select “Import File”
  4. Choose docs/swagger/swagger-3-0.json
  5. Click “Import”
  6. Create a new environment for local development:
    • Name: Local
    • Variable: baseUrl
    • Initial Value: http://localhost:8080/v1
    • Current Value: http://localhost:8080/v1
    • Variable: apiKey
    • Initial Value: 0cc505d7b917e0b1f25ccbea029dd43f4002edfea46b7f941f281911246768fe
    • Current Value: 0cc505d7b917e0b1f25ccbea029dd43f4002edfea46b7f941f281911246768fe

Troubleshooting

Docker Issues

  1. Ensure Docker is running properly:
docker info
  1. Check the status of all containers:
docker compose ps
  1. View logs for a specific service:
docker compose logs [service_name]

Database Connection Issues

  1. Check database logs:
docker compose logs postgres
docker compose logs clickhouse
  1. Verify the database is running:
docker compose ps postgres
docker compose ps clickhouse

Kafka Issues

  1. Verify Kafka is running:
docker compose logs kafka
  1. Check topic list:
docker compose exec kafka kafka-topics --bootstrap-server kafka:9092 --list
  1. View Kafka UI at http://localhost:8084

Additional Resources