Skip to content

Commit 4e72aeb

Browse files
Jacob-Eliat-Eliatgemini-code-assist[bot]dmivankov
authored
retry unknownHost too (#869)
* retry unknownHost too * small test * changing exception type * fmt * Update src/test/scala/com/cognite/sdk/scala/sttp/RetryingBackendTest.scala Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fix test * fix tests * Apply suggestion from @dmivankov Co-authored-by: Dmitry Ivankov <dmitry.ivankov@cognite.com> * Update src/test/scala/com/cognite/sdk/scala/sttp/RetryingBackendTest.scala Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * fix test * fmt --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Dmitry Ivankov <dmitry.ivankov@cognite.com>
1 parent 150aacd commit 4e72aeb

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

src/main/scala/com/cognite/sdk/scala/sttp/RetryingBackend.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import sttp.client3.{Request, Response, SttpBackend, SttpClientException}
1111
import sttp.model.StatusCode
1212
import sttp.monad.MonadError
1313

14-
import java.net.ConnectException
14+
import java.net.{ConnectException, UnknownHostException}
1515
import scala.concurrent.TimeoutException
1616
import scala.concurrent.duration.{DurationInt, FiniteDuration}
1717
import scala.util.Random
@@ -54,7 +54,8 @@ class RetryingBackend[F[_], +P](
5454
case cdpError: CdpApiException => maybeRetry(Some(StatusCode(cdpError.code)), cdpError)
5555
case sdkException @ SdkException(_, _, _, code @ Some(_)) =>
5656
maybeRetry(code.map(StatusCode(_)), sdkException)
57-
case e @ (_: TimeoutException | _: ConnectException | _: SttpClientException) =>
57+
case e @ (_: TimeoutException | _: ConnectException | _: SttpClientException |
58+
_: UnknownHostException) =>
5859
maybeRetry(None, e)
5960
}
6061
responseMonad.flatMap(r) { resp =>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.cognite.sdk.scala.sttp
2+
3+
import cats.effect.IO
4+
import cats.effect.unsafe.implicits.global
5+
import sttp.client3._
6+
import sttp.monad.MonadError
7+
import org.scalatest.flatspec.AnyFlatSpec
8+
import org.scalatest.matchers.should.Matchers
9+
import sttp.capabilities.Effect
10+
import sttp.client3.impl.cats.implicits.monadError
11+
12+
import java.net.UnknownHostException
13+
import java.util.concurrent.atomic.AtomicInteger
14+
import scala.concurrent.duration.DurationInt
15+
16+
@SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf", "org.wartremover.warts.NonUnitStatements"))
17+
class FailingRetryingBackend[F[_], +P](val shouldSucceed: Boolean = false)(implicit val responseMonad: MonadError[F]) extends SttpBackend[F, P] {
18+
val callCount: AtomicInteger = new java.util.concurrent.atomic.AtomicInteger(0)
19+
20+
override def send[T, R >: P with Effect[F]](request: Request[T, R]): F[Response[T]] = {
21+
callCount.incrementAndGet()
22+
if(shouldSucceed)
23+
responseMonad.unit(Response.ok(Right("mock success").asInstanceOf[T]))
24+
else
25+
responseMonad.error(new UnknownHostException("Connection failed"))
26+
}
27+
override def close(): F[Unit] = responseMonad.unit(())
28+
}
29+
30+
@SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements"))
31+
class RetryingBackendTest extends AnyFlatSpec with Matchers {
32+
val port: Int = 50000 + (java.lang.Math.random() * 1000).toInt
33+
34+
"RetryingBackend" should "retry failed requests multiple times" in {
35+
val mockBackend = new FailingRetryingBackend[IO, Any]
36+
val retryingBackend = new RetryingBackend[IO, Any](mockBackend, maxRetries = 2, initialRetryDelay = 1.millis)
37+
38+
//request doesn't matter, underlying backend just returns a failure
39+
val request = basicRequest
40+
.body("test")
41+
.post(uri"http://host:$port/string")
42+
43+
an[UnknownHostException] should be thrownBy {
44+
request.send(retryingBackend).unsafeRunSync()
45+
()
46+
}
47+
48+
mockBackend.callCount.get should be(3)
49+
}
50+
51+
it should "not retry successful requests multiple times" in {
52+
val mockBackend = new FailingRetryingBackend[IO, Any](shouldSucceed = true)
53+
val retryingBackend = new RetryingBackend[IO, Any](mockBackend, maxRetries = 2, initialRetryDelay = 1.millis)
54+
55+
//request doesn't matter, underlying backend just returns a success
56+
val request = basicRequest
57+
.body("test")
58+
.post(uri"http://host:$port/string")
59+
60+
request.send(retryingBackend).unsafeRunSync()
61+
62+
63+
mockBackend.callCount.get shouldBe 1
64+
}
65+
}

0 commit comments

Comments
 (0)