Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine error callbacks #377

Merged
merged 4 commits into from Feb 21, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 0 additions & 47 deletions api/src/main/java/com/vimeo/networking2/ApiResponse.kt

This file was deleted.

25 changes: 5 additions & 20 deletions api/src/main/java/com/vimeo/networking2/VimeoCallback.kt
Expand Up @@ -10,29 +10,14 @@ interface VimeoCallback<ResponseType_T> {
*
* @param response Data returned by the API.
*/
fun onSuccess(response: ApiResponse.Success<ResponseType_T>)
fun onSuccess(response: VimeoResponse.Success<ResponseType_T>)

/**
* An error occurred on the API. [apiError] contains information about the error that occurred.
* An error occurred when making the request.
*
* @param apiError Information on the error returned by API.
* @param error Information on the error. This error could be due to an exception thrown or
* parsing response error.
*/
fun onApiError(apiError: ApiResponse.Failure.ApiFailure)

/**
* Generic error occurred. This occurred was not caused by the API rather it was due to
* parsing the data or the response body was null.
*
* @param genericFailure The response code of the API request.
*/
fun onGenericError(genericFailure: ApiResponse.Failure.GenericFailure)

/**
* An exception occurred by Retrofit in the API request.
*
* @param exceptionFailure The exception thrown by Retrofit for the request.
*/
fun onExceptionError(exceptionFailure: ApiResponse.Failure.ExceptionFailure)
fun onError(error: VimeoResponse.Error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good for both Java and Kotlin consumers!


}

52 changes: 52 additions & 0 deletions api/src/main/java/com/vimeo/networking2/VimeoResponse.kt
@@ -0,0 +1,52 @@
package com.vimeo.networking2

import com.vimeo.networking2.VimeoResponse.Error
import com.vimeo.networking2.VimeoResponse.Success

/**
* Result of the API response. [Success] contains the data while the [Error] class will
* inform you of an api error.
*/
sealed class VimeoResponse<out T> {

/**
* A successful response.
*
* @param data The parsed data for the request.
*/
data class Success<out T>(val data: T) : VimeoResponse<T>()

/**
* An error occurred when making the request. This error may be due to invalid parameters,
* exception thrown when making the request or there was an error parsing the response.
*
* @param message The error message.
*/
sealed class Error(val message: String): VimeoResponse<Nothing>() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥


/**
* Vimeo API returned an error response for the request you made.
*
* @param reason Info on the error.
*/
data class Api(val reason: ApiError): Error("API error: ${reason.errorCode ?: "unknown"}")

/**
* Exception was thrown when making the request. This maybe due to no internet.
*
* @param throwable Info on the exception that was thrown.
*/
data class Exception(val throwable: Throwable): Error("Exception thrown")

/**
* Generic error occurred. The request was successful, but the response could not be
* parsed by the SDK. This maybe because it is not formatted correctly. The raw response
* will allows you to see the info about the request.
*
* @param rawResponse Raw response from the API.
*/
data class Generic(val rawResponse: String): Error("Generic error")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are certain APIs that require knowledge about the HTTP status code (e.g. 404, 401, 500) of an error. Such APIs include:

  • Adding a video to a channel, which performs a check to see if the video is in the channel and a 404 indicates that it is not in the channel.
  • Editing video settings, where a 404 indicates that the video was deleted.
  • Adding a comment to a video, where a 404 indicates that the video was deleted.
  • Playing a DRM protected video, where a 403 indicates that the device limit has been exceeded.

If we don't expose at least the error code here, it will be more difficult for consumers to use certain APIs. Of course in most cases, the specifics of the error are not important to the UI, but our consuming code often makes certain decisions based on that error code, so I would suggest adding the code in addition to the raw response.


}

}
Expand Up @@ -26,30 +26,37 @@ internal class VimeoCallAdapter<T>(
) : VimeoCall<T> {

override fun enqueue(callback: VimeoCallback<T>): VimeoRequest {

call.enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {

if (response.hasBody()) {
callbackExecutor.sendResponse { callback.onSuccess(ApiResponse.Success(response.body()!!)) }
callbackExecutor.sendResponse {
callback.onSuccess(VimeoResponse.Success(response.body()!!))
}
} else {
val apiError = response.parseApiError()
if (apiError != null) {
callbackExecutor.sendResponse { callback.onApiError(ApiResponse.Failure.ApiFailure(apiError)) }
callbackExecutor.sendResponse {
callback.onError(VimeoResponse.Error.Api(apiError))
}
} else {
callbackExecutor.sendResponse { callback.onGenericError(ApiResponse.Failure.GenericFailure(response.code())) }
callbackExecutor.sendResponse {
callback.onError(VimeoResponse.Error.Generic(response.raw().toString()))
}
}
}
}

override fun onFailure(call: Call<T>, t: Throwable) {
callbackExecutor.sendResponse { callback.onExceptionError(ApiResponse.Failure.ExceptionFailure(t)) }
callbackExecutor.sendResponse { callback.onError(VimeoResponse.Error.Exception(t)) }
}
})
return CancellableVimeoRequest(call)
}

override fun enqueueError(apiError: ApiError, callback: VimeoCallback<T>): VimeoRequest {
callbackExecutor.sendResponse { callback.onApiError(ApiResponse.Failure.ApiFailure(apiError)) }
callbackExecutor.sendResponse { callback.onError(VimeoResponse.Error.Api(apiError)) }
return NoOpVimeoRequest
}

Expand Down
12 changes: 2 additions & 10 deletions auth/src/main/java/com/vimeo/networking2/Authenticator.kt
Expand Up @@ -24,19 +24,11 @@ import okhttp3.Credentials
* val authenticator = Authenticator.create(serverConfig)
* authenticator.clientCredentials(object: VimeoCallback<BasicAuthToken>() {
*
* override fun onSuccess(authResponse: ApiResponse.Success<BasicAuthToken>) {
* override fun onSuccess(authResponse: VimeoResponse.Success<BasicAuthToken>) {
*
* }
*
* override fun onGenericError(genericFailure: ApiResponse.Failure.GenericFailure) {
*
* }
*
* override fun onApiError(apiFailure: ApiResponse.Failure.ApiFailure) {
*
* }
*
* override fun onExceptionError(exceptionFailure: ApiResponse.Failure.ExceptionFailure) {
* override fun onError(error: VimeoResponse.Error) {
*
* }
* })
Expand Down
Expand Up @@ -3,10 +3,10 @@ package com.vimeo.vimeonetworking2.playground
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.vimeo.moshiexampleandroid.R
import com.vimeo.networking2.ApiResponse
import com.vimeo.networking2.Authenticator
import com.vimeo.networking2.BasicAccessToken
import com.vimeo.networking2.VimeoCallback
import com.vimeo.networking2.VimeoResponse
import com.vimeo.networking2.config.ServerConfig
import kotlinx.android.synthetic.main.activity_main.*

Expand All @@ -21,26 +21,16 @@ class MainActivity : AppCompatActivity() {
val serverConfig = ServerConfig(CLIENT_ID, CLIENT_SECRET)
val authenticator = Authenticator.create(serverConfig)

authenticator.clientCredentials(object: VimeoCallback<BasicAccessToken> {
override fun onSuccess(response: ApiResponse.Success<BasicAccessToken>) {
authenticator.clientCredentials(object : VimeoCallback<BasicAccessToken> {
override fun onSuccess(response: VimeoResponse.Success<BasicAccessToken>) {

}

override fun onApiError(apiError: ApiResponse.Failure.ApiFailure) {

}

override fun onGenericError(genericFailure: ApiResponse.Failure.GenericFailure) {

}

override fun onExceptionError(exceptionFailure: ApiResponse.Failure.ExceptionFailure) {
override fun onError(error: VimeoResponse.Error) {

}
})

}

}

companion object {
Expand Down