Skip to content

Commit 5cffb22

Browse files
authored
Merge pull request #1189 from modelix/feature/configurable-model-client-retries
feat(model-client): make retries configurable
2 parents 88494bf + bee9c09 commit 5cffb22

File tree

2 files changed

+68
-10
lines changed

2 files changed

+68
-10
lines changed

model-client/src/commonMain/kotlin/org/modelix/model/client2/ModelClientV2.kt

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,9 @@ abstract class ModelClientV2Builder {
499499
protected var connectTimeout: Duration = 1.seconds
500500
protected var requestTimeout: Duration = 30.seconds
501501

502+
// 0 and 1 mean "disable retries"
503+
protected var retries: UInt = 3U
504+
502505
fun build(): ModelClientV2 {
503506
return ModelClientV2(
504507
httpClient?.config { configureHttpClient(this) } ?: createHttpClient(),
@@ -537,6 +540,16 @@ abstract class ModelClientV2Builder {
537540
return this
538541
}
539542

543+
/**
544+
* Configures the number of retries to be performed in case a request has failed.
545+
*
546+
* @param num 0 to disable the retry mechanism
547+
*/
548+
fun retries(num: UInt): ModelClientV2Builder {
549+
this.retries = num
550+
return this
551+
}
552+
540553
protected open fun configureHttpClient(config: HttpClientConfig<*>) {
541554
config.apply {
542555
expectSuccess = true
@@ -548,17 +561,19 @@ abstract class ModelClientV2Builder {
548561
connectTimeoutMillis = connectTimeout.inWholeMilliseconds
549562
requestTimeoutMillis = requestTimeout.inWholeMilliseconds
550563
}
551-
install(HttpRequestRetry) {
552-
retryOnExceptionOrServerErrors(maxRetries = 3)
553-
exponentialDelay()
554-
modifyRequest {
555-
try {
556-
// connectionStatus = ConnectionStatus.SERVER_ERROR
557-
this.response?.call?.client?.coroutineContext?.let { CoroutineScope(it) }?.launch {
558-
response?.let { println(it.bodyAsText()) }
564+
if (retries > 1U) {
565+
install(HttpRequestRetry) {
566+
retryOnExceptionOrServerErrors(maxRetries = retries.toInt())
567+
exponentialDelay()
568+
modifyRequest {
569+
try {
570+
// connectionStatus = ConnectionStatus.SERVER_ERROR
571+
this.response?.call?.client?.coroutineContext?.let { CoroutineScope(it) }?.launch {
572+
response?.let { println(it.bodyAsText()) }
573+
}
574+
} catch (e: Exception) {
575+
LOG.debug(e) { "" }
559576
}
560-
} catch (e: Exception) {
561-
LOG.debug(e) { "" }
562577
}
563578
}
564579
}

model-client/src/commonTest/kotlin/org/modelix/model/client2/ModelClientV2Test.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import io.ktor.client.HttpClient
1919
import io.ktor.client.engine.mock.MockEngine
2020
import io.ktor.client.engine.mock.respond
2121
import io.ktor.client.engine.mock.respondError
22+
import io.ktor.client.plugins.ServerResponseException
2223
import io.ktor.http.HttpHeaders
2324
import io.ktor.http.HttpStatusCode
2425
import io.ktor.http.headersOf
@@ -70,4 +71,46 @@ class ModelClientV2Test {
7071
modelClient.pull(branchRef, null)
7172
}
7273
}
74+
75+
@Test
76+
fun retriesCanBeConfigured() = runTest {
77+
val url = "http://localhost/v2"
78+
val mockEngine = MockEngine {
79+
respondError(HttpStatusCode.InternalServerError)
80+
}
81+
val retries = 2U
82+
val httpClient = HttpClient(mockEngine)
83+
val modelClient = ModelClientV2.builder()
84+
.client(httpClient)
85+
.retries(retries)
86+
.url(url)
87+
.build()
88+
89+
assertFailsWith<ServerResponseException> {
90+
modelClient.init()
91+
}
92+
93+
// We receive one initial request and then the configured number of retries.
94+
assertEquals(1 + retries.toInt(), mockEngine.requestHistory.size)
95+
}
96+
97+
@Test
98+
fun retriesCanBeDisabled() = runTest {
99+
val url = "http://localhost/v2"
100+
val mockEngine = MockEngine {
101+
respondError(HttpStatusCode.InternalServerError)
102+
}
103+
val httpClient = HttpClient(mockEngine)
104+
val modelClient = ModelClientV2.builder()
105+
.client(httpClient)
106+
.retries(0U)
107+
.url(url)
108+
.build()
109+
110+
assertFailsWith<ServerResponseException> {
111+
modelClient.init()
112+
}
113+
114+
assertEquals(1, mockEngine.requestHistory.size)
115+
}
73116
}

0 commit comments

Comments
 (0)