Skip to content

Commit a5547c5

Browse files
authored
fix(core): allow zero max size caches across providers (#173)
1 parent 1bc9faa commit a5547c5

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

core/src/main/java/io/github/xanthic/cache/core/CacheApi.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import io.github.xanthic.cache.api.ICacheSpec;
55
import io.github.xanthic.cache.api.exception.MisconfiguredCacheException;
66
import io.github.xanthic.cache.api.exception.NoDefaultCacheImplementationException;
7+
import io.github.xanthic.cache.core.delegate.EmptyCache;
78

9+
import java.time.Duration;
810
import java.util.function.Consumer;
911

1012
/**
@@ -32,7 +34,14 @@ private CacheApi() {
3234
*/
3335
public static <K, V> Cache<K, V> create(Consumer<CacheApiSpec<K, V>> spec) {
3436
CacheApiSpec<K, V> finalSpec = CacheApiSpec.process(spec);
37+
if (isPermanentlyEmpty(finalSpec)) return EmptyCache.get();
3538
return finalSpec.provider().build(finalSpec);
3639
}
3740

41+
private static boolean isPermanentlyEmpty(ICacheSpec<?, ?> spec) {
42+
Long maxSize = spec.maxSize();
43+
Duration expiryTime = spec.expiryTime();
44+
return (maxSize != null && maxSize == 0) || (expiryTime != null && expiryTime.isZero());
45+
}
46+
3847
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package io.github.xanthic.cache.core.delegate;
2+
3+
import io.github.xanthic.cache.api.Cache;
4+
import org.jetbrains.annotations.ApiStatus;
5+
import org.jetbrains.annotations.NotNull;
6+
import org.jetbrains.annotations.Nullable;
7+
8+
import java.util.Map;
9+
import java.util.function.BiFunction;
10+
import java.util.function.Function;
11+
12+
public final class EmptyCache<K, V> implements Cache<K, V> {
13+
14+
@SuppressWarnings("rawtypes")
15+
private static final Cache INSTANCE = new EmptyCache<>();
16+
17+
@ApiStatus.Internal
18+
@SuppressWarnings("unchecked")
19+
public static <K, V> Cache<K, V> get() {
20+
return INSTANCE;
21+
}
22+
23+
private EmptyCache() {
24+
// restrict instantiation
25+
}
26+
27+
@Override
28+
public @Nullable V get(@NotNull K key) {
29+
return null;
30+
}
31+
32+
@Override
33+
public @Nullable V put(@NotNull K key, @NotNull V value) {
34+
return null;
35+
}
36+
37+
@Override
38+
public @Nullable V remove(@NotNull K key) {
39+
return null;
40+
}
41+
42+
@Override
43+
public void clear() {
44+
// no-op
45+
}
46+
47+
@Override
48+
public long size() {
49+
return 0L;
50+
}
51+
52+
@Override
53+
public @Nullable V compute(@NotNull K key, @NotNull BiFunction<? super K, ? super V, ? extends V> computeFunc) {
54+
return computeFunc.apply(key, null);
55+
}
56+
57+
@Override
58+
public V computeIfAbsent(@NotNull K key, @NotNull Function<K, V> computeFunc) {
59+
return computeFunc.apply(key);
60+
}
61+
62+
@Override
63+
public @Nullable V computeIfPresent(@NotNull K key, @NotNull BiFunction<? super K, ? super V, ? extends V> computeFunc) {
64+
return null;
65+
}
66+
67+
@Override
68+
public @Nullable V putIfAbsent(@NotNull K key, @NotNull V value) {
69+
return null;
70+
}
71+
72+
@Override
73+
public V merge(@NotNull K key, @NotNull V value, @NotNull BiFunction<V, V, V> mergeFunc) {
74+
return value;
75+
}
76+
77+
@Override
78+
public boolean replace(@NotNull K key, @NotNull V value) {
79+
return false;
80+
}
81+
82+
@Override
83+
public boolean replace(@NotNull K key, @NotNull V oldValue, @NotNull V newValue) {
84+
return false;
85+
}
86+
87+
@Override
88+
public @NotNull V getOrDefault(@NotNull K key, @NotNull V defaultValue) {
89+
return defaultValue;
90+
}
91+
92+
@Override
93+
public void putAll(@NotNull Map<? extends K, ? extends V> map) {
94+
// no-op
95+
}
96+
97+
}

core/src/testFixtures/java/io/github/xanthic/cache/core/provider/ProviderTestBase.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,24 @@ public void replaceTest() {
135135
Assertions.assertNull(cache.get("9"));
136136
}
137137

138+
@Test
139+
@DisplayName("Test that caches with zero maximum size remain empty")
140+
public void zeroMaxSizeTest() {
141+
Cache<String, Integer> cache = build(spec -> spec.maxSize(0L));
142+
cache.put("1", 1);
143+
Assertions.assertNull(cache.get("1"));
144+
Assertions.assertEquals(0, cache.size());
145+
}
146+
147+
@Test
148+
@DisplayName("Test that caches with zero time-to-live for entries remain empty")
149+
public void zeroExpiryTimeTest() {
150+
Cache<String, Integer> cache = build(spec -> spec.expiryTime(Duration.ZERO));
151+
cache.put("1", 1);
152+
Assertions.assertNull(cache.get("1"));
153+
Assertions.assertEquals(0, cache.size());
154+
}
155+
138156
@Test
139157
@DisplayName("Test that cache size constraint is respected")
140158
public void sizeEvictionTest() {

0 commit comments

Comments
 (0)