Skip to content

Commit b861b7f

Browse files
Jules was unable to complete the task in time. Please review the work done so far and provide feedback for Jules to continue.
1 parent e82098f commit b861b7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+5782
-2498
lines changed

commons/src/main/java/org/restheart/cache/Cache.java

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,78 @@
2323
import java.util.Optional;
2424

2525
/**
26+
* A generic cache interface that defines common caching operations.
2627
*
2728
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
28-
* @param <K> the class of the keys
29-
* @param <V> the class of the values
29+
* @param <K> the type of keys maintained by this cache
30+
* @param <V> the type of mapped values
3031
*/
3132
public interface Cache<K, V> {
33+
/**
34+
* Defines the expiration policies for cache entries.
35+
*/
3236
public enum EXPIRE_POLICY {
33-
NEVER, AFTER_WRITE, AFTER_READ
37+
/** Cache entries never expire. */
38+
NEVER,
39+
/** Cache entries expire after a fixed duration an entry is written. */
40+
AFTER_WRITE,
41+
/** Cache entries expire after a fixed duration an entry is accessed. */
42+
AFTER_READ
3443
}
3544

45+
/**
46+
* Returns the value associated with the specified key, or {@code Optional.empty()}
47+
* if there is no cached value for the key.
48+
*
49+
* @param key the key whose associated value is to be returned
50+
* @return an {@code Optional} containing the value associated with the key,
51+
* or {@code Optional.empty()} if no mapping for the key exists
52+
*/
3653
public Optional<V> get(K key);
3754

55+
/**
56+
* Removes the mapping for a key from this cache if it is present.
57+
*
58+
* @param key the key whose mapping is to be removed from the cache
59+
* @return an {@code Optional} containing the previous value associated with the key,
60+
* or {@code Optional.empty()} if there was no mapping for the key.
61+
*/
3862
public Optional<V> remove(K key);
3963

64+
/**
65+
* Associates the specified value with the specified key in this cache.
66+
* If the cache previously contained a mapping for the key, the old
67+
* value is replaced by the specified value.
68+
*
69+
* @param key the key with which the specified value is to be associated
70+
* @param value the value to be associated with the specified key
71+
*/
4072
public void put(K key, V value);
4173

4274
/**
4375
* Performs any pending maintenance operations needed by the cache.
76+
* This might include tasks like eviction of expired entries.
4477
*/
4578
public void cleanUp();
4679

80+
/**
81+
* Invalidates the cache entry associated with the specified key.
82+
*
83+
* @param key the key to invalidate
84+
*/
4785
public void invalidate(K key);
4886

87+
/**
88+
* Invalidates all entries in this cache.
89+
*/
4990
public void invalidateAll();
5091

92+
/**
93+
* Returns a view of the entries stored in this cache as a {@code Map}.
94+
* Modifications to the returned map may or may not be reflected in the cache,
95+
* depending on the cache implementation.
96+
*
97+
* @return a map view of the cache
98+
*/
5199
public Map<K, Optional<V>> asMap();
52100
}

commons/src/main/java/org/restheart/cache/CacheFactory.java

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,61 +28,78 @@
2828
import org.restheart.cache.impl.HashMapLoadingCache;
2929

3030
/**
31+
* A factory class for creating {@link Cache} and {@link LoadingCache} instances.
32+
* This factory provides methods to create different cache implementations,
33+
* such as Caffeine-based caches and HashMap-based loading caches.
3134
*
3235
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
3336
*/
3437
public class CacheFactory {
3538
/**
39+
* Creates a new Caffeine-based {@link LoadingCache} with the specified configuration.
3640
*
3741
* @param <K> the type of the cache keys
3842
* @param <V> the type of the cached values
39-
* @param size the size of the cache
40-
* @param expirePolicy specifies how and when each entry should be automatically
41-
* removed from the cache
42-
* @param ttl Time To Live in milliseconds
43-
* @param loader the cache loader used to obtain new values
44-
* @return the cache
43+
* @param size the maximum number of entries the cache can hold
44+
* @param expirePolicy the policy that specifies how and when each entry
45+
* should be automatically removed from the cache
46+
* @param ttl the Time To Live (TTL) for cache entries in milliseconds
47+
* @param loader the function used to load values for keys that are not
48+
* already in the cache
49+
* @return a new {@link LoadingCache} instance configured as specified
4550
*/
4651
public static <K, V> LoadingCache<K, V> createLocalLoadingCache(long size, Cache.EXPIRE_POLICY expirePolicy, long ttl, Function<K, V> loader) {
4752
return new CaffeineLoadingCache<>(size, expirePolicy, ttl, loader);
4853
}
4954

5055
/**
56+
* Creates a new HashMap-based {@link LoadingCache}.
57+
* This cache does not have a size limit or expiration policy.
58+
*
5159
* @param <K> the type of the cache keys
5260
* @param <V> the type of the cached values
53-
* @param loader the cache loader used to obtain new values
54-
* @return the cache
61+
* @param loader the function used to load values for keys that are not
62+
* already in the cache
63+
* @return a new {@link LoadingCache} instance using a HashMap backend
5564
*/
5665
public static <K, V> LoadingCache<K, V> createHashMapLoadingCache(Function<K, V> loader) {
5766
return new HashMapLoadingCache<>(loader);
5867
}
5968

6069
/**
70+
* Creates a new Caffeine-based {@link Cache} with the specified configuration.
6171
*
62-
* @param <K> the type of the cache keys
63-
* @param <V> the type of the cached values
64-
* @param size the size of the cache
65-
* @param expirePolicy specifies how and when each entry should be automatically removed from the cache
66-
* @param ttl Time To Live in milliseconds
67-
* @return the cache.
72+
* @param <K> the type of the cache keys
73+
* @param <V> the type of the cached values
74+
* @param size the maximum number of entries the cache can hold
75+
* @param expirePolicy the policy that specifies how and when each entry
76+
* should be automatically removed from the cache
77+
* @param ttl the Time To Live (TTL) for cache entries in milliseconds
78+
* @return a new {@link Cache} instance configured as specified
6879
*/
6980
public static <K,V> Cache<K,V> createLocalCache(long size, Cache.EXPIRE_POLICY expirePolicy, long ttl) {
7081
return new CaffeineCache<>(size, expirePolicy, ttl);
7182
}
83+
7284
/**
85+
* Creates a new Caffeine-based {@link Cache} with the specified configuration,
86+
* including a custom removal listener.
7387
*
74-
* @param <K> the type of the cache keys.
75-
* @param <V> the type of the cached values.
76-
* @param size the size of the cache.
77-
* @param expirePolicy specifies how and when each entry should be automatically removed from the cache.
78-
* @param ttl Time To Live in milliseconds.
79-
* @param remover the cache remover to invoke each time a value is automatically removed from the cache according to the expire xpolicy
80-
* @return the cache.
88+
* @param <K> the type of the cache keys
89+
* @param <V> the type of the cached values
90+
* @param size the maximum number of entries the cache can hold
91+
* @param expirePolicy the policy that specifies how and when each entry
92+
* should be automatically removed from the cache
93+
* @param ttl the Time To Live (TTL) for cache entries in milliseconds
94+
* @param remover a {@link Consumer} that is invoked when an entry is removed
95+
* from the cache due to expiration or eviction
96+
* @return a new {@link Cache} instance configured as specified
8197
*/
8298
public static <K,V> Cache<K,V> createLocalCache(long size, Cache.EXPIRE_POLICY expirePolicy, long ttl, Consumer<Map.Entry<K, Optional<V>>> remover) {
8399
return new CaffeineCache<>(size, expirePolicy, ttl, remover);
84100
}
85101

86102
private CacheFactory() {
103+
// Prevent instantiation
87104
}
88105
}

commons/src/main/java/org/restheart/cache/LoadingCache.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,27 @@
2222
import java.util.Optional;
2323

2424
/**
25+
* A {@link Cache} that supports atomic computation of values for keys that are
26+
* not already in the cache. This interface extends the basic {@link Cache}
27+
* interface by adding a method to retrieve a value, loading it if necessary.
2528
*
2629
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
27-
* @param <K> the class of the keys
28-
* @param <V> the class of the values
30+
* @param <K> the type of keys maintained by this cache
31+
* @param <V> the type of mapped values
2932
*/
3033
public interface LoadingCache<K,V> extends Cache<K,V> {
34+
/**
35+
* Returns the value associated with the specified key.
36+
* If the key is not already in the cache, this method will attempt to load
37+
* the value using the cache's configured loader. If the value is successfully
38+
* loaded, it will be stored in the cache and returned.
39+
* <p>
40+
* If the loading process fails or returns null, this method will return
41+
* {@code Optional.empty()} and no mapping will be stored in the cache.
42+
*
43+
* @param key the key whose associated value is to be returned or loaded
44+
* @return an {@code Optional} containing the value associated with the key,
45+
* or {@code Optional.empty()} if the key is not found or loading fails
46+
*/
3147
public Optional<V> getLoading(K key);
3248
}

commons/src/main/java/org/restheart/cache/impl/CaffeineCache.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,30 @@
3535
import com.github.benmanes.caffeine.cache.RemovalCause;
3636

3737
/**
38+
* A {@link org.restheart.cache.Cache} implementation backed by a
39+
* <a href="https://github.com/ben-manes/caffeine">Caffeine</a> cache.
40+
* This class wraps a Caffeine cache instance and adapts it to the
41+
* {@code org.restheart.cache.Cache} interface.
42+
* <p>
43+
* Values are stored as {@code Optional<V>} to allow caching of null values.
3844
*
3945
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
40-
* @param <K> the class of the keys.
41-
* @param <V> the class of the values (is Optional-ized).
46+
* @param <K> the type of keys maintained by this cache
47+
* @param <V> the type of mapped values
4248
*/
4349
public class CaffeineCache<K, V> implements org.restheart.cache.Cache<K, V> {
4450
private static final Executor virtualThreadsExecutor = ThreadsUtils.virtualThreadsExecutor();
4551
private final Cache<K, Optional<V>> wrapped;
4652

53+
/**
54+
* Constructs a new {@code CaffeineCache} with the specified configuration.
55+
*
56+
* @param size the maximum number of entries the cache can hold
57+
* @param expirePolicy the policy that specifies how and when each entry
58+
* should be automatically removed from the cache
59+
* @param ttl the Time To Live (TTL) for cache entries in milliseconds.
60+
* If zero or negative, entries do not expire based on time.
61+
*/
4762
public CaffeineCache(long size, EXPIRE_POLICY expirePolicy, long ttl) {
4863
var builder = Caffeine.newBuilder().executor(virtualThreadsExecutor);
4964

@@ -58,6 +73,20 @@ public CaffeineCache(long size, EXPIRE_POLICY expirePolicy, long ttl) {
5873
wrapped = builder.build();
5974
}
6075

76+
/**
77+
* Constructs a new {@code CaffeineCache} with the specified configuration,
78+
* including a custom removal listener.
79+
*
80+
* @param size the maximum number of entries the cache can hold
81+
* @param expirePolicy the policy that specifies how and when each entry
82+
* should be automatically removed from the cache
83+
* @param ttl the Time To Live (TTL) for cache entries in milliseconds.
84+
* If zero or negative, entries do not expire based on time.
85+
* @param remover a {@link Consumer} that is invoked when an entry is
86+
* removed from the cache due to expiration or eviction.
87+
* The entry passed to the consumer contains the key and the
88+
* {@code Optional<V>} value.
89+
*/
6190
public CaffeineCache(long size, EXPIRE_POLICY expirePolicy, long ttl, Consumer<Map.Entry<K, Optional<V>>> remover) {
6291
var builder = Caffeine.newBuilder().executor(virtualThreadsExecutor);
6392

@@ -75,38 +104,59 @@ public CaffeineCache(long size, EXPIRE_POLICY expirePolicy, long ttl, Consumer<M
75104
}).build();
76105
}
77106

107+
/**
108+
* {@inheritDoc}
109+
*/
78110
@Override
79111
public Optional<V> get(K key) {
80112
return wrapped.getIfPresent(key);
81113
}
82114

115+
/**
116+
* {@inheritDoc}
117+
*/
83118
@Override
84119
public synchronized Optional<V> remove(K key) {
85120
var ret = wrapped.getIfPresent(key);
86121
wrapped.invalidate(key);
87122
return ret;
88123
}
89124

125+
/**
126+
* {@inheritDoc}
127+
*/
90128
@Override
91129
public void put(K key, V value) {
92130
wrapped.put(key, Optional.ofNullable(value));
93131
}
94132

133+
/**
134+
* {@inheritDoc}
135+
*/
95136
@Override
96137
public void invalidate(K key) {
97138
wrapped.invalidate(key);
98139
}
99140

141+
/**
142+
* {@inheritDoc}
143+
*/
100144
@Override
101145
public void invalidateAll() {
102146
wrapped.invalidateAll();
103147
}
104148

149+
/**
150+
* {@inheritDoc}
151+
*/
105152
@Override
106153
public Map<K, Optional<V>> asMap() {
107154
return wrapped.asMap();
108155
}
109156

157+
/**
158+
* {@inheritDoc}
159+
*/
110160
@Override
111161
public void cleanUp() {
112162
wrapped.cleanUp();

0 commit comments

Comments
 (0)