Skip to content

Latest commit

 

History

History
150 lines (100 loc) · 4.75 KB

File metadata and controls

150 lines (100 loc) · 4.75 KB

Solution Structure

Executable Projects

There are four important runnable projects.

Project Role
src/Hosting/Evently.AppHost Aspire orchestration and local infrastructure graph
src/API/Evently.Api Main API host for Users, Events, and Attendance
src/API/Evently.Ticketing.Api Separate API host for Ticketing
src/API/Evently.Gateway YARP gateway in front of the APIs

Shared Projects

The src/Common folder contains the cross-cutting building blocks used by the modules.

Project Purpose
Evently.Common.Domain base domain types such as Entity, Result, errors, domain events
Evently.Common.Application application abstractions such as commands, queries, event handlers, authorization contracts
Evently.Common.Infrastructure database, messaging, auth, caching, Quartz, OpenTelemetry, inbox/outbox support
Evently.Common.Presentation endpoint discovery and API result helpers
Evently.Common.Constants shared constants such as service names

These are technical shared libraries, not business shared state.

Module Layout Pattern

Each business module follows the same internal shape:

Layer Purpose
Domain aggregates, entities, value objects, domain events, business rules
Application commands, queries, handlers, use-case orchestration
Infrastructure EF Core, repositories, inbox/outbox jobs, external integrations
Presentation HTTP endpoints and integration-event entry points
IntegrationEvents contracts that other modules are allowed to depend on

This is one of the most important patterns in the whole repository. Once you understand one module, the others become much easier to read.

Why There Are Two APIs

The system is still one overall application, but the modules are split across two API hosts:

  • Evently.Api hosts Users, Events, and Attendance
  • Evently.Ticketing.Api hosts Ticketing

That split is operational, not conceptual. The real boundaries are the modules themselves.

What The AppHost Does

Evently.AppHost is the local development composition root.

It starts and wires:

  • PostgreSQL
  • MongoDB
  • Redis
  • RabbitMQ
  • Keycloak
  • the main API
  • the ticketing API
  • the gateway

It also injects the runtime values the applications need, including:

  • connection strings
  • broker URI
  • identity provider URLs
  • gateway destination addresses
  • OpenTelemetry export settings

With Aspire, the app projects do not need to hardcode local credentials or local hostnames.

What Each API Does At Startup

Evently.Api

This host:

  • adds shared service defaults and telemetry
  • loads module-specific configuration files for events, users, and attendance
  • registers shared infrastructure
  • registers the three modules
  • exposes OpenAPI and Scalar in development
  • applies EF Core migrations in development
  • maps all discovered module endpoints

Evently.Ticketing.Api

This host does the same thing for the Ticketing module.

Evently.Gateway

The gateway:

  • loads reverse-proxy routes and clusters from configuration
  • validates JWT bearer tokens
  • exposes health endpoints
  • forwards traffic to the main API or the ticketing API

Configuration Shape

Configuration is intentionally split:

  • host-level config lives in each API's appsettings*.json
  • module config lives in modules.<name>.json
  • local runtime values are injected by Aspire

The main API explicitly loads:

  • modules.events.json
  • modules.users.json
  • modules.attendance.json

The ticketing API explicitly loads:

  • modules.ticketing.json

Those module files currently hold things such as inbox and outbox polling intervals and Keycloak-related options for the Users module.

Endpoint Discovery Pattern

Endpoints are not registered one by one in Program.cs.

Instead:

  • each endpoint class implements IEndpoint
  • the module presentation assembly is scanned
  • all discovered endpoints are registered and later mapped automatically

This keeps the entry point thin and keeps each endpoint near its module logic.

Development Startup Sequence

When you run the AppHost locally, the normal sequence is:

  1. Aspire starts infrastructure containers.
  2. Aspire injects connection strings and service URLs into the app projects.
  3. The APIs start, register services, and expose health endpoints.
  4. In development, EF Core migrations are applied automatically.
  5. Quartz starts background inbox and outbox jobs.
  6. MassTransit consumers start listening on RabbitMQ.
  7. The gateway becomes the front door.

In short

The solution has one local orchestration host, two API hosts, one gateway, a set of shared technical libraries, and four business modules that all follow the same Domain/Application/Infrastructure/Presentation split.