Skip to content

Commit c051953

Browse files
committed
feat: Add retry logic to our custom WebClient
The change aims to resolve Connection reset by peer error which appears from time to time while establishing tcp connection with the authentication server.
1 parent 0567d6c commit c051953

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

gooddata-server-oauth2-autoconfigure/src/main/kotlin/ReactiveCommunicationClientsConfiguration.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package com.gooddata.oauth2.server
1717

1818
import io.netty.channel.ChannelOption
1919
import java.time.Duration
20+
import org.slf4j.LoggerFactory
2021
import org.springframework.boot.context.properties.EnableConfigurationProperties
2122
import org.springframework.context.annotation.Bean
2223
import org.springframework.context.annotation.Configuration
@@ -37,9 +38,11 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser
3738
import org.springframework.security.oauth2.core.user.OAuth2User
3839
import org.springframework.web.client.RestTemplate
3940
import org.springframework.web.reactive.function.client.WebClient
41+
import org.springframework.web.reactive.function.client.WebClientRequestException
4042
import reactor.netty.http.client.HttpClient
4143
import reactor.netty.resources.ConnectionProvider
4244
import reactor.netty.resources.ConnectionProvider.DEFAULT_POOL_ACQUIRE_TIMEOUT
45+
import reactor.util.retry.Retry
4346

4447
private const val DEFAULT_MAX_CONNECTIONS = 500
4548
private const val CUSTOM_CONNECTION_PROVIDER_NAME = "gdc-connection-provider"
@@ -58,6 +61,16 @@ class ReactiveCommunicationClientsConfiguration(private val httpProperties: Http
5861
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, httpProperties.connectTimeoutMillis)
5962
return WebClient.builder()
6063
.clientConnector(ReactorClientHttpConnector(httpClient))
64+
.filter { request, next ->
65+
next.exchange(request)
66+
.retryWhen(
67+
Retry.backoff(MAX_RETRY_ATTEMPTS, Duration.ofSeconds(RETRY_BACKOFF_SECONDS))
68+
.filter { throwable -> throwable is WebClientRequestException }
69+
.doBeforeRetry { retrySignal ->
70+
log.warn("Retrying request after error: {}", retrySignal.failure().message)
71+
}
72+
)
73+
}
6174
.build()
6275
}
6376

@@ -124,4 +137,10 @@ class ReactiveCommunicationClientsConfiguration(private val httpProperties: Http
124137
setWebClient(webClient)
125138
setBodyExtractor(SafeOAuth2AccessTokenResponseBodyExtractor())
126139
}
140+
141+
companion object {
142+
private val log = LoggerFactory.getLogger(ReactiveCommunicationClientsConfiguration::class.java)
143+
private const val MAX_RETRY_ATTEMPTS = 3L
144+
private const val RETRY_BACKOFF_SECONDS = 1L
145+
}
127146
}

0 commit comments

Comments
 (0)