JakeWharton/retrofit2-kotlin-coroutines-adapter

Allow returning a Job

PaulWoitaschek opened this issue · 4 comments

For POST of PATCH requests, there is no real value to return.

Therefore I want to suggest to allow returning a kotlinx.coroutines.experimental.Job.
As Deferred implements job, the adapter could just use a Deferred<Unit> internally.

This is a follow-up of #2

Do you accept a PR? My current implementation looks like this:

  override fun get(
    returnType: Type,
    annotations: Array<out Annotation>,
    retrofit: Retrofit
  ): CallAdapter<*, *>? {
    val rawType = getRawType(returnType)
    if (rawType == Job::class.java) {
      return JobCallAdapter()
    }
    if (Deferred::class.java != rawType) {
      return null
    }
    ... 
  private class JobCallAdapter : CallAdapter<Void, Job> {

    override fun responseType() = Void::class.java

    override fun adapt(call: Call<Void>): Job {
      val deferred = CompletableDeferred<Unit>()

      deferred.invokeOnCompletion {
        if (deferred.isCancelled) {
          call.cancel()
        }
      }

      call.enqueue(object : Callback<Void> {
        override fun onFailure(call: Call<Void>, t: Throwable) {
          deferred.completeExceptionally(t)
        }

        override fun onResponse(call: Call<Void>, response: Response<Void>) {
          if (response.isSuccessful) {
            deferred.complete(Unit)
          } else {
            deferred.completeExceptionally(HttpException(response))
          }
        }
      })

      return deferred
    }
  }

I'm about to send a PR 😢

You don't need a separate CallAdapter for this because a Deferred is a Job.

Job is a weird choice here. It doesn't throw when you call join(). How are you expecting to be notified of failure when you are returned a Job?

True :(