update cache-module

This commit is contained in:
2025-09-03 23:29:37 +02:00
parent 63a1b97db7
commit 2eefe24a4f
6 changed files with 93 additions and 93 deletions
@@ -4,73 +4,73 @@ import at.mocode.core.domain.event.DomainEvent
import java.util.UUID import java.util.UUID
/** /**
* Interface for serializing and deserializing domain events. * Schnittstelle für die Serialisierung und Deserialisierung von Domain-Events.
*/ */
interface EventSerializer { interface EventSerializer {
/** /**
* Serializes a domain event to a map of strings to strings. * Serialisiert ein Domain-Event zu einer Map von Strings zu Strings.
* This format is suitable for storage in Redis Streams. * Dieses Format ist für die Speicherung in Redis Streams geeignet.
* *
* @param event The event to serialize * @param event Das zu serialisierende Event
* @return A map of strings to strings representing the event * @return Eine Map von Strings zu Strings, die das Event repräsentiert
*/ */
fun serialize(event: DomainEvent): Map<String, String> fun serialize(event: DomainEvent): Map<String, String>
/** /**
* Deserializes a map of strings to a domain event. * Deserialisiert eine Map von Strings zu einem Domain-Event.
* *
* @param data The map of strings to deserialize * @param data Die zu deserialisierende Map von Strings
* @return The deserialized domain event * @return Das deserialisierte Domain-Event
*/ */
fun deserialize(data: Map<String, String>): DomainEvent fun deserialize(data: Map<String, String>): DomainEvent
/** /**
* Gets the type of domain event. * Ermittelt den Typ des Domain-Events.
* This is used to determine the type of event when deserializing. * Dies wird verwendet, um den Typ des Events bei der Deserialisierung zu bestimmen.
* *
* @param event The event to get the type of * @param event Das Event, dessen Typ ermittelt werden soll
* @return The type of the event as a string * @return Der Typ des Events als String
*/ */
fun getEventType(event: DomainEvent): String fun getEventType(event: DomainEvent): String
/** /**
* Gets the type of domain event from a serialized map. * Ermittelt den Typ des Domain-Events aus einer serialisierten Map.
* *
* @param data The serialized event data * @param data Die serialisierten Event-Daten
* @return The type of the event as a string * @return Der Typ des Events als String
*/ */
fun getEventType(data: Map<String, String>): String fun getEventType(data: Map<String, String>): String
/** /**
* Registers a domain event class with the serializer. * Registriert eine Domain-Event-Klasse beim Serializer.
* This is used to map event types to their corresponding classes. * Dies wird verwendet, um Event-Typen auf ihre entsprechenden Klassen abzubilden.
* *
* @param eventClass The class of the event to register * @param eventClass Die Klasse des zu registrierenden Events
* @param eventType The type of the event as a string * @param eventType Der Typ des Events als String
*/ */
fun registerEventType(eventClass: Class<out DomainEvent>, eventType: String) fun registerEventType(eventClass: Class<out DomainEvent>, eventType: String)
/** /**
* Gets the aggregate ID from a serialized event. * Ermittelt die Aggregat-ID aus einem serialisierten Event.
* *
* @param data The serialized event data * @param data Die serialisierten Event-Daten
* @return The aggregate ID * @return Die Aggregat-ID
*/ */
fun getAggregateId(data: Map<String, String>): UUID fun getAggregateId(data: Map<String, String>): UUID
/** /**
* Gets the event ID from a serialized event. * Ermittelt die Event-ID aus einem serialisierten Event.
* *
* @param data The serialized event data * @param data Die serialisierten Event-Daten
* @return The event ID * @return Die Event-ID
*/ */
fun getEventId(data: Map<String, String>): UUID fun getEventId(data: Map<String, String>): UUID
/** /**
* Gets the version from a serialized event. * Ermittelt die Version aus einem serialisierten Event.
* *
* @param data The serialized event data * @param data Die serialisierten Event-Daten
* @return The version * @return Die Version
*/ */
fun getVersion(data: Map<String, String>): Long fun getVersion(data: Map<String, String>): Long
} }
@@ -4,96 +4,96 @@ import at.mocode.core.domain.event.DomainEvent
import java.util.UUID import java.util.UUID
/** /**
* Interface for an event store that persists domain events. * Schnittstelle für einen Event Store, der Domain-Events persistiert.
*/ */
interface EventStore { interface EventStore {
/** /**
* Appends an event to the event store. * Fügt ein Event zum Event Store hinzu.
* *
* @param event The event to append * @param event Das hinzuzufügende Event
* @param streamId The ID of the event stream (typically the aggregate ID) * @param streamId Die ID des Event-Streams (normalerweise die Aggregat-ID)
* @param expectedVersion The expected version of the stream (for optimistic concurrency) * @param expectedVersion Die erwartete Version des Streams (für optimistische Nebenläufigkeitskontrolle)
* @return The new version of the stream * @return Die neue Version des Streams
* @throws ConcurrencyException if the expected version doesn't match the actual version * @throws ConcurrencyException wenn die erwartete Version nicht mit der tatsächlichen Version übereinstimmt
*/ */
fun appendToStream(event: DomainEvent, streamId: UUID, expectedVersion: Long): Long fun appendToStream(event: DomainEvent, streamId: UUID, expectedVersion: Long): Long
/** /**
* Appends multiple events to the event store. * Fügt mehrere Events zum Event Store hinzu.
* *
* @param events The events to append * @param events Die hinzuzufügenden Events
* @param streamId The ID of the event stream (typically the aggregate ID) * @param streamId Die ID des Event-Streams (normalerweise die Aggregat-ID)
* @param expectedVersion The expected version of the stream (for optimistic concurrency) * @param expectedVersion Die erwartete Version des Streams (für optimistische Nebenläufigkeitskontrolle)
* @return The new version of the stream * @return Die neue Version des Streams
* @throws ConcurrencyException if the expected version doesn't match the actual version * @throws ConcurrencyException wenn die erwartete Version nicht mit der tatsächlichen Version übereinstimmt
*/ */
fun appendToStream(events: List<DomainEvent>, streamId: UUID, expectedVersion: Long): Long fun appendToStream(events: List<DomainEvent>, streamId: UUID, expectedVersion: Long): Long
/** /**
* Reads events from a stream. * Liest Events aus einem Stream.
* *
* @param streamId The ID of the event stream to read from * @param streamId Die ID des Event-Streams, aus dem gelesen werden soll
* @param fromVersion The version to start reading from (inclusive) * @param fromVersion Die Version, ab der gelesen werden soll (inklusive)
* @param toVersion The version to read to (inclusive), or null to read all events * @param toVersion Die Version, bis zu der gelesen werden soll (inklusive), oder null um alle Events zu lesen
* @return The events in the stream * @return Die Events im Stream
*/ */
fun readFromStream(streamId: UUID, fromVersion: Long = 0, toVersion: Long? = null): List<DomainEvent> fun readFromStream(streamId: UUID, fromVersion: Long = 0, toVersion: Long? = null): List<DomainEvent>
/** /**
* Reads all events from all streams. * Liest alle Events aus allen Streams.
* *
* @param fromPosition The position to start reading from (inclusive) * @param fromPosition Die Position, ab der gelesen werden soll (inklusive)
* @param maxCount The maximum number of events to read, or null to read all events * @param maxCount Die maximale Anzahl der zu lesenden Events, oder null um alle Events zu lesen
* @return The events in all streams * @return Die Events in allen Streams
*/ */
fun readAllEvents(fromPosition: Long = 0, maxCount: Int? = null): List<DomainEvent> fun readAllEvents(fromPosition: Long = 0, maxCount: Int? = null): List<DomainEvent>
/** /**
* Gets the current version of a stream. * Ermittelt die aktuelle Version eines Streams.
* *
* @param streamId The ID of the event stream * @param streamId Die ID des Event-Streams
* @return The current version of the stream, or -1 if the stream doesn't exist * @return Die aktuelle Version des Streams, oder -1 wenn der Stream nicht existiert
*/ */
fun getStreamVersion(streamId: UUID): Long fun getStreamVersion(streamId: UUID): Long
/** /**
* Subscribes to events from a specific stream. * Abonniert Events von einem spezifischen Stream.
* *
* @param streamId The ID of the event stream to subscribe to * @param streamId Die ID des Event-Streams, der abonniert werden soll
* @param fromVersion The version to start subscribing from (inclusive) * @param fromVersion Die Version, ab der abonniert werden soll (inklusive)
* @param handler The handler to call for each event * @param handler Der Handler, der für jedes Event aufgerufen wird
* @return A subscription that can be used to unsubscribe * @return Ein Abonnement, das zum Abbestellen verwendet werden kann
*/ */
fun subscribeToStream(streamId: UUID, fromVersion: Long = 0, handler: (DomainEvent) -> Unit): Subscription fun subscribeToStream(streamId: UUID, fromVersion: Long = 0, handler: (DomainEvent) -> Unit): Subscription
/** /**
* Subscribes to all events from all streams. * Abonniert alle Events von allen Streams.
* *
* @param fromPosition The position to start subscribing from (inclusive) * @param fromPosition Die Position, ab der abonniert werden soll (inklusive)
* @param handler The handler to call for each event * @param handler Der Handler, der für jedes Event aufgerufen wird
* @return A subscription that can be used to unsubscribe * @return Ein Abonnement, das zum Abbestellen verwendet werden kann
*/ */
fun subscribeToAll(fromPosition: Long = 0, handler: (DomainEvent) -> Unit): Subscription fun subscribeToAll(fromPosition: Long = 0, handler: (DomainEvent) -> Unit): Subscription
} }
/** /**
* Interface for a subscription to an event stream. * Schnittstelle für ein Abonnement eines Event-Streams.
*/ */
interface Subscription { interface Subscription {
/** /**
* Unsubscribes from the event stream. * Beendet das Abonnement des Event-Streams.
*/ */
fun unsubscribe() fun unsubscribe()
/** /**
* Checks if the subscription is active. * Überprüft, ob das Abonnement aktiv ist.
* *
* @return true if the subscription is active, false otherwise * @return true wenn das Abonnement aktiv ist, false andernfalls
*/ */
fun isActive(): Boolean fun isActive(): Boolean
} }
/** /**
* Exception thrown when there is a concurrency conflict in the event store. * Exception, die bei einem Nebenläufigkeitskonflikt im Event Store ausgelöst wird.
*/ */
class ConcurrencyException(message: String) : RuntimeException(message) class ConcurrencyException(message: String) : RuntimeException(message)
@@ -8,10 +8,10 @@ import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.atomic.LongAdder import java.util.concurrent.atomic.LongAdder
/** /**
* Comprehensive metrics tracking for Redis Event Store operations. * Umfassende Metriken-Verfolgung für Redis Event-Store-Operationen.
* *
* Tracks performance metrics, error rates, and operational statistics * Verfolgt Performance-Metriken, Fehlerquoten und Betriebsstatistiken,
* to provide insights into event store health and performance. * um Einblicke in die Gesundheit und Performance des Event-Stores zu geben.
*/ */
class EventStoreMetrics { class EventStoreMetrics {
private val logger = LoggerFactory.getLogger(EventStoreMetrics::class.java) private val logger = LoggerFactory.getLogger(EventStoreMetrics::class.java)
@@ -11,7 +11,7 @@ import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
/** /**
* Jackson-based implementation of EventSerializer. * Jackson-basierte Implementierung des EventSerializer.
*/ */
class JacksonEventSerializer : EventSerializer { class JacksonEventSerializer : EventSerializer {
private val logger = LoggerFactory.getLogger(JacksonEventSerializer::class.java) private val logger = LoggerFactory.getLogger(JacksonEventSerializer::class.java)
@@ -86,7 +86,7 @@ class RedisEventStore(
} }
/** /**
* Validates the expected version and returns the current version, handling cache invalidation on conflicts. * Validiert die erwartete Version und gibt die aktuelle Version zurück, behandelt Cache-Invalidierung bei Konflikten.
*/ */
private fun validateAndGetCurrentVersion(streamId: UUID, expectedVersion: Long): Long { private fun validateAndGetCurrentVersion(streamId: UUID, expectedVersion: Long): Long {
var currentVersion = getStreamVersion(streamId) var currentVersion = getStreamVersion(streamId)
@@ -105,7 +105,7 @@ class RedisEventStore(
} }
/** /**
* Appends multiple events in a single Redis transaction for optimal performance. * Fügt mehrere Events in einer einzigen Redis-Transaktion hinzu für optimale Performance.
*/ */
private fun appendEventsInBatch(events: List<DomainEvent>, streamId: UUID, currentVersion: Long): Long { private fun appendEventsInBatch(events: List<DomainEvent>, streamId: UUID, currentVersion: Long): Long {
val streamKey = getStreamKey(streamId) val streamKey = getStreamKey(streamId)
@@ -15,7 +15,7 @@ import org.springframework.data.redis.core.StringRedisTemplate
import java.time.Duration import java.time.Duration
/** /**
* Redis event store properties. * Redis Event Store Eigenschaften.
*/ */
@ConfigurationProperties(prefix = "redis.event-store") @ConfigurationProperties(prefix = "redis.event-store")
data class RedisEventStoreProperties( data class RedisEventStoreProperties(
@@ -39,17 +39,17 @@ data class RedisEventStoreProperties(
) )
/** /**
* Spring configuration for Redis event store. * Spring-Konfiguration für Redis Event Store.
*/ */
@Configuration @Configuration
@EnableConfigurationProperties(RedisEventStoreProperties::class) @EnableConfigurationProperties(RedisEventStoreProperties::class)
class RedisEventStoreConfiguration { class RedisEventStoreConfiguration {
/** /**
* Creates a Redis connection factory for the event store. * Erstellt eine Redis-Verbindungsfactory für den Event Store.
* *
* @param properties Redis event store properties * @param properties Redis Event Store Eigenschaften
* @return Redis connection factory * @return Redis-Verbindungsfactory
*/ */
@Bean @Bean
@ConditionalOnMissingBean(name = ["eventStoreRedisConnectionFactory"]) @ConditionalOnMissingBean(name = ["eventStoreRedisConnectionFactory"])
@@ -68,10 +68,10 @@ class RedisEventStoreConfiguration {
} }
/** /**
* Creates a Redis template for the event store. * Erstellt ein Redis-Template für den Event Store.
* *
* @param connectionFactory Redis connection factory * @param connectionFactory Redis-Verbindungsfactory
* @return Redis template * @return Redis-Template
*/ */
@Bean @Bean
@ConditionalOnMissingBean(name = ["eventStoreRedisTemplate"]) @ConditionalOnMissingBean(name = ["eventStoreRedisTemplate"])
@@ -86,9 +86,9 @@ class RedisEventStoreConfiguration {
} }
/** /**
* Creates an event serializer. * Erstellt einen Event-Serializer.
* *
* @return Event serializer * @return Event-Serializer
*/ */
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@@ -97,12 +97,12 @@ class RedisEventStoreConfiguration {
} }
/** /**
* Creates a Redis event store. * Erstellt einen Redis Event Store.
* *
* @param redisTemplate Redis template * @param redisTemplate Redis-Template
* @param eventSerializer Event serializer * @param eventSerializer Event-Serializer
* @param properties Redis event store properties * @param properties Redis Event Store Eigenschaften
* @return Event store * @return Event Store
*/ */
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@@ -116,12 +116,12 @@ class RedisEventStoreConfiguration {
} }
/** /**
* Creates a Redis event consumer. * Erstellt einen Redis Event Consumer.
* *
* @param redisTemplate Redis template * @param redisTemplate Redis-Template
* @param eventSerializer Event serializer * @param eventSerializer Event-Serializer
* @param properties Redis event store properties * @param properties Redis Event Store Eigenschaften
* @return Event consumer * @return Event Consumer
*/ */
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean