1
+ package io .reflectoring .resilience4j .springboot ;
2
+
3
+ import io .github .resilience4j .micrometer .tagged .TaggedTimeLimiterMetrics ;
4
+ import io .github .resilience4j .ratelimiter .RequestNotPermitted ;
5
+ import io .github .resilience4j .ratelimiter .annotation .RateLimiter ;
6
+ import io .github .resilience4j .timelimiter .TimeLimiter .EventPublisher ;
7
+ import io .github .resilience4j .timelimiter .TimeLimiterConfig ;
8
+ import io .github .resilience4j .timelimiter .TimeLimiterRegistry ;
9
+ import io .github .resilience4j .timelimiter .annotation .TimeLimiter ;
10
+ import io .micrometer .core .instrument .Measurement ;
11
+ import io .micrometer .core .instrument .Meter ;
12
+ import io .micrometer .core .instrument .MeterRegistry ;
13
+ import io .micrometer .core .instrument .simple .SimpleMeterRegistry ;
14
+ import io .reflectoring .resilience4j .springboot .model .Flight ;
15
+ import io .reflectoring .resilience4j .springboot .model .SearchRequest ;
16
+ import io .reflectoring .resilience4j .springboot .services .FlightSearchService ;
17
+ import java .sql .Time ;
18
+ import java .time .Duration ;
19
+ import java .time .LocalDateTime ;
20
+ import java .util .ArrayList ;
21
+ import java .util .Arrays ;
22
+ import java .util .List ;
23
+ import java .util .concurrent .CompletableFuture ;
24
+ import java .util .concurrent .CompletionStage ;
25
+ import java .util .concurrent .ExecutionException ;
26
+ import java .util .concurrent .Executors ;
27
+ import java .util .concurrent .ScheduledExecutorService ;
28
+ import java .util .concurrent .TimeUnit ;
29
+ import java .util .concurrent .TimeoutException ;
30
+ import java .util .function .Consumer ;
31
+ import java .util .function .Supplier ;
32
+ import java .util .stream .StreamSupport ;
33
+ import javax .annotation .PostConstruct ;
34
+ import org .springframework .beans .factory .annotation .Autowired ;
35
+ import org .springframework .stereotype .Service ;
36
+
37
+ @ Service
38
+ public class TimeLimitingService {
39
+ @ Autowired
40
+ private FlightSearchService remoteSearchService ;
41
+
42
+ @ Autowired
43
+ private TimeLimiterRegistry timeLimiterRegistry ;
44
+
45
+ /*
46
+ void printDefaultValues() {
47
+ TimeLimiterConfig config = TimeLimiterConfig.ofDefaults();
48
+
49
+ System.out.println(
50
+ "getTimeoutDuration in ms = " + Duration.from(config.getTimeoutDuration()).toMillis());
51
+ System.out.println("shouldCancelRunningFuture = " + config.shouldCancelRunningFuture());
52
+ } */
53
+
54
+
55
+ @ TimeLimiter (name = "basicExample" )
56
+ CompletableFuture <List <Flight >> basicExample (SearchRequest request ) {
57
+ return CompletableFuture .supplyAsync (() -> remoteSearchService .searchFlightsTakingOneSecond (request ));
58
+ }
59
+
60
+ @ TimeLimiter (name = "timeoutExample" )
61
+ CompletableFuture <List <Flight >> timeoutExample (SearchRequest request ) {
62
+ return CompletableFuture .supplyAsync (() -> remoteSearchService .searchFlightsTakingOneSecond (request ));
63
+ }
64
+
65
+ @ TimeLimiter (name = "timeAndRateLimiter" )
66
+ @ RateLimiter (name = "timeAndRateLimiter" )
67
+ CompletableFuture <List <Flight >> aspectOrderExample (SearchRequest request ) {
68
+ return CompletableFuture .supplyAsync (() -> remoteSearchService .searchFlightsTakingOneSecond (request ));
69
+ }
70
+
71
+ /*
72
+ void basicExample_ExcecuteCompletionStage() {
73
+ TimeLimiterConfig config = TimeLimiterConfig.custom()
74
+ .timeoutDuration(Duration.ofMillis(500))
75
+ .build();
76
+
77
+ TimeLimiterRegistry registry = TimeLimiterRegistry.of(config);
78
+ TimeLimiter limiter = registry.timeLimiter("flightSearch");
79
+
80
+ FlightSearchService service = new FlightSearchService();
81
+ SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
82
+
83
+ Supplier<List<Flight>> flightSupplier = () -> service.searchFlightsTakingOneSecond(request);
84
+ Supplier<CompletionStage<List<Flight>>> origCompletionStageSupplier = () -> CompletableFuture
85
+ .supplyAsync(flightSupplier);
86
+ ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
87
+ CompletionStage<List<Flight>> decoratedCompletionStage = limiter
88
+ .executeCompletionStage(scheduler, origCompletionStageSupplier);
89
+
90
+ decoratedCompletionStage.whenComplete((result, ex) -> {
91
+ if (ex != null) {
92
+ System.out.println("Exception " +
93
+ ex.getMessage() +
94
+ " on thread " +
95
+ Thread.currentThread().getName() +
96
+ " at " +
97
+ LocalDateTime.now().format(formatter));
98
+ }
99
+ if (result != null) {
100
+ System.out.println(result + " on thread " + Thread.currentThread().getName());
101
+ }
102
+ });
103
+
104
+ scheduler.shutdown();
105
+ }
106
+
107
+
108
+ void whenToUseExample() {
109
+ CompletableFuture.supplyAsync(this::slowMethod).thenAccept(System.out::println);
110
+ }
111
+
112
+ void whenToUseExample_Blocking()
113
+ throws InterruptedException, ExecutionException, TimeoutException {
114
+ CompletableFuture<Integer> completableFuture = CompletableFuture
115
+ .supplyAsync(this::slowMethod);
116
+ Integer result = completableFuture.get(3000, TimeUnit.MILLISECONDS);
117
+ System.out.println(result);
118
+ }
119
+
120
+ int slowMethod() {
121
+ System.out.println(Thread.currentThread().getName());
122
+ // sleep to simulate delay
123
+ try {
124
+ Thread.sleep(2000);
125
+ } catch (InterruptedException e) {
126
+ e.printStackTrace();
127
+ }
128
+ return 0;
129
+ }
130
+
131
+ static void delay(int seconds) {
132
+ // sleep to simulate delay
133
+ try {
134
+ Thread.sleep(seconds * 1000);
135
+ } catch (InterruptedException e) {
136
+ e.printStackTrace();
137
+ }
138
+ } */
139
+
140
+ @ TimeLimiter (name = "eventsExample" )
141
+ CompletableFuture <List <Flight >> eventsExample (SearchRequest request ) {
142
+ return CompletableFuture .supplyAsync (() -> remoteSearchService .searchFlightsTakingRandomTime (request ));
143
+ }
144
+
145
+ @ TimeLimiter (name = "fallbackExample" , fallbackMethod = "localCacheFlightSearch" )
146
+ CompletableFuture <List <Flight >> fallbackExample (SearchRequest request ) {
147
+ return CompletableFuture .supplyAsync (() -> remoteSearchService .searchFlightsTakingOneSecond (request ));
148
+ }
149
+
150
+ private CompletableFuture <List <Flight >> localCacheFlightSearch (SearchRequest request , TimeoutException rnp ) {
151
+ System .out .println ("Returning search results from cache" );
152
+ System .out .println (rnp .getMessage ());
153
+ CompletableFuture <List <Flight >> result = new CompletableFuture <>();
154
+ result .complete (Arrays .asList (
155
+ new Flight ("XY 765" , request .getFlightDate (), request .getFrom (), request .getTo ()),
156
+ new Flight ("XY 781" , request .getFlightDate (), request .getFrom (), request .getTo ())));
157
+ return result ;
158
+ }
159
+
160
+ @ PostConstruct
161
+ void postConstruct () {
162
+ EventPublisher eventPublisher = timeLimiterRegistry .timeLimiter ("eventsExample" ).getEventPublisher ();
163
+ eventPublisher .onSuccess (System .out ::println );
164
+ eventPublisher .onError (System .out ::println );
165
+ eventPublisher .onTimeout (System .out ::println );
166
+ }
167
+ }
0 commit comments