Skip to content

Repository files navigation


Elaris Marketplace
Elaris Marketplace

🐾 Elaris Marketplace — A Pixel Pet Trading System built on microservice architecture for learning production-ready distributed systems (CQRS, Saga, Outbox, Observability, etc.)

OverviewKey FeaturesArchitectureTech StackLocal DevelopmentTesting & ObservabilityDeployment & Roadmap


🧱 Project Overview

Elaris Marketplace is a microservice learning project simulating a virtual marketplace where users can buy, sell, and trade pixel pets.
The primary goal: hands-on practice with real-world microservice architectures, applying industry-standard patterns for production environments such as CQRS, Outbox, Saga Orchestration, Observability, and Resilience.

  • 🎯 Master production-grade patterns (API gateway, messaging, distributed tracing, saga)
  • 🧩 Highly scalable and decoupled distributed architecture
  • 🧠 An ideal environment for learning and showcasing modern .NET microservices

🔑 Key Features

  • 🔐 Authentication & Authorization: Duende IdentityServer, JWT RS256, refresh token rotation
  • 🐉 Product Management: CRUD với MongoDB, filter/sort/paging
  • 🛒 Basket Service: Redis-based, atomic operations, TTL
  • 📦 Inventory Management: Postgres + gRPC + reservation logic
  • 🧾 Ordering System: CQRS, Outbox, Read model, MassTransit Saga
  • 💳 Payment Flow: Simulated preauthorize & capture
  • 🪄 Observability: OpenTelemetry, Prometheus, Grafana, Loki
  • ⚙️ Resilience: Polly retry, circuit breaker
  • 🚦 Gateway (YARP): Rate limiting, caching, structured logging

🏗️ Architecture

Architecture

     [ Gateway (YARP) ]
          ↓
 ┌────────────────────────────┐
 │ Identity (Duende)          │
 │ ProductService (MongoDB)   │
 │ Basket (Redis)             │
 │ Inventory (Postgres/gRPC)  │
 │ Ordering (CQRS + Saga)     │
 │ Payment (Simulated)        │
 └────────────────────────────┘
         ↕ RabbitMQ (MassTransit)
        ↳ Observability (OTel, Grafana)

🧰 Tech Stack

Layer Technology
API Gateway YARP (.NET 8)
Auth Duende IdentityServer
Messaging RabbitMQ + MassTransit
Databases MongoDB, PostgreSQL, Redis
Saga Orchestration MassTransit Saga
Observability OpenTelemetry, Prometheus, Grafana, Loki
CI/CD GitHub Actions + Helm + Kubernetes

⚙️ Local Development

Prerequisites

  • Docker & Docker Compose
  • .NET 8 SDK

Setup & Run

# Clone the repository
git clone https://github.com/your-username/elaris-marketplace.git
cd elaris-marketplace

# Start dependencies
docker compose up -d

# Run services
dotnet run --project Services.Identity
dotnet run --project Services.ProductService
dotnet run --project Services.InventoryService
dotnet run --project Services.OrderService
dotnet run --project Services.PaymentService
dotnet run --project Gateway

# Access URLs
Gateway API: http://localhost:8000

🧪 Testing & Observability

Testing Strategy

Type Description
Unit Business logic
Integration Mongo, Postgres, RabbitMQ (TestContainers)
Contract Event schema validation
E2E Simulate purchase flow
Chaos RabbitMQ/network failures
Load k6 / Locust testing

Observability Stack

  • Tracing: OpenTelemetry → Grafana Tempo / Jaeger
  • Metrics: Prometheus
  • Logs: Serilog → Loki
  • Dashboards: Grafana panels per service
  • Alerts: Prometheus Alertmanager

🧑‍💻 Contributors

Name Role
Trần Văn Nhanh Architect / Developer
(You?) Join via PR or Issue!

Folder Structure 28/11/2025. └───src │ Elaris.sln │ inventory.proto │ InventoryGrpcService.cs │ ├───ApiGateway │ │ ApiGateway.csproj │ │ ApiGateway.csproj.user │ │ ApiGateway.http │ │ appsettings.Development.json │ │ appsettings.json │ │ Dockerfile │ │ Program.cs │ │ │ ├───Middlewares │ │ LoggingMiddleware.cs │ │ SwaggerAggregatorMiddleware.cs │ │ │ └───Properties │ launchSettings.json │ ├───BuildingBlocks │ └───Contracts │ │ BuildingBlocks.Contracts.csproj │ │ │ ├───Commands │ │ OrderProcessingCommands.cs │ │ │ ├───Events │ │ BasketEvent.cs │ │ InventoryEvent.cs │ │ OrderEvent.cs │ │ PaymentEvent.cs │ │ ProductEvent.cs │ ├───BuildingBlocks.GrpcContracts │ │ BuildingBlocks.GrpcContracts.csproj │ │ │ └───proto │ inventory.proto │ payment.proto │ ├───BuildingBlocks.Infrastucture │ │ BuildingBlocks.Infrastucture.csproj │ │ │ └───Authentication │ JwtAuthenticationHelper.cs │ ├───GrpcContracts │ GrpcContracts.csproj │ ├───Services.BasketService │ ├───Services.BasketService.API │ │ │ appsettings.Development.json │ │ │ appsettings.json │ │ │ Dockerfile │ │ │ Program.cs │ │ │ Services.BasketService.API.csproj │ │ │ Services.BasketService.API.csproj.user │ │ │ Services.BasketService.API.http │ │ │ │ │ ├───Extensions │ │ │ HttpContextExtensions.cs │ │ │ │ │ └───Properties │ │ launchSettings.json │ │ │ ├───Services.BasketService.Application │ │ │ Services.BasketService.Application.csproj │ │ │ │ │ ├───Interfaces │ │ │ IBasketRepository.cs │ │ │ ICatalogServiceClient.cs │ │ │ │ │ ├───Models │ │ │ Basket.cs │ │ │ BasketDto.cs │ │ │ BasketItem.cs │ │ │ ProductDto.cs │ │ │ │ │ └───Validators │ │ BasketItemValidator.cs │ │ │ └───Services.BasketService.Infrastructure │ │ Services.BasketService.Infrastructure.csproj │ │ │ ├───Monitoring │ │ RedisMetrics.cs │ │ │ ├───Repositories │ │ BasketRepository.cs │ │ │ └───Services │ CatalogServiceClient.cs │ ├───Services.CatalogService │ │ appsettings.Development.json │ │ appsettings.json │ │ Dockerfile │ │ Program.cs │ │ Services.CatalogService.csproj │ │ Services.CatalogService.csproj.user │ │ Services.CatalogService.http │ │ │ ├───Config │ │ MinIOOptions.cs │ │ │ ├───Data │ │ MongoContext.cs │ │ SoftDeleteCollection.cs │ │ │ ├───Extensions │ │ HttpContextExtensions.cs │ │ │ ├───Features │ │ └───Products │ │ ├───ApproveProduct │ │ │ ApproveProductEndpoints.cs │ │ ├───CreateProduct │ │ │ CreateProductEndpoint.cs │ │ ├───DeleteProduct │ │ │ DeleteProductEndpoint.cs │ │ ├───GetAllProducts │ │ │ GetAllProductsEndpoint.cs │ │ ├───GetMyProducts │ │ │ GetMyProductsEndpoint.cs │ │ ├───GetPendingProducts │ │ │ GetPendingProductsEndpoint.cs │ │ ├───GetProduct │ │ │ GetProductEndpoint.cs │ │ ├───GetProducts │ │ │ GetProductsEndpoint.cs │ │ │ GetProductsQuery.cs │ │ ├───RejectProduct │ │ │ RejectProductEndpoint.cs │ │ └───UpdateProduct │ │ UpdateProductEndpoint.cs │ │ │ ├───Models │ │ CreateProductRequest.cs │ │ Product.cs │ │ UpdateProductRequest.cs │ │ │ ├───Properties │ │ launchSettings.json │ │ │ └───Services │ FileStorageService.cs │ ├───Services.IdentityService │ │ appsettings.Development.json │ │ appsettings.json │ │ Dockerfile │ │ IdentityServerConfig.cs │ │ Program.cs │ │ Services.IdentityService.csproj │ │ Services.IdentityService.csproj.user │ │ Services.IdentityService.http │ │ │ ├───Controllers │ │ AuthController.cs │ │ UserController.cs │ │ │ ├───Data │ │ │ AppDbContext.cs │ │ │ SeedData.cs │ │ │ │ │ ├───Entities │ │ │ PayoutRequest.cs │ │ │ │ │ └───Migrations │ │ 20251021074357_InitialIdentity.cs │ │ 20251021074357_InitialIdentity.Designer.cs │ │ 20251022043642_AddRefreshToken.cs │ │ 20251022043642_AddRefreshToken.Designer.cs │ │ 20251125083847_AddUserExtendedFields.cs │ │ 20251125083847_AddUserExtendedFields.Designer.cs │ │ AppDbContextModelSnapshot.cs │ │ │ ├───DTOs │ │ UserDtos.cs │ │ │ ├───Extensions │ │ HttpContextExtensions.cs │ │ │ ├───Properties │ │ launchSettings.json │ │ │ └───Security │ Argon2PasswordHasher.cs │ RsaKeyProvider.cs │ ├───Services.InventoryService │ ├───Services.InventoryService.API │ │ │ appsettings.Development.json │ │ │ appsettings.json │ │ │ DesignTimeDbContextFactory.cs │ │ │ Dockerfile │ │ │ Program.cs │ │ │ Services.InventoryService.API.csproj │ │ │ Services.InventoryService.API.csproj.user │ │ │ Services.InventoryService.API.http │ │ │ │ │ ├───Controllers │ │ │ InventoryController.cs │ │ │ │ │ ├───Extensions │ │ │ HttpContextExtensions.cs │ │ │ │ │ ├───Grpc │ │ │ InventoryGrpcService.cs │ │ │ │ │ └───Properties │ │ launchSettings.json │ │ │ ├───Services.InventoryService.Application │ │ │ AssemblyReference.cs │ │ │ Services.InventoryService.Application.csproj │ │ │ │ │ ├───Common │ │ │ ├───Mappings │ │ │ │ InventoryMappingConfig.cs │ │ │ │ │ │ │ └───Models │ │ │ PaginatedList.cs │ │ │ │ │ ├───DTOs │ │ │ InventoryItemDto.cs │ │ │ OrderDto.cs │ │ │ ProductDto.cs │ │ │ │ │ ├───Interfaces │ │ │ ICatalogServiceClient.cs │ │ │ IInventoryRepository.cs │ │ │ IInventoryService.cs │ │ │ IUnitOfWork.cs │ │ │ │ │ ├───Inventory │ │ │ ├───Commands │ │ │ │ ├───BulkUpdateInventory │ │ │ │ │ BulkUpdateInventoryCommand.cs │ │ │ │ │ BulkUpdateInventoryCommandHandler.cs │ │ │ │ ├───ConfirmStockDeduction │ │ │ │ │ ConfirmStockDeductionCommand.cs │ │ │ │ │ ConfirmStockDeductionCommandHandler.cs │ │ │ │ ├───CreateOrUpdateInventoryItem │ │ │ │ │ CreateOrUpdateInventoryItemCommand.cs │ │ │ │ │ CreateOrUpdateInventoryItemCommandHandler.cs │ │ │ │ ├───DecreaseStock │ │ │ │ │ DecreaseStockCommand.cs │ │ │ │ │ DecreaseStockCommandHandler.cs │ │ │ │ ├───IncreaseStock │ │ │ │ │ IncreaseStockCommand.cs │ │ │ │ │ IncreaseStockCommandHandler.cs │ │ │ │ ├───ReleaseStock │ │ │ │ │ ReleaseStockCommand.cs │ │ │ │ │ ReleaseStockCommandHandler.cs │ │ │ │ ├───ReserveStock │ │ │ │ │ ReserveStockCommand.cs │ │ │ │ │ ReserveStockCommandHandler.cs │ │ │ │ └───SetLowStockThreshold │ │ │ │ SetLowStockThresholdCommand.cs │ │ │ │ SetLowStockThresholdCommandHandler.cs │ │ │ │ │ │ │ └───Queries │ │ │ ├───CheckProductsAvailability │ │ │ │ CheckProductsAvailabilityQuery.cs │ │ │ │ CheckProductsAvailabilityQueryHandler.cs │ │ │ ├───GetInventoryByProductId │ │ │ │ GetInventoryByProductIdQuery.cs │ │ │ │ GetInventoryByProductIdQueryHandler.cs │ │ │ ├───GetInventoryHistory │ │ │ │ GetInventoryHistoryQuery.cs │ │ │ │ GetInventoryHistoryQueryHandler.cs │ │ │ ├───GetInventoryList │ │ │ │ GetInventoryListQuery.cs │ │ │ │ GetInventoryListQueryHandler.cs │ │ │ ├───GetInventoryStatistics │ │ │ │ GetInventoryStatisticsQuery.cs │ │ │ │ GetInventoryStatisticsQueryHandler.cs │ │ │ └───GetLowStockItems │ │ │ GetLowStockItemsQuery.cs │ │ │ GetLowStockItemsQueryHandler.cs │ │ │ │ ├───Services.InventoryService.Domain │ │ │ Services.InventoryService.Domain.csproj │ │ │ │ │ └───Entities │ │ InventoryHistory.cs │ │ InventoryItem.cs │ │ StockReservation.cs │ │ │ └───Services.InventoryService.Infrastructure │ │ Services.InventoryService.Infrastructure.csproj │ │ │ ├───BackgroundServices │ │ ExpiredReservationCleanupService.cs │ │ ReservationTimeoutService.cs │ │ │ ├───Consumers │ │ ConfirmInventoryConsumer.cs │ │ ProductCreatedConsumer.cs │ │ ReleaseInventoryConsumer.cs │ │ ReserveInventoryConsumer.cs │ │ │ ├───Extensions │ │ DependencyInjection.cs │ │ │ ├───Migrations │ │ 20251030083514_InitialInventory.cs │ │ 20251030083514_InitialInventory.Designer.cs │ │ 20251113045114_AddReservedQuantity.cs │ │ 20251113045114_AddReservedQuantity.Designer.cs │ │ 20251127102506_AddInventoryExtendedEntitiesAndFields.cs │ │ 20251127102506_AddInventoryExtendedEntitiesAndFields.Designer.cs │ │ InventoryDbContextModelSnapshot.cs │ │ │ ├───Persistence │ │ InventoryDbContext.cs │ │ │ ├───Repositories │ │ InventoryRepository.cs │ │ UnitOfWork.cs │ │ │ └───Services │ CatalogServiceClient.cs │ InventoryService.cs │ ├───Services.InventoryService.Grpc │ │ appsettings.Development.json │ │ appsettings.json │ │ Program.cs │ │ Services.InventoryService.Grpc.csproj │ │ Services.InventoryService.Grpc.csproj.user │ │ │ ├───Properties │ │ launchSettings.json │ │ │ ├───Protos │ │ inventory.proto │ │ │ └───Services │ InventoryGrpcService.cs │ ├───Services.InventoryService.SDK │ │ ServiceCollectionExtension.cs │ │ Services.InventoryService.SDK.csproj │ └───Services.OrderService ├───Services.OrderService.API │ │ appsettings.Development.json │ │ appsettings.json │ │ DesignTimeDbContextFactory.cs │ │ Dockerfile │ │ Program.cs │ │ Services.OrderService.API.csproj │ │ Services.OrderService.API.csproj.user │ │ Services.OrderService.API.http │ │ │ ├───Controllers │ │ OrdersController.cs │ │ │ ├───Extensions │ │ HttpContextExtensions.cs │ │ │ ├───Middleware │ │ ExceptionMiddleware.cs │ │ │ └───Properties │ launchSettings.json

🪪 License

MIT License © 2025 — Elaris Marketplace Team

About

Elaris Marketplace — A virtual marketplace built with .NET microservices: YARP Gateway, Duende Identity, MongoDB, Redis, Postgres, RabbitMQ, MassTransit Saga, CQRS & Outbox. Learn real e-commerce flows, distributed transactions, and observability with OpenTelemetry.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages