From 1eec6fa34ac69311ee5c70d9dc3a2deb463673e6 Mon Sep 17 00:00:00 2001 From: szimano Date: Mon, 19 Mar 2018 12:41:31 -0400 Subject: hystrix take 2 --- build.sbt | 12 ++++++++ .../softwaremill/sttp/hystrix/HystrixBackend.scala | 33 ++++++++++++++++++++++ .../sttp/hystrix/HystrixBackendTest.scala | 32 +++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 circuit-breaker/hystrix-backend/src/main/scala/com/softwaremill/sttp/hystrix/HystrixBackend.scala create mode 100644 circuit-breaker/hystrix-backend/src/test/scala/com/softwaremill/sttp/hystrix/HystrixBackendTest.scala diff --git a/build.sbt b/build.sbt index c4331fe..b218909 100644 --- a/build.sbt +++ b/build.sbt @@ -59,6 +59,7 @@ lazy val rootProject = (project in file(".")) json4s, braveBackend, prometheusBackend, + hystrixBackend, tests ) @@ -203,6 +204,17 @@ lazy val prometheusBackend: Project = (project in file("metrics/prometheus-backe ) .dependsOn(core) +lazy val hystrixBackend: Project = (project in file("circuit-breaker/hystrix-backend")) + .settings(commonSettings: _*) + .settings( + name := "hystrix-backend", + libraryDependencies ++= Seq( + "com.netflix.hystrix" % "hystrix-core" % "1.5.12", + scalaTest % "test" + ) + ) + .dependsOn(core) + lazy val tests: Project = (project in file("tests")) .settings(commonSettings: _*) .settings( diff --git a/circuit-breaker/hystrix-backend/src/main/scala/com/softwaremill/sttp/hystrix/HystrixBackend.scala b/circuit-breaker/hystrix-backend/src/main/scala/com/softwaremill/sttp/hystrix/HystrixBackend.scala new file mode 100644 index 0000000..bd57357 --- /dev/null +++ b/circuit-breaker/hystrix-backend/src/main/scala/com/softwaremill/sttp/hystrix/HystrixBackend.scala @@ -0,0 +1,33 @@ +package com.softwaremill.sttp.hystrix + +import com.netflix.hystrix.HystrixCommand.Setter +import com.netflix.hystrix.{HystrixCommand, HystrixCommandGroupKey, HystrixCommandProperties} +import com.softwaremill.sttp.{MonadError, Request, Response, SttpBackend} + +class HystrixBackend[R[_], S] private (delegate: SttpBackend[R, S]) extends SttpBackend[R, S] { + + class SttpCMD[T](request: Request[T, S], delegate: SttpBackend[R, S]) + extends HystrixCommand[R[Response[T]]]( + Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("SttpCommand")) + .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withMetricsHealthSnapshotIntervalInMilliseconds(10)) + ) { + + override def run(): R[Response[T]] = delegate.send(request) + } + + override def send[T](request: Request[T, S]): R[Response[T]] = { + new SttpCMD(request, delegate).execute() + } + + override def close(): Unit = delegate.close() + + /** + * The monad in which the responses are wrapped. Allows writing wrapper + * backends, which map/flatMap over the return value of [[send]]. + */ + override def responseMonad: MonadError[R] = delegate.responseMonad +} + +object HystrixBackend { + def apply[R[_], S](delegate: SttpBackend[R, S]) = new HystrixBackend(delegate) +} \ No newline at end of file diff --git a/circuit-breaker/hystrix-backend/src/test/scala/com/softwaremill/sttp/hystrix/HystrixBackendTest.scala b/circuit-breaker/hystrix-backend/src/test/scala/com/softwaremill/sttp/hystrix/HystrixBackendTest.scala new file mode 100644 index 0000000..15cc55a --- /dev/null +++ b/circuit-breaker/hystrix-backend/src/test/scala/com/softwaremill/sttp/hystrix/HystrixBackendTest.scala @@ -0,0 +1,32 @@ +package com.softwaremill.sttp.prometheus + +import com.netflix.hystrix.{HystrixCommandKey, HystrixCommandMetrics} +import com.softwaremill.sttp.hystrix.HystrixBackend +import com.softwaremill.sttp.testing.SttpBackendStub +import com.softwaremill.sttp.{HttpURLConnectionBackend, Id, sttp, _} +import org.scalatest.concurrent.Eventually +import org.scalatest.{BeforeAndAfter, FlatSpec, Matchers, OptionValues} + +class HystrixBackendTest extends FlatSpec with Matchers with BeforeAndAfter with Eventually with OptionValues { + + before { + } + + it should "use default hystrix commands" in { + // given + val backendStub = SttpBackendStub(HttpURLConnectionBackend()).whenAnyRequest.thenRespondOk() + val backend = HystrixBackend[Id, Nothing](backendStub) + val requestsNumber = 10 + + // when + (0 until requestsNumber).map(_ => backend.send(sttp.get(uri"http://127.0.0.1/foo"))).foreach(println) + + // then + val metrics = HystrixCommandMetrics.getInstance(HystrixCommandKey.Factory.asKey("SttpCMD")) + println(metrics.getExecutionTimeMean) + println(metrics.getExecutionTimePercentile(10)) + println(metrics.getHealthCounts) + println(metrics.getCommandGroup) + } + +} -- cgit v1.2.3