Reputation: 594
since I cannot use Caffeine and Spring Boot annotations (@Cacheable etc..) with Kotlin suspend functions, I am trying to implement it manually.
I have this method to retrieve a Shopping Cart from a cookie value:
@CacheConfig(cacheNames = ["shopping-cart"])
class ShoppingCartService {
suspend fun getShoppingCartWithItemsCount(cartCookieValue: String?): ShoppingCart {
if (cartCookieValue == null) return ShoppingCart(-1)
return cacheManager.getCache("shopping-cart")?.get<ShoppingCart>(cartCookieValue).also { shoppingCart ->
if (shoppingCart == null) log.info("Shopping cart with id $cartCookieValue not found in cache")
else log.info("Shopping with id $cartCookieValue found in cache")
} ?: suspend {
return getShoppingCart(cartCookieValue)
}.also {
log.info("Add to cache key $cartCookieValue")
cacheManager.getCache("shopping-cart")?.put(cartCookieValue, it)
}
?: run { throw RuntimeException("Invalid shopping cart") }
shoppingCart
}.invoke()
}
}
I have added this to the application.yml
file:
spring.cache:
cache-names: shopping-cart
caffeine.spec: maximumSize=500,expireAfterAccess=600s
And this configuration:
@EnableCaching
...
@Bean
fun cacheManager(): CacheManager {
val cacheManager = CaffeineCacheManager()
cacheManager.setCaffeine(caffeineCacheBuilder())
return cacheManager
}
@Bean
fun caffeineCacheBuilder(): Caffeine<Any, Any> {
return Caffeine.newBuilder()
.maximumSize(500)
.expireAfterWrite(10, TimeUnit.MINUTES)
.weakKeys()
.recordStats()
}
Unfortunately I keep getting in the logs this message. Meaning that even if the key is exactly the same, it is duplicated in the cache:
2023-10-21T22:55:17.110+02:00 INFO 90127 --- [actor-tcp-nio-1] c.s.c.s.c.ShoppingCartService : Add to cache key MTM3OjE2OTcyMjI0jEzMTI6OWVmNzlmYTc1YzY0ZGU0NTFiMDJhOTQ3NWE5NGQzYTkyZWVkMzlhZjZhNGMzZGMzZTI1Y0NmE3MGU4YzNiNQ==
Why? And how to resolve? Thanks
EDIT:
Using Deferred it works:
@Cacheable(sync = true, key = "#cartCookieValue")
fun getShoppingCartWithItemsCount(cartCookieValue: String?): Deferred<ShoppingCart> =
CoroutineScope(Dispatchers.Default).async {
delay(5000)
cartCookieValue?.let { value ->
return getShoppingCart(value)
} ?: ShoppingCart(-1)
}
Upvotes: 0
Views: 430