Skip to content

Commit

Permalink
Merge pull request #929 from ably/feature/retry-ably-operations-core
Browse files Browse the repository at this point in the history
Add methods for detecting retriable and fatal Ably exceptions
  • Loading branch information
QuintinWillison authored Jan 23, 2023
2 parents 824dcd0 + 2073683 commit 8b02b88
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
16 changes: 16 additions & 0 deletions common/src/main/java/com/ably/tracking/common/AblyHelpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,19 @@ private fun TokenAuthException.toAblyException(): AblyException =
is CouldNotFetchTokenException ->
AblyException.fromErrorInfo(ErrorInfo(message, 401, 100_002))
}

/**
* Indicates whether the exception from Ably is fatal and we should not attempt to retry it.
* Fatal errors have status codes like 4xx (e.g. 400).
*/
fun ConnectionException.isFatal(): Boolean {
return (400..499).contains(errorInformation.statusCode)
}

/**
* Indicates whether the exception from Ably is retriable and we can attempt to retry it.
* Non-fatal errors have status codes in range 500-504.
*/
fun ConnectionException.isRetriable(): Boolean {
return (500..504).contains(errorInformation.statusCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.ably.tracking.common

import com.ably.tracking.ConnectionException
import com.ably.tracking.ErrorInformation
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized

@RunWith(Parameterized::class)
class ConnectionExceptionTests(
private val statusCode: Int,
private val isFatal: Boolean,
private val isRetriable: Boolean,
) {

companion object {
@JvmStatic
@Parameterized.Parameters(
name = "Status code: {0} | Is fatal: {1} | Is retriable: {2}"
)
fun data() = listOf(
params(
statusCode = 399,
isFatal = false,
isRetriable = false,
),
params(
statusCode = 400,
isFatal = true,
isRetriable = false,
),
params(
statusCode = 499,
isFatal = true,
isRetriable = false,
),
params(
statusCode = 500,
isFatal = false,
isRetriable = true,
),
params(
statusCode = 504,
isFatal = false,
isRetriable = true,
),
params(
statusCode = 505,
isFatal = false,
isRetriable = false,
),
)

private fun params(statusCode: Int, isFatal: Boolean, isRetriable: Boolean) =
arrayOf(statusCode, isFatal, isRetriable)
}

@Test
fun `exception should be treated as fatal if its status code is between 400 and 499`() {
// given
val exception = createConnectionException(statusCode)

// when
val result = exception.isFatal()

// then
Assert.assertEquals(isFatal, result)
}

@Test
fun `exception should be treated as retriable if its status code is between 500 and 504`() {
// given
val exception = createConnectionException(statusCode)

// when
val result = exception.isRetriable()

// then
Assert.assertEquals(isRetriable, result)
}

private fun createConnectionException(statusCode: Int): ConnectionException =
ConnectionException(ErrorInformation(0, statusCode, "Test exception", null, null))
}

0 comments on commit 8b02b88

Please sign in to comment.