This commit introduces a major refactoring of the build system and the core infrastructure modules. The primary goal is to establish a strict "Single Source of Truth" for all dependencies using Gradle Version Catalogs and to create a clean, maintainable, and scalable foundation for all current and future services. ### 1. Centralized Dependency Management (`libs.versions.toml`) - **Established Single Source of Truth:** All dependency versions are now exclusively managed in `gradle/libs.versions.toml`. Hardcoded versions have been removed from all build scripts. - **Introduced Gradle Bundles:** To simplify module dependencies, several bundles have been created (e.g., `testing-jvm`, `redis-cache`, `spring-cloud-gateway`, `monitoring-client`). This drastically reduces boilerplate in the `build.gradle.kts` files and improves readability. - **Cleaned up Aliases:** All library and plugin aliases have been standardized for consistency. ### 2. Infrastructure Module Refactoring All infrastructure modules (`core`, `platform`, `auth`, `cache`, `event-store`, `messaging`, `monitoring`, `gateway`) have been refactored to align with the new dependency management strategy. - **Simplified Build Scripts:** The `build.gradle.kts` for each module now uses the new bundles and aliases, making them significantly cleaner and easier to understand. - **Consistent Structure:** The architecture of each module now clearly follows the Port-Adapter pattern where applicable (e.g., `cache-api`/`redis-cache`). - **Standardized `platform-bom`:** The project's own Bill of Materials (`platform-bom`) now also includes the Spring Cloud BOM, ensuring version consistency for all Spring-related dependencies. ### 3. Added Infrastructure Documentation To improve onboarding and architectural understanding, a dedicated `README-*.md` file has been created for each refactored infrastructure module: - `README-CORE.md` - `README-PLATFORM.md` - `README-INFRA-AUTH.md` - `README-INFRA-CACHE.md` - `README-INFRA-EVENT-STORE.md` - `README-INFRA-MESSAGING.md` - `README-INFRA-MONITORING.md` - `README-INFRA-GATEWAY.md` These documents explain the purpose, architecture, and usage of each component within the system. This lays the groundwork for our "Tracer Bullet" development approach.
71 lines
3.9 KiB
Markdown
71 lines
3.9 KiB
Markdown
# Infrastructure/Event-Store Module
|
|
|
|
## Überblick
|
|
|
|
Das **Event-Store-Modul** ist eine kritische Komponente der Infrastruktur, die für die Persistenz und Veröffentlichung von Domänen-Events zuständig ist. Es bildet die technische Grundlage für **Event Sourcing** und eine allgemeine **event-getriebene Architektur**. Anstatt nur den aktuellen Zustand einer Entität zu speichern, speichert der Event Store die gesamte Kette von Ereignissen (Events), die zu diesem Zustand geführt haben.
|
|
|
|
## Architektur: Port-Adapter-Muster
|
|
|
|
Wie schon das Cache-Modul, folgt auch der Event Store streng dem **Port-Adapter-Muster**, um eine maximale Entkopplung von der konkreten Speichertechnologie zu erreichen.
|
|
|
|
|
|
infrastructure/event-store/
|
|
├── event-store-api/ # Der "Port": Definiert die Event-Store-Schnittstelle
|
|
└── redis-event-store/ # Der "Adapter": Implementiert die Schnittstelle mit Redis Streams
|
|
|
|
|
|
### `event-store-api`
|
|
|
|
Dieses Modul ist der **abstrakte "Port"** der Architektur. Es definiert den Vertrag, wie der Rest der Anwendung mit dem Event Store interagiert.
|
|
|
|
* **Zweck:** Definiert Interfaces wie `EventStore` (zum Speichern und Laden von Event-Streams) und `EventPublisher` (zum Veröffentlichen von Events an interessierte Listener). Es ist eng mit den `DomainEvent`-Definitionen aus dem `:core:core-domain`-Modul verknüpft.
|
|
* **Vorteil:** Die Fach-Services (z.B. `members-application`) sind vollständig von der Implementierung des Event Stores entkoppelt. Sie wissen nicht, ob die Events in Redis, Kafka oder einer relationalen Datenbank gespeichert werden.
|
|
|
|
### `redis-event-store`
|
|
|
|
Dieses Modul ist der **konkrete "Adapter"**, der die in `event-store-api` definierten Schnittstellen implementiert.
|
|
|
|
* **Zweck:** Stellt eine Implementierung des `EventStore` bereit, die **Redis Streams** als zugrunde liegenden Datenspeicher verwendet. Redis Streams sind eine leistungsstarke Datenstruktur, die sich ideal für die Implementierung eines append-only Logs eignet, wie es für einen Event Store benötigt wird.
|
|
* **Technologie:** Nutzt Spring Data Redis und den Lettuce-Client für die performante Kommunikation mit Redis. Die Domänen-Events werden vor der Speicherung mittels Jackson in ein JSON-Format serialisiert.
|
|
* **Vorteil:** Kapselt die gesamte Redis-spezifische Logik. Ein zukünftiger Wechsel zu einem anderen Event-Store-System (z.B. Apache Kafka) würde nur den Austausch dieses einen Moduls erfordern.
|
|
|
|
## Verwendung in anderen Modulen
|
|
|
|
Ein Anwendungs-Service, der Event Sourcing verwendet, interagiert wie folgt mit dem Modul:
|
|
|
|
1. **Abhängigkeit deklarieren:** Das Service-Modul (z.B. `members-application`) fügt eine `implementation`-Abhängigkeit zu `:infrastructure:event-store:redis-event-store` in seiner `build.gradle.kts` hinzu.
|
|
|
|
2. **Interface injizieren:** Im Service-Code wird nur das `EventStore`-Interface aus der `event-store-api` injiziert.
|
|
|
|
```kotlin
|
|
// In einem Use Case oder Application Service
|
|
@Service
|
|
class MemberApplicationService(
|
|
private val eventStore: EventStore, // Nur das Interface wird verwendet!
|
|
private val eventPublisher: EventPublisher
|
|
) {
|
|
fun registerNewMember(command: RegisterMemberCommand): Member {
|
|
// 1. Geschäftslogik ausführen und ein oder mehrere Events erzeugen
|
|
val memberRegisteredEvent = MemberRegisteredEvent(
|
|
memberId = UUID.randomUUID(),
|
|
name = command.name,
|
|
// ...
|
|
)
|
|
|
|
// 2. Das Event im Event Store speichern
|
|
eventStore.save(memberRegisteredEvent)
|
|
|
|
// 3. Das Event veröffentlichen, damit andere Teile des Systems
|
|
// (z.B. ein E-Mail-Service) darauf reagieren können.
|
|
eventPublisher.publish(memberRegisteredEvent)
|
|
|
|
// ...
|
|
}
|
|
}
|
|
```
|
|
|
|
Diese Architektur ermöglicht eine hochgradig entkoppelte, skalierbare und resiliente Systemlandschaft, die auf asynchroner Kommunikation basiert.
|
|
|
|
---
|
|
**Letzte Aktualisierung**: 31. Juli 2025
|