refactor: Migrate from monolithic to modular architecture
1. **Dokumentation der Architektur:**
- Vervollständigen Sie die C4-Diagramme im docs-Verzeichnis
- Dokumentieren Sie die wichtigsten Architekturentscheidungen in ADRs
2. **Redis-Integration finalisieren:**
- Implementieren Sie die verteilte Cache-Lösung für die Offline-Fähigkeit
- Nutzen Sie Redis Streams für das Event-Sourcing
This commit is contained in:
@@ -3,6 +3,9 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Apply platform BOM for version management
|
||||
implementation(platform(projects.platform.platformBom))
|
||||
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package at.mocode.infrastructure.eventstore.api
|
||||
|
||||
import at.mocode.core.domain.event.DomainEvent
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Interface for serializing and deserializing domain events.
|
||||
*/
|
||||
interface EventSerializer {
|
||||
/**
|
||||
* Serializes a domain event to a map of strings to strings.
|
||||
* This format is suitable for storage in Redis Streams.
|
||||
*
|
||||
* @param event The event to serialize
|
||||
* @return A map of strings to strings representing the event
|
||||
*/
|
||||
fun serialize(event: DomainEvent): Map<String, String>
|
||||
|
||||
/**
|
||||
* Deserializes a map of strings to strings to a domain event.
|
||||
*
|
||||
* @param data The map of strings to strings to deserialize
|
||||
* @return The deserialized domain event
|
||||
*/
|
||||
fun deserialize(data: Map<String, String>): DomainEvent
|
||||
|
||||
/**
|
||||
* Gets the type of a domain event.
|
||||
* This is used to determine the type of event when deserializing.
|
||||
*
|
||||
* @param event The event to get the type of
|
||||
* @return The type of the event as a string
|
||||
*/
|
||||
fun getEventType(event: DomainEvent): String
|
||||
|
||||
/**
|
||||
* Gets the type of a domain event from a serialized map.
|
||||
*
|
||||
* @param data The serialized event data
|
||||
* @return The type of the event as a string
|
||||
*/
|
||||
fun getEventType(data: Map<String, String>): String
|
||||
|
||||
/**
|
||||
* Registers a domain event class with the serializer.
|
||||
* This is used to map event types to their corresponding classes.
|
||||
*
|
||||
* @param eventClass The class of the event to register
|
||||
* @param eventType The type of the event as a string
|
||||
*/
|
||||
fun registerEventType(eventClass: Class<out DomainEvent>, eventType: String)
|
||||
|
||||
/**
|
||||
* Gets the aggregate ID from a serialized event.
|
||||
*
|
||||
* @param data The serialized event data
|
||||
* @return The aggregate ID
|
||||
*/
|
||||
fun getAggregateId(data: Map<String, String>): UUID
|
||||
|
||||
/**
|
||||
* Gets the event ID from a serialized event.
|
||||
*
|
||||
* @param data The serialized event data
|
||||
* @return The event ID
|
||||
*/
|
||||
fun getEventId(data: Map<String, String>): UUID
|
||||
|
||||
/**
|
||||
* Gets the version from a serialized event.
|
||||
*
|
||||
* @param data The serialized event data
|
||||
* @return The version
|
||||
*/
|
||||
fun getVersion(data: Map<String, String>): Long
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package at.mocode.infrastructure.eventstore.api
|
||||
|
||||
import at.mocode.core.domain.event.DomainEvent
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Interface for an event store that persists domain events.
|
||||
*/
|
||||
interface EventStore {
|
||||
/**
|
||||
* Appends an event to the event store.
|
||||
*
|
||||
* @param event The event to append
|
||||
* @param streamId The ID of the event stream (typically the aggregate ID)
|
||||
* @param expectedVersion The expected version of the stream (for optimistic concurrency)
|
||||
* @return The new version of the stream
|
||||
* @throws ConcurrencyException if the expected version doesn't match the actual version
|
||||
*/
|
||||
fun appendToStream(event: DomainEvent, streamId: UUID, expectedVersion: Long): Long
|
||||
|
||||
/**
|
||||
* Appends multiple events to the event store.
|
||||
*
|
||||
* @param events The events to append
|
||||
* @param streamId The ID of the event stream (typically the aggregate ID)
|
||||
* @param expectedVersion The expected version of the stream (for optimistic concurrency)
|
||||
* @return The new version of the stream
|
||||
* @throws ConcurrencyException if the expected version doesn't match the actual version
|
||||
*/
|
||||
fun appendToStream(events: List<DomainEvent>, streamId: UUID, expectedVersion: Long): Long
|
||||
|
||||
/**
|
||||
* Reads events from a stream.
|
||||
*
|
||||
* @param streamId The ID of the event stream to read from
|
||||
* @param fromVersion The version to start reading from (inclusive)
|
||||
* @param toVersion The version to read to (inclusive), or null to read all events
|
||||
* @return The events in the stream
|
||||
*/
|
||||
fun readFromStream(streamId: UUID, fromVersion: Long = 0, toVersion: Long? = null): List<DomainEvent>
|
||||
|
||||
/**
|
||||
* Reads all events from all streams.
|
||||
*
|
||||
* @param fromPosition The position to start reading from (inclusive)
|
||||
* @param maxCount The maximum number of events to read, or null to read all events
|
||||
* @return The events in all streams
|
||||
*/
|
||||
fun readAllEvents(fromPosition: Long = 0, maxCount: Int? = null): List<DomainEvent>
|
||||
|
||||
/**
|
||||
* Gets the current version of a stream.
|
||||
*
|
||||
* @param streamId The ID of the event stream
|
||||
* @return The current version of the stream, or -1 if the stream doesn't exist
|
||||
*/
|
||||
fun getStreamVersion(streamId: UUID): Long
|
||||
|
||||
/**
|
||||
* Subscribes to events from a specific stream.
|
||||
*
|
||||
* @param streamId The ID of the event stream to subscribe to
|
||||
* @param fromVersion The version to start subscribing from (inclusive)
|
||||
* @param handler The handler to call for each event
|
||||
* @return A subscription that can be used to unsubscribe
|
||||
*/
|
||||
fun subscribeToStream(streamId: UUID, fromVersion: Long = 0, handler: (DomainEvent) -> Unit): Subscription
|
||||
|
||||
/**
|
||||
* Subscribes to all events from all streams.
|
||||
*
|
||||
* @param fromPosition The position to start subscribing from (inclusive)
|
||||
* @param handler The handler to call for each event
|
||||
* @return A subscription that can be used to unsubscribe
|
||||
*/
|
||||
fun subscribeToAll(fromPosition: Long = 0, handler: (DomainEvent) -> Unit): Subscription
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for a subscription to an event stream.
|
||||
*/
|
||||
interface Subscription {
|
||||
/**
|
||||
* Unsubscribes from the event stream.
|
||||
*/
|
||||
fun unsubscribe()
|
||||
|
||||
/**
|
||||
* Checks if the subscription is active.
|
||||
*
|
||||
* @return true if the subscription is active, false otherwise
|
||||
*/
|
||||
fun isActive(): Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when there is a concurrency conflict in the event store.
|
||||
*/
|
||||
class ConcurrencyException(message: String) : RuntimeException(message)
|
||||
Reference in New Issue
Block a user