11package com .coveo .pushapiclient ;
22
3+ import io .github .resilience4j .core .IntervalFunction ;
4+ import io .github .resilience4j .retry .Retry ;
5+ import io .github .resilience4j .retry .RetryConfig ;
36import java .io .IOException ;
47import java .net .URI ;
58import java .net .http .HttpClient ;
69import java .net .http .HttpRequest ;
710import java .net .http .HttpRequest .BodyPublisher ;
811import java .net .http .HttpResponse ;
12+ import java .util .function .Function ;
913import org .apache .logging .log4j .LogManager ;
1014import org .apache .logging .log4j .Logger ;
1115
12- // TODO: LENS-934 - Support throttling
1316class ApiCore {
1417 private final HttpClient httpClient ;
1518 private final Logger logger ;
19+ private final BackoffOptions options ;
1620
1721 public ApiCore () {
18- this .httpClient = HttpClient .newHttpClient ();
19- this .logger = LogManager .getLogger (ApiCore .class );
22+ this (HttpClient .newHttpClient (), LogManager .getLogger (ApiCore .class ));
2023 }
2124
2225 public ApiCore (HttpClient httpClient , Logger logger ) {
26+ this (httpClient , logger , new BackoffOptionsBuilder ().build ());
27+ }
28+
29+ public ApiCore (HttpClient httpClient , Logger logger , BackoffOptions options ) {
2330 this .httpClient = httpClient ;
2431 this .logger = logger ;
32+ this .options = options ;
33+ }
34+
35+ public HttpResponse <String > callApiWithRetries (HttpRequest request )
36+ throws IOException , InterruptedException {
37+ IntervalFunction intervalFn =
38+ IntervalFunction .ofExponentialRandomBackoff (
39+ this .options .getRetryAfter (), this .options .getTimeMultiple ());
40+
41+ RetryConfig retryConfig =
42+ RetryConfig .<HttpResponse <String >>custom ()
43+ .maxAttempts (this .options .getMaxRetries ())
44+ .intervalFunction (intervalFn )
45+ .retryOnResult (response -> response != null && response .statusCode () == 429 )
46+ .build ();
47+
48+ Retry retry = Retry .of ("platformRequest" , retryConfig );
49+
50+ Function <HttpRequest , HttpResponse <String >> retryRequestFn =
51+ Retry .decorateFunction (retry , req -> sendRequest (req ));
52+
53+ return retryRequestFn .apply (request );
54+ }
55+
56+ public HttpResponse <String > sendRequest (HttpRequest request ) {
57+ String uri = request .uri ().toString ();
58+ String reqMethod = request .method ();
59+ this .logger .debug (reqMethod + " " + uri );
60+ try {
61+ HttpResponse <String > response =
62+ this .httpClient .send (request , HttpResponse .BodyHandlers .ofString ());
63+ this .logResponse (response );
64+ return response ;
65+ } catch (IOException | InterruptedException e ) {
66+ throw new Error (e .getMessage ());
67+ }
2568 }
2669
2770 public HttpResponse <String > post (URI uri , String [] headers )
@@ -31,42 +74,30 @@ public HttpResponse<String> post(URI uri, String[] headers)
3174
3275 public HttpResponse <String > post (URI uri , String [] headers , BodyPublisher body )
3376 throws IOException , InterruptedException {
34- this .logger .debug ("POST " + uri );
3577 HttpRequest request = HttpRequest .newBuilder ().headers (headers ).uri (uri ).POST (body ).build ();
36- HttpResponse <String > response =
37- this .httpClient .send (request , HttpResponse .BodyHandlers .ofString ());
38- this .logResponse (response );
78+ HttpResponse <String > response = this .callApiWithRetries (request );
3979 return response ;
4080 }
4181
4282 public HttpResponse <String > put (URI uri , String [] headers , BodyPublisher body )
4383 throws IOException , InterruptedException {
44- this .logger .debug ("PUT " + uri );
4584 HttpRequest request = HttpRequest .newBuilder ().headers (headers ).uri (uri ).PUT (body ).build ();
46- HttpResponse <String > response =
47- this .httpClient .send (request , HttpResponse .BodyHandlers .ofString ());
48- this .logResponse (response );
85+ HttpResponse <String > response = this .callApiWithRetries (request );
4986 return response ;
5087 }
5188
5289 public HttpResponse <String > delete (URI uri , String [] headers )
5390 throws IOException , InterruptedException {
54- this .logger .debug ("DELETE " + uri );
5591 HttpRequest request = HttpRequest .newBuilder ().headers (headers ).uri (uri ).DELETE ().build ();
56- HttpResponse <String > response =
57- this .httpClient .send (request , HttpResponse .BodyHandlers .ofString ());
58- this .logResponse (response );
92+ HttpResponse <String > response = this .callApiWithRetries (request );
5993 return response ;
6094 }
6195
6296 public HttpResponse <String > delete (URI uri , String [] headers , BodyPublisher body )
6397 throws IOException , InterruptedException {
64- this .logger .debug ("DELETE " + uri );
6598 HttpRequest request =
6699 HttpRequest .newBuilder ().headers (headers ).uri (uri ).method ("DELETE" , body ).build ();
67- HttpResponse <String > response =
68- this .httpClient .send (request , HttpResponse .BodyHandlers .ofString ());
69- this .logResponse (response );
100+ HttpResponse <String > response = this .callApiWithRetries (request );
70101 return response ;
71102 }
72103
0 commit comments