问题
I am using caffeine cache to store an authorisation token that has been obtained using webClient WebFlux. I have set the expireAfterWrite to a hardcoded value in the application.yml file as follows:
spring:
cache:
cache-names: accessTokens
caffeine:
spec: expireAfterWrite=100m
The token is obtained using a WebClient with Spring WebFlux as below code depicts:
@Autowired
var cacheManager: CacheManager? = null
override fun getAuthToken(): Mono<AccessToken> {
val map = LinkedMultiValueMap<String, String>()
map.add("client_id", clientId)
map.add("client_secret", clientSecret)
map.add("grant_type", "client_credentials")
var cachedVersion = this.cacheManager?.getCache("accessTokens");
if (cachedVersion?.get("tokens") != null) {
val token = cachedVersion.get("tokens")
return Mono.just(token?.get() as AccessToken)
} else {
return webClient.post()
.uri("/client-credentials/token")
.body(BodyInserters.fromFormData(map))
.retrieve()
.onStatus(HttpStatus::is5xxServerError) {
ClientLogger.logClientErrorResponse(it, errorResponse)
}
.onStatus(HttpStatus::is4xxClientError) {
ClientLogger.logClientErrorResponse(it, errorResponse)
}
.bodyToMono(AccessToken::class.java)
.doOnNext { response ->
// Set here the expiration time of the cache based on
// response.expiresIn
this.cacheManager?.getCache("accessTokens")?.put("tokens", response) }
.log()
}
}
I am storing the token after the data is emitted/returned successfully within the .doOnNext() method but i need to be able to set the expiration time or refresh the hardcoded expiration time of the cache based on the expiresIn property that is part of the response object,
.doOnNext { response ->
// Set here the expiration time of the cache based on
// response.expiresIn
this.cacheManager?.getCache("accessTokens")?.put("tokens", response)
}
Any ideas would be much appreciated.
回答1:
// Policy to set the lifetime based on when the entry was created
var expiresAfterCreate = new Expiry<String, AccessToken>() {
public long expireAfterCreate(String credentials, AccessToken token, long currentTime) {
Duration duration = token.expiresIn();
return token.toNanos();
}
public long expireAfterUpdate(String credentials, AccessToken token,
long currentTime, long currentDuration) {
return currentDuration;
}
public long expireAfterRead(String credentials, AccessToken token,
long currentTime, long currentDuration) {
return currentDuration;
}
});
// CompletableFuture-based cache
AsyncLoadingCache<String, AccessToken> cache = Caffeine.newBuilder()
.expireAfter(expiresAfterCreate)
.buildAsync((credentials, executor) -> {
Mono<AccessToken> token = retrieve(credentials);
return token.toFuture();
});
// Get from cache, loading if absent, and converts to Mono
Mono<AccessToken> getAuthToken() {
var token = cache.get(credentials);
return Mono.fromFuture(token);
}
来源:https://stackoverflow.com/questions/65823211/set-cache-expireafterwrite-property-dynamically-caffeine-and-spring-webflux