Skip to content

samin-z/microservice-test

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

14 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Microservices Learning Project

A polyglot microservices architecture demonstrating synchronous and asynchronous communication patterns using different technology stacks and AWS services via LocalStack.

πŸ—οΈ Architecture Overview

This project consists of two microservices that demonstrate modern microservice patterns:

  • Service 1: Counter API (Kotlin/Spring Boot) - Handles HTTP requests and manages a simple counter
  • Service 2: Message Processor (PHP/Symfony) - Processes events asynchronously and sends email reports

πŸš€ System Flow

Synchronous Communication

Client β†’ GET /counter β†’ Service 1 β†’ PostgreSQL (returns current total)
Client β†’ POST /counter/increment β†’ Service 1 β†’ PostgreSQL (+1) β†’ SQS Message

Asynchronous Communication

SQS Message β†’ Symfony Messenger β†’ MongoDB Document β†’ Hourly Job β†’ SES Email β†’ Clear MongoDB

πŸ› οΈ Technology Stack

Service 1: Counter API

  • Language: Kotlin
  • Framework: Spring Boot 3.x
  • Database: PostgreSQL
  • Features: Spring Data JPA, Spring Web, OpenAPI 3, JUnit 5
  • Purpose: REST API for counter operations with comprehensive testing

Service 2: Message Processor

  • Language: PHP 8.4
  • Framework: Symfony 7.x
  • Message Queue: Symfony Messenger + SQS transport
  • Database: MongoDB
  • Email: AWS SES integration
  • Error Tracking: Sentry integration
  • Purpose: Event collection and hourly email reports

Infrastructure

  • Message Queue: AWS SQS via LocalStack
  • Email Service: AWS SES via LocalStack
  • Containerization: Docker & Docker Compose
  • Local Development: LocalStack for AWS services simulation

πŸ“ Project Structure

microservice-test/
β”œβ”€β”€ counter-api/                    # Service 1 (Kotlin/Spring Boot)
β”‚   β”œβ”€β”€ src/main/kotlin/com/example/counter/
β”‚   β”‚   β”œβ”€β”€ CounterApplication.kt
β”‚   β”‚   β”œβ”€β”€ controller/CounterController.kt
β”‚   β”‚   β”œβ”€β”€ service/CounterService.kt
β”‚   β”‚   β”œβ”€β”€ repository/CounterRepository.kt
β”‚   β”‚   β”œβ”€β”€ entity/Counter.kt
β”‚   β”‚   β”œβ”€β”€ dto/CounterResponseDto.kt
β”‚   β”‚   └── config/
β”‚   β”‚       β”œβ”€β”€ DatabaseConfig.kt
β”‚   β”‚       └── SqsConfig.kt
β”‚   β”œβ”€β”€ src/test/kotlin/com/example/counter/
β”‚   β”‚   β”œβ”€β”€ CounterApplicationTests.kt
β”‚   β”‚   β”œβ”€β”€ controller/CounterControllerTest.kt
β”‚   β”‚   β”œβ”€β”€ service/CounterServiceTest.kt
β”‚   β”‚   └── repository/CounterRepositoryTest.kt
β”‚   β”œβ”€β”€ src/main/resources/
β”‚   β”‚   β”œβ”€β”€ application.yml
β”‚   β”‚   β”œβ”€β”€ application-test.yml
β”‚   β”‚   └── db/migration/V1__create_counter_table.sql
β”‚   β”œβ”€β”€ build.gradle.kts
β”‚   └── Dockerfile
β”œβ”€β”€ message-processor/              # Service 2 (PHP/Symfony)
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ MessageHandler/CounterIncrementHandler.php
β”‚   β”‚   β”œβ”€β”€ Document/CounterEvent.php
β”‚   β”‚   β”œβ”€β”€ Service/EmailService.php
β”‚   β”‚   β”œβ”€β”€ Command/ProcessHourlyEmailCommand.php
β”‚   β”‚   └── Repository/CounterEventRepository.php
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ packages/messenger.yaml
β”‚   β”‚   β”œβ”€β”€ packages/doctrine_mongodb.yaml
β”‚   β”‚   └── services.yaml
β”‚   β”œβ”€β”€ composer.json
β”‚   β”œβ”€β”€ symfony.lock
β”‚   β”œβ”€β”€ .env
β”‚   └── Dockerfile
β”œβ”€β”€ docker-compose.yml
└── README.md

πŸ—„οΈ Database Schemas

PostgreSQL (Service 1) - Simple Counter

CREATE TABLE counter (
    id INTEGER PRIMARY KEY DEFAULT 1,
    value INTEGER NOT NULL DEFAULT 0,
    CONSTRAINT single_row CHECK (id = 1)
);

INSERT INTO counter (id, value) VALUES (1, 0);

MongoDB (Service 2) - Event Collection

// Collection: counter_events
{
  "_id": ObjectId,
  "eventType": "COUNTER_INCREMENT",
  "timestamp": ISODate("2024-01-15T10:30:00Z"),
  "createdAt": ISODate("2024-01-15T10:30:05Z"),
  "metadata": {
    "source": "counter-api",
    "version": "1.0"
  }
}

πŸ”Œ API Endpoints

Service 1: Counter API

  • GET /counter - Returns current counter value: {"value": 42}
  • POST /counter/increment - Increments counter, sends SQS message, returns new value
  • GET /health - Health check endpoint
  • GET /swagger-ui.html - OpenAPI documentation

πŸ“¨ Message Format

SQS Message Structure

{
  "eventType": "COUNTER_INCREMENT",
  "timestamp": "2024-01-15T10:30:00Z",
  "metadata": {
    "source": "counter-api",
    "version": "1.0"
  }
}

πŸ“§ Email Reports

Service 2 generates hourly email reports with the following content:

Subject: Hourly Counter Report - [Date Hour]

Counter Activity Summary:
- Total increments this hour: 15
- Events processed: 15
- Time period: 2024-01-15 10:00-11:00 UTC

First event: 10:05:23 UTC
Last event: 10:58:47 UTC

All events have been processed and cleared from the system.

🎯 Learning Outcomes

Microservice Patterns

  • Database per Service: PostgreSQL vs MongoDB for different use cases
  • Event-driven Architecture: Asynchronous communication via SQS
  • Polyglot Persistence: Different storage solutions for different needs
  • Batch Processing: Hourly aggregation and cleanup operations

Technology Integration

  • Kotlin/Spring Boot: Modern JVM microservice development with comprehensive testing
  • PHP/Symfony: Modern PHP with Symfony Messenger for message handling
  • PostgreSQL: Relational data management with atomic operations
  • MongoDB: Document-based event storage with temporal data
  • LocalStack: AWS services simulation for local development

Communication Patterns

  • Synchronous: REST API calls with proper error handling
  • Asynchronous: SQS message queues with reliable processing
  • Scheduled Tasks: Cron-based email notifications with cleanup
  • Event Sourcing: Store events then process and clean pattern

πŸš€ Getting Started

Prerequisites

  • Docker & Docker Compose
  • JDK 17+ (for Kotlin service)
  • PHP 8.4+ & Composer (for PHP service)
  • LocalStack CLI (optional, for debugging)

Quick Start

# Clone the repository
git clone <repository-url>
cd microservice-test

# Start all services with Docker Compose
docker-compose up -d

# Check service health
curl http://localhost:8080/health  # Counter API
curl http://localhost:8080/counter # Get current counter value

# Increment counter (triggers async processing)
curl -X POST http://localhost:8080/counter/increment

Development Setup

# Service 1 (Kotlin) - Local development
cd counter-api
./gradlew bootRun

# Service 2 (PHP) - Local development
cd message-processor
composer install
symfony server:start

# Run message consumer
php bin/console messenger:consume sqs

# Run hourly email job (manually)
php bin/console app:process-hourly-email

πŸ§ͺ Testing

Service 1 (Kotlin)

cd counter-api

# Run all tests
./gradlew test

# Run integration tests with TestContainers
./gradlew integrationTest

# Generate test coverage report
./gradlew jacocoTestReport

Service 2 (PHP)

cd message-processor

# Run PHPUnit tests
php bin/phpunit

# Run specific test suites
php bin/phpunit tests/MessageHandler/

πŸ“Š Monitoring & Debugging

LocalStack Services

  • SQS Console: http://localhost:4566/_localstack/sqs
  • SES Console: http://localhost:4566/_localstack/ses
  • Health: http://localhost:4566/_localstack/health

Application Logs

# View service logs
docker-compose logs -f counter-api
docker-compose logs -f message-processor

# MongoDB operations
docker-compose exec mongodb mongosh

πŸ”§ Configuration

Environment Variables

  • LOCALSTACK_ENDPOINT: LocalStack endpoint URL
  • SQS_QUEUE_URL: SQS queue URL for message processing
  • DATABASE_URL: PostgreSQL connection string
  • MONGODB_URL: MongoDB connection string
  • SES_FROM_EMAIL: Email sender address for notifications
  • SENTRY_DSN: Sentry DSN for error tracking (optional)
  • SENTRY_TRACES_SAMPLE_RATE: Performance monitoring sample rate (0.0-1.0, default: 0.0)
  • SENTRY_PROFILES_SAMPLE_RATE: Profiling sample rate (0.0-1.0, default: 0.0)
  • SENTRY_RELEASE: Release version for tracking deployments (optional)
  • SENTRY_SERVER_NAME: Server name identifier (default: message-processor)

Sentry Error Tracking

The Message Processor service includes Sentry integration for error tracking and monitoring. To enable Sentry:

  1. Get your Sentry DSN:

    • Sign up at sentry.io
    • Create a new project (PHP/Symfony)
    • Copy your DSN from the project settings
  2. Configure environment variables:

    # In your .env file or docker-compose.yml
    SENTRY_DSN=https://your-key@sentry.io/your-project-id
    SENTRY_TRACES_SAMPLE_RATE=0.1  # 10% of transactions
    SENTRY_RELEASE=1.0.0  # Optional: track releases
  3. Sentry automatically captures:

    • Unhandled exceptions in console commands
    • Errors in message handlers
    • AWS SES exceptions with context
    • Symfony Messenger failures
  4. Manual error capture (already implemented):

    // In your services, Sentry Hub is automatically injected
    if ($this->sentryHub !== null) {
        $this->sentryHub->captureException($exception, [
            'tags' => ['service' => 'email'],
            'contexts' => ['custom' => 'data'],
        ]);
    }

πŸŽ“ Educational Value

This project demonstrates:

  • Polyglot Microservices: Different languages solving different problems
  • Event-driven Architecture: Loose coupling through messaging
  • Different Data Models: SQL for state, NoSQL for events
  • Comprehensive Testing: Unit, integration, and contract testing
  • Modern Frameworks: Latest versions of Spring Boot and Symfony
  • Cloud-native Patterns: AWS services integration via LocalStack
  • Production Readiness: Proper logging, health checks, and monitoring

⏱️ Implementation Timeline

  • Service 1 + Tests: 4-5 hours
  • Service 2 + Symfony: 3-4 hours
  • Integration & Docker: 1-2 hours
  • Total: 8-11 hours

Perfect for weekend learning or spread across multiple evening sessions!

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Implement changes with tests
  4. Submit a pull request

πŸ“ License

This project is for educational purposes. Feel free to use and modify as needed for learning microservices architecture.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors