-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathCacheConfig.java
123 lines (111 loc) · 5.11 KB
/
CacheConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package com.faforever.api.config;
import com.faforever.api.config.elide.ElideConfig;
import com.faforever.api.data.domain.Achievement;
import com.faforever.api.data.domain.Avatar;
import com.faforever.api.data.domain.Clan;
import com.faforever.api.data.domain.CoopMap;
import com.faforever.api.data.domain.CoopResult;
import com.faforever.api.data.domain.CoopScenario;
import com.faforever.api.data.domain.Event;
import com.faforever.api.data.domain.FeaturedMod;
import com.faforever.api.data.domain.Game;
import com.faforever.api.data.domain.Leaderboard;
import com.faforever.api.data.domain.LeaderboardRating;
import com.faforever.api.data.domain.Map;
import com.faforever.api.data.domain.MapVersion;
import com.faforever.api.data.domain.Mod;
import com.faforever.api.data.domain.ModVersion;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.interceptor.AbstractCacheResolver;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.HandlerMapping;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static com.faforever.api.challonge.ChallongeController.CHALLONGE_READ_CACHE_NAME;
import static com.faforever.api.featuredmods.FeaturedModService.FEATURED_MOD_FILES_CACHE_NAME;
import static com.github.benmanes.caffeine.cache.Caffeine.newBuilder;
import static java.util.concurrent.TimeUnit.MINUTES;
@EnableCaching(proxyTargetClass = true)
@Configuration
@Profile({ApplicationProfile.PRODUCTION, ApplicationProfile.TRAINING})
public class CacheConfig {
/**
* To be used when there is only one "main" request (e.g. show full list) and not many deviations exist
*/
private static final long SMALL_SIZE = 25;
/**
* To be used when there is one "main" request we want to cache (e.g. show full list) but there are
* deviating queries that might overwrite the main request.
*/
private static final long MEDIUM_SIZE = 50;
/**
* To be used when many recurring calls expected (e.g. maps and mods in open lobbies)
*/
private static final long BIG_SIZE = 100;
@Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(List.of(
// Elide entity caches
new CaffeineCache(ElideConfig.DEFAULT_CACHE_NAME, newBuilder().maximumSize(0).build()),
buildCache(Avatar.TYPE_NAME, 5, MINUTES, SMALL_SIZE),
buildCache(Achievement.TYPE_NAME, 60, MINUTES, SMALL_SIZE),
buildCache(Clan.TYPE_NAME, 5, MINUTES, SMALL_SIZE),
buildCache(CoopResult.TYPE_NAME, 5, MINUTES, MEDIUM_SIZE),
buildCache(CoopScenario.TYPE_NAME, 5, MINUTES, SMALL_SIZE),
buildCache(CoopMap.TYPE_NAME, 5, MINUTES, MEDIUM_SIZE),
buildCache(Event.TYPE_NAME, 60, MINUTES, SMALL_SIZE),
buildCache(FeaturedMod.TYPE_NAME, 60, MINUTES, SMALL_SIZE),
buildCache(Game.TYPE_NAME, 2, MINUTES, BIG_SIZE),
buildCache(Map.TYPE_NAME, 60, MINUTES, BIG_SIZE),
buildCache(MapVersion.TYPE_NAME, 60, MINUTES, BIG_SIZE),
buildCache(Mod.TYPE_NAME, 60, MINUTES, BIG_SIZE),
buildCache(ModVersion.TYPE_NAME, 60, MINUTES, BIG_SIZE),
// Other caches
buildCache(CHALLONGE_READ_CACHE_NAME, 5, MINUTES, SMALL_SIZE),
buildCache(FEATURED_MOD_FILES_CACHE_NAME, 5, MINUTES, MEDIUM_SIZE),
buildCache(Leaderboard.TYPE_NAME, 2, MINUTES, SMALL_SIZE),
buildCache(LeaderboardRating.TYPE_NAME, 2, MINUTES, SMALL_SIZE)
));
return cacheManager;
}
private CaffeineCache buildCache(String key, long duration, TimeUnit unit, long maxSize) {
return new CaffeineCache(
key,
newBuilder()
.expireAfterWrite(duration, unit)
.maximumSize(maxSize)
.build()
);
}
/**
* Returns a cache resolver that resolves cache names by JSON API type names. For instance, the type "map" will be
* resolved to a cache named "map". If no dedicated cache config is available, the "default" config will be applied.
*/
@Bean
public CacheResolver elideCacheResolver(CacheManager cacheManager) {
return new AbstractCacheResolver(cacheManager) {
@Override
protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
String entity = getEntity((HttpServletRequest) context.getArgs()[1]);
if (!cacheManager.getCacheNames().contains(entity)) {
return List.of(ElideConfig.DEFAULT_CACHE_NAME);
}
return List.of(entity);
}
};
}
@SuppressWarnings("unchecked")
private String getEntity(HttpServletRequest request) {
return (String) ((java.util.Map<String, Object>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE)).get("entity");
}
}