I need to lookup something by id asynchronously an...
# coroutines
s
I need to lookup something by id asynchronously and limit it to one lookup per id. Would something like this be the way to do it?
Copy code
val cache = ConcurrentHashMap<Int, Deferred<String>>()

suspend fun getById(id: Int) : String {
    return cache.computeIfAbsent(id) {
        async { asyncAction(id) }
    }.await()
}

suspend fun asyncAction(id: Int): String = TODO()
d
Why not an
actor
?
w
Also, why use
async
only to immediately
await
? may as well just use
withContext
d
Is
actor
better only because it doesn't block?
ConcurrentHashMap
is less boilerplate imo, and reads are lock free anyway
b
actor isnt' really different, it only helps organize things conceptually, but it's more than you need for this case
suspend fun getById(id: Int) = withContext(CommonPool) { asyncAction(id) }
all you need
d
I don't think that satisfies the initial use case. Also why
withContext
rather than simply running
asyncAction
?
b
based on his first post I assumed he wanted it done on a background thread, but maybe not. what wouldn't it satisfy?
w
Copy code
val cache = ConcurrentHashMap<Int, String>()

suspend fun getById(id: Int) : String {
    return cache.computeIfAbsent(id) {
        withContext(IO_DISPATCHER) { asyncAction(id) }
    }
}

suspend fun asyncAction(id: Int): String = "Some String"
This is probably closer to what you want
d
I mean it wouldn't satisfy the actual thing he wanted to do with the whole
computeIfAbsent
w
looks to me like it will compute the string if it’s missing to me, so either I fundamentally misunderstand compute if absent or I misunderstand the use case
d
sorry, I meant @bj0
b
I didn't notice the
cache
, was focused on the coroutine stuff and assumed the logic was inside
asyncAction
s
@withoutclass does that compile? The compute call blocks the calling thread and it’s closure is not inline so I avoid that with the async call
The asyncAction is io though so I guess that needs another dispatcher. Thx for that :-)
u
The price is, awaiting the deferred on every cache lookup which should be pretty fast if it is already resolved. I'd say fine if it suits your use case
w
Unsure if it compiles I just did a quick and dirty change