fuel
fuel copied to clipboard
Cancellation of coroutine does not always cancel Requests
Bug Report
Description
Making a request (for example a download) with .suspendable().await()
and then canceling the coroutine does not cancel the download request if the download has been started.
val task = async {
"https://github.com/kittinunf/fuel/archive/master.zip"
.httpDownload()
.fileDestination { a, b -> Files.createTempFile("tmp", ".tmp").toFile() }
.suspendable().await()
}
task.cancel()
To Reproduce
Steps to reproduce the behavior:
- Run the following Unit Tests
-
testCancellableRequest
works buttestCoroutine
fails
Note: sometimes .progress
reports -1
for totalBytes
in that case the test will also fail and has the be restarted
import com.github.kittinunf.fuel.core.requests.suspendable
import com.github.kittinunf.fuel.httpDownload
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.Test
import java.nio.file.Files
import java.util.concurrent.atomic.AtomicBoolean
class Test {
@Test
fun testCoroutine() {
val startedDownload = AtomicBoolean(false)
val finishedDownload = AtomicBoolean(false)
runBlocking {
val task = async {
"https://github.com/kittinunf/fuel/archive/master.zip"
.httpDownload()
.fileDestination { a, b -> Files.createTempFile("tmp", ".tmp").toFile() }
.progress { a, b ->
if (b == -1L) finishedDownload.set(true)
startedDownload.set(true)
println("$a, $b")
if (a == b) finishedDownload.set(true)
}
.suspendable().await()
}
while (!startedDownload.get()) delay(1)
task.cancel()
println("cancel called")
task.join()
assertFalse(finishedDownload.get())
}
}
@Test
fun testCancellableRequest() {
val startedDownload = AtomicBoolean(false)
val finishedDownload = AtomicBoolean(false)
runBlocking {
val cancellableRequest =
"https://github.com/kittinunf/fuel/archive/master.zip"
.httpDownload()
.fileDestination { a, b -> Files.createTempFile("tmp", ".tmp").toFile() }
.progress { a, b ->
if (b == -1L) finishedDownload.set(true)
startedDownload.set(true)
println("$a, $b")
if (a == b) finishedDownload.set(true)
}
.response { result ->
fail()
}
while (!startedDownload.get()) delay(1)
cancellableRequest.cancel()
println("cancel called")
cancellableRequest.join()
assertFalse(finishedDownload.get())
}
}
}
Expected behavior
Canceling the coroutine/job which executes the request (also when the cancelation is propagated) should cancel the request, also when the download of the response has already been started.
Environment
Development Machine
Complete the following information if applicable
- OS: Windows 10
- IDE: Android Studio
- Fuel version: 2.3.1
- Kotlin version: 1.4.21
Additional context
There where similar issues in the past #516, #429 and fixes #355. But there were refactorings which I think removed the cancellation feature https://github.com/kittinunf/fuel/issues/429#issuecomment-748649897