Coroutine-variant is throwing while blocking equivalent is not
See original GitHub issueI’m implementing some kind of custom caching. Because of this 304 is an interesting response for me. When getting the Triple
from .response()
I correctly get a Result
, which is a failure. When using .awaitResponse()
the continuation is throwing instead. Of course I could try-catch the FuelError
, but I believe changing Fuels behaviour so that the coroutine-case matches the default case makes more sense.
My code looks like this:
class CachedHttpLineSource(private val prefs: Prefs, private val uri: String, private val userName: String, private val password: String, private val cacheDir: File) : LineSource() {
@Serializable
data class CachedFile(val uri: String, val etag: String?, val savedPath: String)
private fun getDownloadRequest(etag: String? = null): Request {
val req = Fuel.download(uri).authenticate(userName, password)
if (etag == null) return req
return req.header("If-None-Match" to etag)
}
private suspend fun download(etag: String? = null): CachedFile {
val file = File(cacheDir, uri.sha1())
if (file.exists()) file.delete()
val triple = getDownloadRequest(etag).destination { _, _ -> file }.awaitResponse() // does throw here
val response = triple.second
val result = triple.third
when (result) {
is Result.Failure -> { throw(result.getException()) } // should throw here
is Result.Success -> { return CachedFile(uri, response.headers["ETag"]?.firstOrNull(), file.absolutePath) }
}
}
}
Looking into Coroutines.kt
reveals the problem. Using fold
for all cases instead of just returning the Triple
seems wrong. As far as I understand it could work to just remove the fold
ing and resume with the Triple
in any case as the .third.get()
should throw the exception in the relevant cases too.
// line 23
response(deserializable) { request: Request, response: Response, result: Result<T, FuelError> ->
result.fold({
continuation.resume(Triple(request, response, result))
}, {
continuation.resumeWithException(it.exception)
})
}
// line 32
suspend fun Request.awaitResponse(): Triple<Request, Response, Result<ByteArray, FuelError>> =
await(byteArrayDeserializer())
// line 43
suspend fun Request.awaitResponseResult(): ByteArray = awaitResponse().third.get()
Issue Analytics
- State:
- Created 5 years ago
- Comments:6
Top Results From Across the Web
Exceptions in coroutines. Cancellation and Exceptions in…
When a coroutine fails with an exception, it will propagate said exception up to its parent! Then, the parent will 1) cancel the...
Read more >Coroutines (C++20) - cppreference.com
A coroutine is a function that can suspend execution to be resumed later. Coroutines are stackless: they suspend execution by returning to the...
Read more >Are Kotlin Coroutines Enough to Replace RxJava? - JVM Advent
Both are a stream of 0..N events and the main difference between the two is that the Flowable is backpressure aware while the...
Read more >C++ Coroutines: Understanding Symmetric Transfer
Assume we have a simple task type that lazily executes the body when another coroutine awaits it. This particular task type does not...
Read more >Kotlin Coroutines vs Java Virtual Threads — A good story, but ...
When Kotlin came to the scene I was almost immediately sold out to the idea of it being ... Other IO operations are...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@georg-jung The pull request #373 has been merged and should solve this issue.
@D-A-R Now I see what you mean there. Thank you for the clarification. So it seems that it’s related to the other issue.