rogercaplan
11/21/2024, 12:10 AMinterface Repo {
/*
1) concurrent calls to this method will not result in duplicate requests for the same url
2) the more callers waiting on a url, the higher priority the underlying remote request
3) if a caller's scope is cancelled, the priority of the underlying remote request is lowered
4) if all callers' scopes are cancelled, the remote request is cancelled
*/
suspend fun fetch(url: String): String
}
(I realize I could accomplish this using a SharedFlow
but I’d rather expose a suspend fun that returns a scalar value)
This is what I was thinking of doing to implement this - basically using a Deferred.invokeOnCompletion
to “catch” the caller’s scope being cancelled:
class Repo() {
// something to keep track of callers/priority
val priorities
// the actual remote request - runs in its own scope
fun getOrCreateFetchJob(String): Deferred<String>
suspend fun fetch(url: String): String =
CoroutineScope(currentCoroutineContext()).async {
priorities.increase(url)
getOrCreateFetchJob(url).await()
}.also {
it.invokeOnCompletion {
priorities.decrease(url)
}
}.await()
Does this make sense? Is there a better approach?asdf asdf
11/21/2024, 12:32 AMasdf asdf
11/21/2024, 12:34 AMasdf asdf
11/21/2024, 12:36 AMephemient
11/21/2024, 12:46 AMinvokeOnCompletion
, just use
priorities.increase(url)
try {
...
} finally {
priorities.decrease(url)
}
Sam
11/21/2024, 7:57 AMfetch
function to users; just use the flow as an internal implementation detail.rogercaplan
11/21/2024, 3:00 PMWhat does a request having “higher priority” mean exactly in this case?well, that’s ultimately up to the data fetching implementation (my example above is misleading in that respect since
priorities
is in the repo), but the plan is to send these as http priority hints