Files
meldestelle/infrastructure/cache/README-INFRA-CACHE.md
T
2025-09-03 15:19:11 +02:00

115 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Infrastructure/Cache Modulbeschreibung und Implementierungsleitfaden
Letzte Aktualisierung: 03. September 2025
## Zweck und Aufgaben des Moduls
Das Infrastructure/Cache-Modul stellt eine einheitliche, technologieneutrale CacheSchnittstelle für alle Services bereit und liefert mit einer Redisbasierten AdapterImplementierung die produktionsreife Ausführung. Ziele:
- Antwortzeiten reduzieren und Primärdatenbanken entlasten.
- Einheitliche API für Lesen/Schreiben, BatchOperationen und TTLs.
- Resilienz bei RedisAusfällen durch lokalen Fallback.
- Operative Transparenz durch einfache Metriken, HealthInformationen und periodische Wartungsaufgaben.
## Architektur (PortAdapter)
- cacheapi: enthält die öffentlichen Verträge und Basistypen
- DistributedCache: zentrale PortSchnittstelle für CacheOperationen
- CacheEntry, CacheConfiguration, CacheSerializer
- ConnectionStatusTracker/ConnectionStateListener zur Verbindungsüberwachung
- rediscache: Adapter, der die PortSchnittstelle mit Spring Data Redis umsetzt
- RedisDistributedCache: konkrete Implementierung inkl. OfflineFallback, DirtySync, Batchs, KeyPrefixing, TTLHandling und einfachen Metriken
- JacksonCacheSerializer: serialisiert Werte und CacheEntry per Jackson
## Öffentliche API (Auszug)
DistributedCache
- get(key, clazz)/set(key, value, ttl?)
- delete(key), exists(key)
- multiGet(keys, clazz), multiSet(map, ttl?)
- multiDelete(keys)
- synchronize(keys?), markDirty(key), getDirtyKeys(), clear()
Idiomatic Kotlin Extensions
- cache.get<T>(key)
- cache.multiGet<T>(keys)
CacheConfiguration (DefaultCacheConfiguration vorhanden)
- defaultTtl?, localCacheMaxSize?, offlineModeEnabled, synchronizationInterval, offlineEntryMaxAge?, keyPrefix, compressionEnabled, compressionThreshold
Hinweis: Die Kompression wird aktuell durch den Serializer bereitgestellt; Schwellwerte/Flags sind für zukünftiges Tuning vorgesehen.
## Implementierungsdetails (RedisDistributedCache)
- Lokaler Fallback: ConcurrentHashMap als lokaler Cache speichert CacheEntry inkl. expiresAt. Bei RedisAusfall werden Schreibvorgänge lokal gehalten und als „dirty“ markiert.
- DirtySynchronisation: Sobald die Verbindung wieder ONLINE ist, werden geänderte Schlüssel zu Redis synchronisiert (synchronize()).
- KeyPrefixing: Alle externen Keys werden mittels keyPrefix gekapselt, um Mandanten/Services zu isolieren.
- TTL/Expiration: TTL wird einheitlich über kotlin.time.Duration angegeben und für Redis in java.time.Duration konvertiert. Lokale Einträge enthalten expiresAt und werden periodisch bereinigt.
- BatchOperationen: multiGet/multiSet/multiDelete nutzen RedisBatching/Pipelining, lokal wird konsistent gespiegelt.
- Größenbegrenzung Local Cache (neu): Wenn localCacheMaxSize gesetzt ist, werden bei Überschreitung die am längsten nicht mehr modifizierten Einträge aus dem lokalen Cache entfernt (LRM least recently modified). Dadurch bleibt der lokale Fallback speichereffizient.
- Periodische Aufgaben (@Scheduled):
- Verbindungsprüfung: fixedDelayString = "${redis.connection-check-interval:10000}"
- Lokale Bereinigung: fixedDelayString = "${redis.local-cache-cleanup-interval:60000}"
- DirtySync: fixedDelayString = "${redis.sync-interval:300000}"
- MetrikenLog: fixedDelayString = "${redis.metrics-log-interval:300000}"
Wichtige Robustheitsdetails
- Alle RedisOperationen fangen RedisConnectionFailureException ab und schalten den ConnectionState auf DISCONNECTED. Beim nächsten erfolgreichen Zugriff wird CONNECTED gesetzt und eine Synchronisation der dirty keys ausgelöst.
- multiSet setzt TTLs bei Bedarf per Pipeline nach (pExpire); einzelne setOperationen nutzen expire via Duration.
## Verwendung (Beispiele)
Einbinden: Projekte hängen gegen :infrastructure:cache:redis-cache und injizieren DistributedCache.
Lesen/Schreiben mit TTL
```kotlin
val user = cache.get<User>("user:42")
if (user == null) {
val loaded = userRepository.findById("42") ?: return null
cache.set("user:42", loaded, ttl = 1.hours)
}
```
BatchLesezugriff
```kotlin
val ids = listOf("user:1", "user:2", "user:3")
val map = cache.multiGet<User>(ids)
```
BulkSchreiben
```kotlin
cache.multiSet(mapOf(
"cfg:app" to appConfig,
"cfg:features" to features
), ttl = 30.minutes)
```
Verbindungsstatus überwachen
```kotlin
cache.registerConnectionListener(object : ConnectionStateListener {
override fun onConnectionStateChanged(newState: ConnectionState, timestamp: Instant) {
logger.info("Cache connection state: $newState at $timestamp")
}
})
```
## Konfiguration
DefaultCacheConfiguration bietet sinnvolle Defaults. Relevante Properties (optional via Spring @Scheduled Platzhalter):
- redis.connection-check-interval: ms für Verbindungsprüfung (Default 10000)
- redis.local-cache-cleanup-interval: ms für lokale Bereinigung (Default 60000)
- redis.sync-interval: ms für Synchronisationsläufe (Default 300000)
- redis.metrics-log-interval: ms für periodisches MetrikenLogging (Default 300000)
Hinweise
- keyPrefix sollte pro Service gesetzt werden (z. B. "masterdata"), um Kollisionen zu vermeiden.
- localCacheMaxSize begrenzt die Größe des lokalen FallbackCaches. Bei null ist die Größe unbegrenzt.
## Betrieb & Monitoring
- HealthInfos: getHealthStatus() liefert eine einfache Einschätzung basierend auf ConnectionState und Erfolgsrate der Operationen.
- Metriken: getPerformanceMetrics() liefert einfache Kennzahlen (Operations, SuccessRate, Größe lokaler Cache, Anzahl dirty Keys). Periodisches Logging per @Scheduled möglich.
- Cache Warming: warmCache(keys, loader) und warmCacheBulk(map) helfen, HotKeys/gefragte Konfigurationen beim Start vorzuwärmen.
## Grenzen & bekannte Punkte
- Kompression ist im Serializer implementiert; die konfigurierbaren Flags/Schwellenwerte sind derzeit nicht dynamisch an/ausgeschaltet.
- OfflineModus: Die Konfiguration offlineModeEnabled ist vorhanden; die Implementierung betreibt den lokalen Fallback standardmäßig bei Verbindungsproblemen. Eine harte Deaktivierung dieses Verhaltens ist aktuell nicht verdrahtet.
## Changelog (Kurz)
- 20250903: Fehlerbehebungen für @ScheduledPlatzhalter, korrektes Logging im CacheWarming, lokale CacheGrößenbegrenzung (LRMEviction) hinzugefügt. Dokumentation aktualisiert (diese Datei).
## Fazit
Das CacheModul bietet eine klare, wiederverwendbare CacheSchnittstelle mit einer robusten RedisImplementierung. Es unterstützt TTLs, BatchOperationen, lokalen Fallback bei Ausfällen und liefert einfache, praxistaugliche Betriebsinformationen. Mit keyPrefix und lokalen Limits ist der Einsatz in MultiServiceUmgebungen unkompliziert und stabil.