fuel icon indicating copy to clipboard operation
fuel copied to clipboard

Cancellation of coroutine does not always cancel Requests

Open Legion2 opened this issue 3 years ago • 0 comments

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:

  1. Run the following Unit Tests
  2. testCancellableRequest works but testCoroutine 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

Legion2 avatar Dec 31 '20 11:12 Legion2