Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6245518
feat: encapsulate cache replacement strategies into enum
DanielDango Jan 20, 2026
95ecd2d
feat: add cache initialization logic to EvaluationConfiguration and u…
DanielDango Apr 18, 2026
c34b4e5
feat: make LocalCache implement Cache and revamp CacheReplacementStra…
DanielDango Apr 18, 2026
cc8c041
feat: retrieve cache replacement strategy from ModuleConfiguration
DanielDango Apr 18, 2026
5186194
feat: implement HierarchicalCache for multi-layer caching and update …
DanielDango Apr 19, 2026
b239c14
docs: update caching documentation to include HierarchicalCache
DanielDango Apr 20, 2026
9c804e1
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
DanielDango Apr 29, 2026
b4aebe6
feat: support environment-based cache configuration
DanielDango Apr 29, 2026
a515e5f
Merge remote-tracking branch 'upstream/main' into fork/DanielDango/fe…
DanielDango May 4, 2026
2135004
revert: remove module config for caches, instead get cache configurat…
DanielDango May 4, 2026
11aa1bb
test: enhance CacheTest with new entry writing, retrieval, serializat…
DanielDango May 4, 2026
68b5c9e
fix: resolve sonar cube issues
DanielDango May 4, 2026
4cadcf7
refactor: streamline cache manager configuration
DanielDango May 4, 2026
53ebb05
refactor: update cache conflict resolution to replacement strategy te…
DanielDango May 4, 2026
8ca6260
revert: remove unused argumentAsEnum method from ModuleConfiguration
DanielDango May 4, 2026
c1ff184
refactor: enhance cache hierarchy parsing to support quoted strings a…
DanielDango May 4, 2026
0940083
refactor: make default cache configuration identical to previous beha…
DanielDango May 5, 2026
1f4b55e
refactor: improve cache inconsistency handling and resolution methods
DanielDango May 5, 2026
c1db4b5
refactor: mark resolveViaInternalKey method as deprecated with clarif…
DanielDango May 5, 2026
0e00965
feat: add test-specific environment configuration and enforce env ove…
DanielDango May 5, 2026
ae89375
refactor: update documentation for CacheManagers reset usage and remo…
DanielDango May 5, 2026
f5aea19
refactor: add deprecated javadoc annotation and standardize dotenv va…
DanielDango May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions docs/caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ LiSSA implements a sophisticated caching system to improve performance and ensur
- [`ClassifierCacheParameter`](../src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/classifier/ClassifierCacheParameter.java): Configuration for classifier caches (model name, seed, temperature)
- [`EmbeddingCacheParameter`](../src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/embedding/EmbeddingCacheParameter.java): Configuration for embedding caches (model name)
2. **Cache Implementations**
- [`Hierarchical Cache`](../src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/HierarchicalCache.java): Two cache levels with a synchronization mechanism
- Changes are applied to both levels
- Reads use a Conflict Resolution Strategy to ensure consistent results
- If a cache entry is missing in one level during a read, it is also written to the other level
- [`LocalCache`](../src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/LocalCache.java): File-based cache implementation that stores data in JSON format
- Implements dirty tracking to optimize writes
- Automatically saves changes on shutdown
- Supports atomic writes using temporary files
- [`RedisCache`](../src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/RedisCache.java): Redis-based cache implementation with fallback to local cache
- [`RedisCache`](../src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/RedisCache.java): Redis-based cache implementation
- Uses Redis for high-performance caching
- Falls back to local cache if Redis is unavailable
- Supports both string and object serialization
3. **Cache Management**
- [`CacheManager`](../src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/CacheManager.java): Central manager for cache instances
Expand Down Expand Up @@ -59,6 +62,16 @@ Parameters are used to:
2. Create cache keys from content (via `createCacheKey()` method)
3. Validate cache consistency when retrieving existing caches

### Cache Replacement Strategies

When using hierarchical caches with multiple layers (e.g., Redis and local cache), the system detects and resolves conflicts between layers:

- **NONE**: Does not replace conflicting values; leaves both cache layers as they are. Primary value is returned on read.
- **ERROR** (default): Throws an exception if a cache conflict is detected, ensuring data consistency by failing fast.
- **OVERWRITE**: Automatically overwrites the secondary cache value with the primary cache value when a conflict is detected, and logs a warning.

The replacement strategy for cache conflicts is configured via the `CACHE_REPLACEMENT_STRATEGY` environment variable.

### Cache API

The `Cache` interface provides two API levels:
Expand All @@ -81,7 +94,20 @@ The `Cache` interface provides two API levels:
"cache_dir": "./cache/path" // Directory for cache storage
}
```
2. **Redis Setup**
2. **Environment Variables**

The caching system supports the following environment variables:
- **CACHE_HIERARCHY**: Comma-separated list of cache types in order (e.g., "LOCAL,REDIS")
- Default: "LOCAL"
- Supported values: "LOCAL", "REDIS"
- **CACHE_REPLACEMENT_STRATEGY**: Strategy for handling conflicts between cache layers
- Default: "ERROR"
- Supported values: "NONE", "ERROR", "OVERWRITE"
- **REDIS_URL**: Redis connection URL for RedisCache
- Default: "redis://localhost:6379"
- Example: "redis://redis-server:6379"

3. **Redis Setup**
To use Redis for caching, you need to set up a Redis server. Here's a recommended Docker Compose configuration:

```yaml
Expand All @@ -101,10 +127,13 @@ The `Cache` interface provides two API levels:

To use Redis with LiSSA:
1. Start the Redis server using Docker Compose
2. The system will automatically use Redis if available
3. If Redis is unavailable, it will fall back to local file-based caching (useful for replication packages)
2. Set environment variables if needed:
- `CACHE_HIERARCHY=REDIS,LOCAL` to use Redis with local fallback
- `REDIS_URL=redis://your-redis-host:6379` if not using the default
3. The system will automatically use Redis if available
4. If Redis is unavailable, it will fall back to local file-based caching (useful for replication packages)

3. **Best Practices**
4. **Best Practices**

- Use the cache directory specified in the configuration
- Clear the cache directory if you encounter issues
Expand Down
39 changes: 26 additions & 13 deletions env-template
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
OPENWEBUI_URL=https://domain.tldr/api
OPENWEBUI_API_KEY=

OLLAMA_EMBEDDING_HOST=
#OLLAMA_EMBEDDING_PASSWORD=
#OLLAMA_EMBEDDING_USER=

OLLAMA_HOST=
#OLLAMA_PASSWORD=
#OLLAMA_USER=

OPENAI_ORGANIZATION_ID=
OPENAI_API_KEY=
OPENWEBUI_URL=https://domain.tldr/api
OPENWEBUI_API_KEY=

OLLAMA_EMBEDDING_HOST=
#OLLAMA_EMBEDDING_PASSWORD=
#OLLAMA_EMBEDDING_USER=

OLLAMA_HOST=
#OLLAMA_PASSWORD=
#OLLAMA_USER=

OPENAI_ORGANIZATION_ID=
OPENAI_API_KEY=

# Cache strategy for handling conflicts between different cache levels
# Valid values: NONE, ERROR, OVERWRITE
#CACHE_REPLACEMENT_STRATEGY=ERROR

# Cache hierarchy - ascending comma-separated list of cache types to use
# Examples:
# LOCAL - only local file-based cache
# LOCAL,REDIS - local cache as primary, Redis as secondary fallback
# REDIS,LOCAL - Redis as primary, local cache as secondary fallback
# Valid cache types: LOCAL, REDIS
#CACHE_HIERARCHY=REDIS,LOCAL

60 changes: 60 additions & 0 deletions src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/Cache.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/* Licensed under MIT 2025-2026. */
package edu.kit.kastel.sdq.lissa.ratlr.cache;

import static edu.kit.kastel.sdq.lissa.ratlr.cache.LocalCache.LOCAL_CACHE_NAME;

import org.jspecify.annotations.Nullable;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
* Interface for cache implementations in the LiSSA framework.
* This interface defines the contract for caching mechanisms that store and retrieve
Expand Down Expand Up @@ -85,4 +90,59 @@ public interface Cache<K extends CacheKey> {
* @return The cache parameters
*/
CacheParameter<K> getCacheParameter();

/**
* Converts a JSON string to an object of the specified type.
* If the target type is String, the JSON string is returned as is.
*
* @param <T> The type to convert to
* @param jsonData The JSON string to convert
* @param clazz The class of the target type
* @param mapper The ObjectMapper instance to use for deserialization
* @return The converted object, or null if jsonData is null
* @throws IllegalArgumentException If the JSON cannot be deserialized to the target type
*/
@SuppressWarnings("unchecked")
static <T> @Nullable T convert(@Nullable String jsonData, Class<T> clazz, ObjectMapper mapper) {
if (jsonData == null) {
return null;
}
if (clazz == String.class) {
return (T) jsonData;
}

try {
return mapper.readValue(jsonData, clazz);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Could not deserialize object", e);
}
}

/**
* Factory method to create a cache instance by type name.
* Supported types:
* <ul>
* <li>"local" - LocalCache for file-based storage</li>
* <li>"redis" - RedisCache for Redis-based storage</li>
* <li>"hierarchical" - HierarchicalCache for multi-layer caching (requires primary and secondary cache)</li>
Comment thread
DanielDango marked this conversation as resolved.
Outdated
* </ul>
*
* @param <K> The type of cache key
* @param type The cache type name (case-insensitive)
* @param cacheDir The directory for local cache storage
* @param parameters The cache parameters
* @param mapper The ObjectMapper for JSON operations
* @return A cache instance of the specified type
* @throws IllegalArgumentException If the type is not recognized or the cache cannot be created
*/
static <K extends CacheKey> Cache<K> createByType(
String type, CacheParameter<K> parameters, @Nullable String cacheDir, @Nullable ObjectMapper mapper) {
return switch (type) {
case LOCAL_CACHE_NAME -> new LocalCache<>(cacheDir, parameters);
case "redis" -> new RedisCache<>(parameters, mapper);
default ->
throw new IllegalArgumentException(
"Unknown cache type: " + type + ". Supported types: local, redis, hierarchical");
Comment thread
DanielDango marked this conversation as resolved.
Outdated
};
}
}
Loading
Loading