'Shared lazy coroutine / memoized coroutine execution
Context:
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
data class DatabaseData(
val a: String,
val b: String
)
interface DatabaseFetcher {
suspend fun get(): DatabaseData
}
class MyClass(
private val databaseFetcher: DatabaseFetcher
) {
suspend fun a() = coroutineScope {
val a = async { databaseFetcher.get().a }
//imagine more async{}'s here
a //imagine a gets computed in regards to the other async{}'s as well
}
suspend fun b() = databaseFetcher.get().b
}
class MyController(private val databaseFetcher: DatabaseFetcher) {
suspend fun someFun() = coroutineScope {
// the reduced example doesn't need a coroutineScope of course, imagine some async{} here
MyClass(databaseFetcher)
}
}
I am trying to call databaseFetcher.get() only once if either a() or b() are called on MyClass. Basically a lazy future that gets started when either a() or b() is called, but with coroutines.
What I have tried so far:
- Can't use
by lazy{}as thecoroutineScopematters here and I can't usewithContext(Dispatchers.IO)as I use a custom Context (multithreading, Spring request scoped data etc.) - passing my context in here seems awkward (would it be bad practice?) - I can't pass an
async(start = CoroutineStart.LAZY)when constructingMyClassas it would block indefinitely if theDeferred<T>is neverawait()ed on, which may happen when neithera()orb()is called. It also blocks indefinitely because the correspondingcoroutineScopeis constructed whenMyClassis constructed which would block asa()andb()are called later afterMyClasshas been fully constructed because (as I understand) acoroutineScopeis only unblocked when all its children are done, which doesn't hold true for a lazy async thats awaited outside the curent scope - Using a wider coroutine context may leak when the lazy async is never awaited - is this true? I couldn't find much about this
This is being done in the context of GraphQL wherein either a b or both can be selected. There are boilerplatey solutions to this but as I am still learning about coroutines I wondered if there is an elegant solution to this which I don't see yet. The CoroutineStart.LAZY issue really caught me by surprise :)
kotlinkotlin-coroutinesamazon-web-services">
amazon-web-servicesazureamazon-cloudformation">
amazon-cloudformationdevops
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
