sksamuel / aedile

Kotlin Wrapper for Caffeine
Apache License 2.0
164 stars 15 forks source link

get(key: K, compute: suspend (K) -> V ) doesn't support `compute` function that returns null #21

Closed shlomitArgov closed 9 months ago

shlomitArgov commented 11 months ago

According to the documentation for get

If the specified key is not already associated with a value, attempts to compute its value and enters it into this cache unless null.

However, when I create a cache with non-nullable values and try to update it using a compute function that can return null I get a compilation error: (scratch file showing the compilation error)


import com.sksamuel.aedile.core.Cache
import com.sksamuel.aedile.core.caffeineBuilder
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

val cache: Cache<String, String> = caffeineBuilder<String, String>().build()

suspend fun foo(): String? {
    return cache.get("key") { _ -> asyncFun("a") }
}

suspend fun asyncFun(s: String): String? {
    delay(1)
    when (s) {
        "a" -> return null
        else -> return s
    }
}

fun main() {
    runBlocking {
        println("key = ${foo()}")
    }
}

main()

Compilation error is on asyncFun:

Type mismatch. Required: String Found: String?

Changing the type of the cache to <String, String?> results in null being saved to the cache (not the desired behavior):

import com.sksamuel.aedile.core.Cache
import com.sksamuel.aedile.core.caffeineBuilder
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

val cache: Cache<String, String?> = caffeineBuilder<String, String?>().build()

suspend fun foo(): String? {
    return cache.get("key") { _ -> asyncFun("a") }
}

suspend fun asyncFun(s: String): String? {
    delay(1)
    when (s) {
        "a" -> return null
        else -> return s
    }
}

fun main() {
    runBlocking {
        println("key = ${foo()}")
    }
}

main()
sksamuel commented 9 months ago

1.3.1 is released with a getOrNull method that allows nulls.