Skip to content

kacpersmaga/TicketFlow

Repository files navigation

TicketFlow

A concert ticket ordering system built to learn and get hands-on experience with microservices, gRPC, message queues, and GraphQL. The domain is intentionally simple so the focus stays on the architecture and the technologies — each service is independently deployable and the whole system is designed with Kubernetes in mind as a future deployment target.

The system covers the full lifecycle of a ticket purchase: browsing concerts, placing an order, authentication, and asynchronous notifications.

Architecture Overview

                        ┌─────────────────────────────────────┐
                        │          External Clients           │
                        └──────────────────┬──────────────────┘
                                           │ GraphQL / HTTP
                                ┌──────────▼──────────┐
                                │    Gateway Service   │
                                │   (HotChocolate)     │
                                └──┬───────────────┬───┘
                     gRPC          │               │  HTTP
             ┌────────────────────▼─┐       ┌─────▼────────────┐
             │   Catalog Service    │       │ Identity Service  │
             │   (gRPC + Redis)     │       │ (JWT + Refresh)   │
             └──────────────────────┘       └──────────────────┘
                                      REST
             ┌────────────────────────────────────────────────┐
             │              Ordering Service                  │
             │         (REST API + MassTransit)               │
             └────────────────────────┬───────────────────────┘
                                      │ OrderCreatedEvent
                            ┌─────────▼──────────────┐
                            │    RabbitMQ (AMQP)      │
                            └─────────┬───────────────┘
                                      │
                        ┌─────────────▼──────────────┐
                        │   Notifications Service     │
                        │   (MassTransit Consumer)    │
                        └────────────────────────────┘

        PostgreSQL ×3          Redis              RabbitMQ
     (catalog / ordering    (catalog cache)    (event bus)
       / identity DBs)

All infrastructure and services are orchestrated by .NET Aspire — no Docker Compose required. Each service exposes /health and /alive endpoints and is stateless by design, making the system straightforward to deploy to Kubernetes in the future.

Services

Service Protocol Responsibility
Gateway GraphQL (HotChocolate) Single entry point; composes Catalog (gRPC) and Identity (HTTP)
Catalog gRPC Exposes concert listings with Redis-backed caching (30s TTL)
Identity REST User registration, JWT issuance, single-use refresh token rotation
Ordering REST Order creation, persistence, and event publishing
Notifications Worker (MassTransit) Consumes OrderCreatedEvent from RabbitMQ asynchronously
ServiceDefaults Library Shared cross-cutting concerns: telemetry, health checks, auth, error handling

Tech Stack

Runtime & Framework

  • .NET 10 / C# — nullable reference types, minimal hosting model
  • .NET Aspire 13 — type-safe infrastructure-as-code, built-in service discovery

Communication

  • gRPC (Grpc.AspNetCore 2.76) — strongly-typed internal service calls via Protocol Buffers
  • GraphQL (HotChocolate 15.1) — flexible public API with authorization middleware
  • MassTransit 8.3 + RabbitMQ — decoupled async event publishing and consumption

Data

  • PostgreSQL — three isolated databases (catalog, ordering, identity), managed by EF Core 9
  • Redis — distributed cache for the Catalog service

Security

  • ASP.NET Core Identity + EF Core — user management, password hashing
  • JWT Bearer (HS256) — stateless access tokens with configurable issuer/audience
  • Refresh token rotation — single-use refresh tokens stored in Postgres with revocation tracking

Observability

  • OpenTelemetry 1.15 — distributed tracing, metrics, and structured logging across all services
  • OTLP exporter — pluggable; connects to Aspire dashboard or any OTEL-compatible backend

Resilience

  • Microsoft.Extensions.Http.Resilience — standard retry/circuit-breaker on all HTTP clients
  • Microsoft.Extensions.ServiceDiscovery — DNS-based service resolution via Aspire

Testing

  • xUnit 2.9 — unit tests per service with Moq and EF InMemory
  • Aspire.Hosting.Testing — full-stack integration tests spinning up live containers

CI

  • GitHub Actions — build, unit tests, and integration tests in separate jobs with NuGet caching

Project Structure

TicketFlow/
├── TicketFlow.AppHost/            # .NET Aspire orchestration (all infra + services)
├── TicketFlow.ServiceDefaults/    # Shared extensions: OTel, health, auth, error handling
├── TicketFlow.Events/             # Shared event contracts (OrderCreatedEvent)
│
├── TicketFlow.Catalog/
│   ├── Protos/catalog.proto
│   ├── Services/CatalogService.cs # gRPC implementation
│   ├── Models/CatalogItem.cs
│   └── Data/
│
├── TicketFlow.Ordering/
│   ├── Controllers/OrdersController.cs
│   ├── Models/Order.cs            # Pending → Confirmed → Cancelled
│   └── Data/
│
├── TicketFlow.Identity/
│   ├── Controllers/AuthController.cs
│   ├── Services/TokenService.cs   # JWT + refresh token generation
│   ├── Models/                    # AppUser, RefreshToken, DTOs
│   └── Data/
│
├── TicketFlow.Gateway/
│   ├── GraphQL/Query.cs           # GetConcerts (authorized, via gRPC)
│   ├── GraphQL/Mutation.cs        # Login, Register, RefreshToken
│   ├── Services/IdentityService.cs
│   └── Protos/catalog.proto       # Client-side gRPC definition
│
├── TicketFlow.Notifications/
│   └── Consumers/OrderCreatedConsumer.cs
│
└── tests/
    ├── TicketFlow.Identity.Tests/
    ├── TicketFlow.Ordering.Tests/
    ├── TicketFlow.Gateway.Tests/
    ├── TicketFlow.Notifications.Tests/
    └── TicketFlow.IntegrationTests/   # Full-stack via Aspire test host

Running Locally

Prerequisites: .NET 10 SDK, Docker Desktop

git clone https://github.com/kacpersmaga/TicketFlow.git
cd TicketFlow
dotnet run --project TicketFlow.AppHost

Aspire starts all containers and services automatically. The dashboard (typically http://localhost:18888) shows live logs, traces, and resource health for every component.

Testing

# Unit tests
dotnet test tests/TicketFlow.Identity.Tests
dotnet test tests/TicketFlow.Ordering.Tests
dotnet test tests/TicketFlow.Gateway.Tests
dotnet test tests/TicketFlow.Notifications.Tests

# Integration tests (requires Docker — boots the full Aspire stack)
dotnet test tests/TicketFlow.IntegrationTests

The integration test suite uses a shared AppHostFixture (xUnit collection fixture) to boot the entire distributed system once per session, then runs all tests against live HTTP clients. Tests cover auth flows (register → login → refresh → token revocation), order creation, and service health checks.

CI/CD

GitHub Actions runs on every push and pull request to master:

  1. Build & Unit Tests — restores, builds in Release, runs all unit test projects in parallel with NuGet caching
  2. Integration Tests — runs after unit tests pass; boots the full Aspire stack on the Ubuntu runner (Docker is available by default) with a 20-minute job timeout

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages