https://kotlinlang.org logo
#coroutines
Title
# coroutines
s

Sam Garfinkel

03/25/2020, 2:24 PM
What this answer says is correct--you can store the
Deferred
in the cache as
Deferred
is a coroutine-safe data structure (via suspendable
await
). However directly manipulating a cache from a coroutine is likely unsafe. Note though that calling
await
on an already complete
Deferred<T>
is free and trivially returns the underlying
T
.
r

rrva

03/25/2020, 7:50 PM
how do I pass the correct coroutine scope to the load function
Is this a correct way of specifying scope, having the same scope for all http calls
Copy code
class FooCoroutinesClient(private val fooUrl: String, val userAgent: String) {

    val coroutineScope = CoroutineScope(Dispatchers.Default)

    private val cache: LoadingCache<String, Deferred<FooResponse>> =
        Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(30, TimeUnit.SECONDS)
            .build { key -> coroutineScope.async { doFetchFoo(key) } }

    val client = HttpClient(Apache) {
        engine {
            connectionRequestTimeout = 400
        }
        install(HttpTimeout){
            connectTimeoutMillis = 400
            socketTimeoutMillis = 100
        }
        install(JsonFeature) {
            serializer = KotlinxSerializer(
                Json(
                    JsonConfiguration(
                        isLenient = true,
                        ignoreUnknownKeys = true,
                        serializeSpecialFloatingPointValues = true,
                        useArrayPolymorphism = true
                    )
                )
            )
        }
    }

    suspend fun doFetchFoo(query: String): FooResponse {
        return client.request {
            header("User-Agent", userAgent)
            parameter("query", query)
            url("$fooUrl/v1/foo")
        }
    }

    suspend fun fetchFoo(query: String): FooResponse {
        return cache.get(query)?.await()!!
    }
}
s

Sam Garfinkel

03/31/2020, 6:03 PM
Inject the scope as a constructor argument--it should be provided by the parent scope. Creating multiple independent coroutine scopes is a bad pattern. Otherwise, what are you trying to cache here? My only observation is that
suspend fun doFetchFoo
should definitely be private and only called from
fetchQuery
.
7 Views