I am writing a suspend-based wrapper around Caffeine's AsyncLoadingCache, which natively understands cache-loading functions that return CompletableFutures. My class has a
get()
method which launches a coroutine using
CoroutineScope.future{}
. That coroutine should not be scoped to the
get()
method's lifetime, because if
get()
is called concurrently with the same key, both
get()
calls will end up waiting on the same CompletableFuture, so cancelling the first coroutine shouldn't cause the second coroutine to fail. So I'm currently passing a
CoroutineScope
into the constructor of the cache and using that to launch the `future`s.
However, my current implementation means that if any of the calls inside
future{}
fail, the long-lived CoroutineScope associated with the cache is canceled, which I don't want. What I want basically is a supervisor scope nested inside the passed-in CoroutineScope, created at cache construction time. But
supervisorScope
doesn't seem to be what I want — I can't call that at cache construction time because I don't want to actually wait before returning like a supervisorScope does! Is there some other API I should be using here? I feel like maybe the answer is
SupervisorJob()
but I am still kinda confused about the distinction between Job and CoroutineScope — I can make a
SupervisorJob(coroutineScope.coroutineContext[Job])
but I'm confused about how to extract a CoroutineScope from it that I can use for launching coroutines.