18
18
*/
19
19
package io .github .resilience4j .decorators ;
20
20
21
+ import static org .assertj .core .api .Assertions .assertThat ;
22
+ import static org .mockito .BDDMockito .given ;
23
+ import static org .mockito .Mockito .mock ;
24
+ import static org .mockito .Mockito .times ;
25
+
26
+ import java .io .IOException ;
27
+ import java .time .Duration ;
28
+ import java .util .concurrent .CompletableFuture ;
29
+ import java .util .concurrent .CompletionStage ;
30
+ import java .util .concurrent .ExecutionException ;
31
+ import java .util .concurrent .Executors ;
32
+ import java .util .function .Function ;
33
+ import java .util .function .Supplier ;
34
+
35
+ import org .junit .Before ;
36
+ import org .junit .Test ;
37
+ import org .mockito .BDDMockito ;
38
+
21
39
import io .github .resilience4j .bulkhead .Bulkhead ;
22
40
import io .github .resilience4j .cache .Cache ;
23
41
import io .github .resilience4j .circuitbreaker .CircuitBreaker ;
31
49
import io .vavr .CheckedFunction1 ;
32
50
import io .vavr .CheckedRunnable ;
33
51
import io .vavr .control .Try ;
34
- import org .junit .Before ;
35
- import org .junit .Test ;
36
- import org .mockito .BDDMockito ;
37
-
38
- import java .io .IOException ;
39
- import java .time .Duration ;
40
- import java .util .concurrent .CompletableFuture ;
41
- import java .util .concurrent .CompletionStage ;
42
- import java .util .concurrent .ExecutionException ;
43
- import java .util .concurrent .Executors ;
44
- import java .util .function .Function ;
45
- import java .util .function .Supplier ;
46
-
47
- import static org .assertj .core .api .Assertions .assertThat ;
48
- import static org .mockito .BDDMockito .given ;
49
- import static org .mockito .Mockito .mock ;
50
- import static org .mockito .Mockito .times ;
51
52
52
53
public class DecoratorsTest {
53
54
public boolean state = false ;
@@ -65,11 +66,11 @@ public void testDecorateSupplier() {
65
66
CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
66
67
67
68
Supplier <String > decoratedSupplier = Decorators .ofSupplier (() -> helloWorldService .returnHelloWorld ())
68
- .withCircuitBreaker (circuitBreaker )
69
- .withRetry (Retry .ofDefaults ("id" ))
70
- .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
71
- .withBulkhead (Bulkhead .ofDefaults ("testName" ))
72
- .decorate ();
69
+ .withCircuitBreaker (circuitBreaker )
70
+ .withRetry (Retry .ofDefaults ("id" ))
71
+ .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
72
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
73
+ .decorate ();
73
74
74
75
String result = decoratedSupplier .get ();
75
76
assertThat (result ).isEqualTo ("Hello world" );
@@ -88,11 +89,11 @@ public void testDecorateCheckedSupplier() throws IOException {
88
89
CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
89
90
90
91
CheckedFunction0 <String > decoratedSupplier = Decorators .ofCheckedSupplier (() -> helloWorldService .returnHelloWorldWithException ())
91
- .withCircuitBreaker (circuitBreaker )
92
- .withRetry (Retry .ofDefaults ("id" ))
93
- .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
94
- .withBulkhead (Bulkhead .ofDefaults ("testName" ))
95
- .decorate ();
92
+ .withCircuitBreaker (circuitBreaker )
93
+ .withRetry (Retry .ofDefaults ("id" ))
94
+ .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
95
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
96
+ .decorate ();
96
97
97
98
String result = Try .of (decoratedSupplier ).get ();
98
99
assertThat (result ).isEqualTo ("Hello world" );
@@ -109,11 +110,11 @@ public void testDecorateRunnable() {
109
110
CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
110
111
111
112
Runnable decoratedRunnable = Decorators .ofRunnable (() -> helloWorldService .sayHelloWorld ())
112
- .withCircuitBreaker (circuitBreaker )
113
- .withRetry (Retry .ofDefaults ("id" ))
114
- .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
115
- .withBulkhead (Bulkhead .ofDefaults ("testName" ))
116
- .decorate ();
113
+ .withCircuitBreaker (circuitBreaker )
114
+ .withRetry (Retry .ofDefaults ("id" ))
115
+ .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
116
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
117
+ .decorate ();
117
118
118
119
decoratedRunnable .run ();
119
120
@@ -130,11 +131,11 @@ public void testDecorateCheckedRunnable() throws IOException {
130
131
CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
131
132
132
133
CheckedRunnable decoratedRunnable = Decorators .ofCheckedRunnable (() -> helloWorldService .sayHelloWorldWithException ())
133
- .withCircuitBreaker (circuitBreaker )
134
- .withRetry (Retry .ofDefaults ("id" ))
135
- .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
136
- .withBulkhead (Bulkhead .ofDefaults ("testName" ))
137
- .decorate ();
134
+ .withCircuitBreaker (circuitBreaker )
135
+ .withRetry (Retry .ofDefaults ("id" ))
136
+ .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
137
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
138
+ .decorate ();
138
139
139
140
Try .run (decoratedRunnable );
140
141
@@ -172,6 +173,32 @@ public void testDecorateCompletionStage() throws ExecutionException, Interrupted
172
173
BDDMockito .then (helloWorldService ).should (times (1 )).returnHelloWorld ();
173
174
}
174
175
176
+ @ Test
177
+ public void testDecorateCompletionStageNewAPI () throws ExecutionException , InterruptedException {
178
+ // Given the HelloWorldService returns Hello world
179
+ given (helloWorldService .returnHelloWorld ()).willReturn ("Hello world" );
180
+ CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
181
+
182
+ Supplier <CompletionStage <String >> completionStageSupplier =
183
+ () -> CompletableFuture .supplyAsync (helloWorldService ::returnHelloWorld );
184
+
185
+ CompletionStage <String > completionStage = Decorators .ofCompletionStage (completionStageSupplier )
186
+ .withCircuitBreaker (circuitBreaker )
187
+ .withRetry (Retry .ofDefaults ("id" ), Executors .newSingleThreadScheduledExecutor ())
188
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
189
+ .get ();
190
+
191
+ String value = completionStage .toCompletableFuture ().get ();
192
+ assertThat (value ).isEqualTo ("Hello world" );
193
+
194
+ CircuitBreaker .Metrics metrics = circuitBreaker .getMetrics ();
195
+ assertThat (metrics .getNumberOfBufferedCalls ()).isEqualTo (1 );
196
+ assertThat (metrics .getNumberOfSuccessfulCalls ()).isEqualTo (1 );
197
+
198
+ // Then the helloWorldService should be invoked 1 time
199
+ BDDMockito .then (helloWorldService ).should (times (1 )).returnHelloWorld ();
200
+ }
201
+
175
202
@ Test
176
203
public void testExecuteConsumer () throws ExecutionException , InterruptedException {
177
204
// Given the HelloWorldService returns Hello world
@@ -199,11 +226,11 @@ public void testDecorateFunction() {
199
226
CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
200
227
201
228
Function <String , String > decoratedFunction = Decorators .ofFunction (helloWorldService ::returnHelloWorldWithName )
202
- .withCircuitBreaker (circuitBreaker )
203
- .withRetry (Retry .ofDefaults ("id" ))
204
- .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
205
- .withBulkhead (Bulkhead .ofDefaults ("testName" ))
206
- .decorate ();
229
+ .withCircuitBreaker (circuitBreaker )
230
+ .withRetry (Retry .ofDefaults ("id" ))
231
+ .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
232
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
233
+ .decorate ();
207
234
208
235
String result = decoratedFunction .apply ("Name" );
209
236
assertThat (result ).isEqualTo ("Hello world Name" );
@@ -220,11 +247,11 @@ public void testDecorateCheckedFunction() throws IOException {
220
247
CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
221
248
222
249
CheckedFunction1 <String , String > decoratedFunction = Decorators .ofCheckedFunction (helloWorldService ::returnHelloWorldWithNameWithException )
223
- .withCircuitBreaker (circuitBreaker )
224
- .withRetry (Retry .ofDefaults ("id" ))
225
- .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
226
- .withBulkhead (Bulkhead .ofDefaults ("testName" ))
227
- .decorate ();
250
+ .withCircuitBreaker (circuitBreaker )
251
+ .withRetry (Retry .ofDefaults ("id" ))
252
+ .withRateLimiter (RateLimiter .ofDefaults ("testName" ))
253
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
254
+ .decorate ();
228
255
229
256
String result = Try .of (() -> decoratedFunction .apply ("Name" )).get ();
230
257
assertThat (result ).isEqualTo ("Hello world Name" );
@@ -242,10 +269,10 @@ public void testDecoratorBuilderWithRetry() {
242
269
CircuitBreaker circuitBreaker = CircuitBreaker .ofDefaults ("helloBackend" );
243
270
244
271
Supplier <String > decoratedSupplier = Decorators .ofSupplier (() -> helloWorldService .returnHelloWorld ())
245
- .withCircuitBreaker (circuitBreaker )
246
- .withRetry (Retry .ofDefaults ("id" ))
247
- .withBulkhead (Bulkhead .ofDefaults ("testName" ))
248
- .decorate ();
272
+ .withCircuitBreaker (circuitBreaker )
273
+ .withRetry (Retry .ofDefaults ("id" ))
274
+ .withBulkhead (Bulkhead .ofDefaults ("testName" ))
275
+ .decorate ();
249
276
250
277
Try .of (decoratedSupplier ::get );
251
278
@@ -257,23 +284,23 @@ public void testDecoratorBuilderWithRetry() {
257
284
}
258
285
259
286
@ Test
260
- public void testDecoratorBuilderWithRateLimiter (){
287
+ public void testDecoratorBuilderWithRateLimiter () {
261
288
// Given the HelloWorldService returns Hello world
262
289
given (helloWorldService .returnHelloWorld ()).willReturn ("Hello world" );
263
290
264
291
// Create a custom RateLimiter configuration
265
292
RateLimiterConfig config = RateLimiterConfig .custom ()
266
- .timeoutDuration (Duration .ofMillis (100 ))
267
- .limitRefreshPeriod (Duration .ofSeconds (1 ))
268
- .limitForPeriod (1 )
269
- .build ();
293
+ .timeoutDuration (Duration .ofMillis (100 ))
294
+ .limitRefreshPeriod (Duration .ofSeconds (1 ))
295
+ .limitForPeriod (1 )
296
+ .build ();
270
297
271
298
// Create a RateLimiter
272
299
RateLimiter rateLimiter = RateLimiter .of ("backendName" , config );
273
300
274
301
CheckedFunction0 <String > restrictedSupplier = Decorators .ofCheckedSupplier (() -> helloWorldService .returnHelloWorld ())
275
- .withRateLimiter (rateLimiter )
276
- .decorate ();
302
+ .withRateLimiter (rateLimiter )
303
+ .decorate ();
277
304
278
305
alignTime (rateLimiter );
279
306
Try <String > firstTry = Try .of (restrictedSupplier );
@@ -308,8 +335,8 @@ public void testDecorateCheckedSupplierWithCache() {
308
335
given (cache .get ("testKey" )).willReturn ("Hello from cache" );
309
336
310
337
CheckedFunction1 <String , String > cachedFunction = Decorators .ofCheckedSupplier (() -> "Hello world" )
311
- .withCache (Cache .of (cache ))
312
- .decorate ();
338
+ .withCache (Cache .of (cache ))
339
+ .decorate ();
313
340
String value = Try .of (() -> cachedFunction .apply ("testKey" )).get ();
314
341
assertThat (value ).isEqualTo ("Hello from cache" );
315
342
}
@@ -325,8 +352,8 @@ public void testDecorateSupplierWithCache() {
325
352
given (cache .get ("testKey" )).willReturn ("Hello from cache" );
326
353
327
354
Function <String , String > cachedFunction = Decorators .ofSupplier (() -> "Hello world" )
328
- .withCache (Cache .of (cache ))
329
- .decorate ();
355
+ .withCache (Cache .of (cache ))
356
+ .decorate ();
330
357
String value = cachedFunction .apply ("testKey" );
331
358
assertThat (value ).isEqualTo ("Hello from cache" );
332
359
}
0 commit comments