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

Throwing GravatarException on noncatching service methods #392

Merged
merged 2 commits into from
Oct 16, 2024

Conversation

hamorillo
Copy link
Contributor

Closes #377

Description

We want to wrap all exceptions that can occur inside the Gravatar service methods in our own GravatarException to provide the ErrorType as we do in the catching variants of those methods.

With this approach, we'll provide detailed information about the error, but at the same time, third-party developers know what exceptions can be expected from the Gravatar Services, basically GravatarException.

Testing Steps

  • Code review (including test)
  • Smoke test demo-app (although we are not using nonCatching method there)

@hamorillo hamorillo added enhancement Enhancement :gravatar Gravatar core module labels Oct 15, 2024
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Oct 15, 2024

📲 You can test the changes from this Pull Request in Gravatar Demo by scanning the QR code below to install the corresponding build.
App Name Gravatar Demo
Commit1976a41
Direct Downloadgravatar-demo-prototype-build-pr392-1976a41.apk

We want to wrap all exceptions that can occur inside the Gravatar service methods in our own "GravatarException."

With this approach, we'll provide detailed information about the error, but at the same time, third-party developers know what exceptions can be expected from the Gravatar Services.
@hamorillo hamorillo force-pushed the hamorillo/377-gravatar-exception branch from 27acb45 to add42d2 Compare October 15, 2024 11:50
internal val rawErrorBody: String? = response.errorBody()?.string()
public val code: Int = response.code()
public override val message: String = "HTTP ${response.code()} $rawErrorBody"
internal class HttpException internal constructor(response: Response<*>) : RuntimeException() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We'll use this exception only internally to catch HTTP errors.

Copy link
Contributor

Choose a reason for hiding this comment

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

We are throwing it and passing as originalException, no? Would it make sense to keep it public for that?

Copy link
Contributor Author

@hamorillo hamorillo Oct 16, 2024

Choose a reason for hiding this comment

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

Yeah, it makes sense. I'll revert the changes in this class.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can keep the constructor private - it's for internal use indeed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I kept it as internal. 👍

*
* @property errorMsg The error message, if available.
*/
public class Unknown(public val errorMsg: String? = null) : ErrorType() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it would be nice to provide some information when it is available.

@@ -84,6 +84,7 @@ dependencies {
testImplementation(libs.mockk.android)
testImplementation(libs.mockk.agent)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(kotlin("test"))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Testing the inside of the expected exception with JUnit 4 is not very straightforward, so adding this dependency here makes our life easier.

@hamorillo hamorillo marked this pull request as ready for review October 15, 2024 13:16
Copy link
Contributor

@AdamGrzybkowski AdamGrzybkowski left a comment

Choose a reason for hiding this comment

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

Demo App works fine - I've tried some network errors like 401 to make sure this still works.

Left some minor comments.

internal val rawErrorBody: String? = response.errorBody()?.string()
public val code: Int = response.code()
public override val message: String = "HTTP ${response.code()} $rawErrorBody"
internal class HttpException internal constructor(response: Response<*>) : RuntimeException() {
Copy link
Contributor

Choose a reason for hiding this comment

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

We are throwing it and passing as originalException, no? Would it make sense to keep it public for that?

Comment on lines +33 to -48
public suspend fun retrieve(hashOrUsername: String): Profile? =
@Suppress("TooGenericExceptionCaught")
try {
withContext(GravatarSdkDI.dispatcherIO) {
val response = service.getProfileById(hashOrUsername)
if (response.isSuccessful) {
response.body() ?: error("Response body is null")
} else {
// Log the response body for debugging purposes if the response is not successful
Logger.w(
LOG_TAG,
"Network call unsuccessful trying to get Gravatar profile: ${response.code()}",
)
if (response.code() == HttpResponseCode.HTTP_NOT_FOUND) {
return@withContext null
} else {
throw HttpException(response)
}
}
}
} catch (ex: Exception) {
throw GravatarException(ex.errorType(GravatarSdkContainer.instance.moshi), ex)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason why we can't use runThrowingExceptionRequest here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case, the returned value when 404 is null instead of the exception, so we can't use runThrowingExceptionRequest, which requires not null.

Keep HttpException public, as it is returned as the original exception when an HTTP error occurs.
@hamorillo hamorillo merged commit 10e422f into trunk Oct 16, 2024
17 checks passed
@hamorillo hamorillo deleted the hamorillo/377-gravatar-exception branch October 16, 2024 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhancement :gravatar Gravatar core module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Not catching service functions should throw Gravatar specific exceptions
3 participants