@@ -24,10 +24,10 @@ import scala.concurrent.duration.DurationInt
24
24
import scala .util .{Failure , Success }
25
25
26
26
/**
27
- * Conceptual PoC inspired by:
27
+ * This conceptual all-in-one PoC is inspired by:
28
28
* https://github.com/mathieuancelin/akka-http-reverse-proxy
29
29
*
30
- * HTTP reverse proxy server echo PoC with :
30
+ * Features ReverseProxy :
31
31
* - Weighted round robin load balancing
32
32
* - Retry on HTTP 5xx from target servers
33
33
* - CircuitBreaker per target server to avoid overload
@@ -40,8 +40,8 @@ import scala.util.{Failure, Success}
40
40
* HTTP client(s) --> ReverseProxy --> remote target server(s)
41
41
*
42
42
* Remarks:
43
- * - The target server selection works via the "Host" HTTP header
44
- * - Local/Remote target servers are designed to be flaky to show retry/circuit breaker behavior
43
+ * - The target server selection is via the "Host" HTTP header
44
+ * - Local/Remote target servers are designed to be flaky to show Retry/CircuitBreaker behavior
45
45
* - On top of the built in client, you may also try other clients
46
46
* - This PoC may not scale well, possible bottlenecks are:
47
47
* - Combination of Retry/CircuitBreaker
@@ -278,29 +278,17 @@ object Retry {
278
278
private [this ] def retryPromise [T ](times : Int , promise : Promise [T ], failure : Option [Throwable ],
279
279
f : => Future [T ])(implicit ec : ExecutionContext ): Unit = {
280
280
(times, failure) match {
281
- case (0 , Some (e)) =>
282
- promise.tryFailure(e)
283
- case (0 , None ) =>
284
- promise.tryFailure(new RuntimeException (" Failure, but lost track of exception" ))
281
+ case (0 , Some (e)) => promise.tryFailure(e)
282
+ case (0 , None ) => promise.tryFailure(new RuntimeException (" Failure, but lost track of exception" ))
285
283
case (_, _) =>
286
284
f.onComplete {
287
- case Success (t) =>
288
- t match {
289
- case httpResponse : HttpResponse =>
290
- val code = httpResponse.status.intValue()
291
- val id = httpResponse.getHeader(" X-Correlation-ID" ).orElse(RawHeader (" X-Correlation-ID" , " N/A" )).value()
292
- if (code >= 500 ) {
293
- logger.info(s " ReverseProxy got 5xx server error for id: $id. Retries left: ${times - 1 }" )
294
- retryPromise[T ](times - 1 , promise, Some (new RuntimeException (s " Received: $code from target server " )), f)
295
- } else {
296
- promise.trySuccess(t)
297
- }
298
- case _ =>
299
- promise.tryFailure(new RuntimeException (" This should not happen: Expected type HttpResponse, but got sth else" ))
300
- }
301
- case Failure (e) =>
302
- retryPromise[T ](times - 1 , promise, Some (e), f)
303
- }(ec)
285
+ case Success (httpResponse : HttpResponse ) if httpResponse.status.intValue() >= 500 =>
286
+ val id = httpResponse.getHeader(" X-Correlation-ID" ).orElse(RawHeader (" X-Correlation-ID" , " N/A" )).value()
287
+ logger.info(s " ReverseProxy got 5xx server error for id: $id. Retries left: ${times - 1 }" )
288
+ retryPromise[T ](times - 1 , promise, Some (new RuntimeException (s " Received: ${httpResponse.status.intValue()} from target server " )), f)
289
+ case Success (t) => promise.trySuccess(t)
290
+ case Failure (e) => retryPromise[T ](times - 1 , promise, Some (e), f)
291
+ }
304
292
}
305
293
}
306
294
}
0 commit comments