1
+ package io .reflectoring .resilience4j .springboot ;
2
+
3
+ import io .github .resilience4j .ratelimiter .RateLimiterRegistry ;
4
+ import io .github .resilience4j .ratelimiter .RequestNotPermitted ;
5
+ import io .github .resilience4j .ratelimiter .annotation .RateLimiter ;
6
+ import io .github .resilience4j .retry .RetryRegistry ;
7
+ import io .github .resilience4j .retry .annotation .Retry ;
8
+ import io .reflectoring .resilience4j .springboot .model .Flight ;
9
+ import io .reflectoring .resilience4j .springboot .model .SearchRequest ;
10
+ import io .reflectoring .resilience4j .springboot .services .FlightSearchService ;
11
+ import java .time .Duration ;
12
+ import java .time .format .DateTimeFormatter ;
13
+ import java .util .Arrays ;
14
+ import java .util .List ;
15
+ import javax .annotation .PostConstruct ;
16
+ import org .springframework .beans .factory .annotation .Autowired ;
17
+ import org .springframework .stereotype .Component ;
18
+ import org .springframework .stereotype .Service ;
19
+
20
+ @ Service
21
+ public class RateLimitingService {
22
+ @ Autowired
23
+ private FlightSearchService remoteSearchService ;
24
+
25
+ @ Autowired
26
+ private RPMRateLimitedFlightSearchSearch rpmRateLimitedFlightSearchSearch ;
27
+
28
+ @ Autowired
29
+ private RateLimiterRegistry registry ;
30
+
31
+ @ Autowired
32
+ private RetryRegistry retryRegistry ;
33
+
34
+ DateTimeFormatter formatter = DateTimeFormatter .ofPattern ("HH:mm:ss SSS" );
35
+
36
+ @ RateLimiter (name = "basicExample" )
37
+ List <Flight > basicExample (SearchRequest request ) {
38
+ return remoteSearchService .searchFlights (request );
39
+ }
40
+
41
+ @ RateLimiter (name = "timeoutExample" )
42
+ List <Flight > timeoutExample (SearchRequest request ) {
43
+ return remoteSearchService .searchFlights (request );
44
+ }
45
+
46
+ @ RateLimiter (name = "multipleRateLimiters_rps_limiter" )
47
+ List <Flight > multipleRateLimitsExample (SearchRequest request ) {
48
+ return rpmRateLimitedFlightSearchSearch .searchFlights (request , remoteSearchService );
49
+ }
50
+
51
+ // doesn't work - @RateLimiter is not a repeatable annotation
52
+ // @RateLimiter(name = "multipleRateLimiters_rps_limiter")
53
+ // @RateLimiter(name = "multipleRateLimiters_rpm_limiter")
54
+ // List<Flight> multipleRateLimitsExample(SearchRequest request) {
55
+ // return remoteSearchService.searchFlights(request, remoteSearchService);
56
+ // }
57
+
58
+ // doesn't work - calls within a Spring bean don't go thru the Spring proxy
59
+ // @RateLimiter(name = "multipleRateLimiters_rps_limiter")
60
+ // List<Flight> rpsLimitedSearch(SearchRequest request) {
61
+ // return rpmLimitedSearch(request, remoteSearchService);
62
+ // }
63
+
64
+ // @RateLimiter(name = "multipleRateLimiters_rpm_limiter")
65
+ // List<Flight> rpmLimitedSearch(SearchRequest request) {
66
+ // return remoteSearchService.searchFlights(request, remoteSearchService);
67
+ // }
68
+
69
+
70
+ @ RateLimiter (name = "changeLimitsExample" )
71
+ public List <Flight > changeLimitsExample (SearchRequest request ) {
72
+ return remoteSearchService .searchFlights (request );
73
+ }
74
+
75
+ @ Retry (name = "retryAndRateLimitExample" )
76
+ @ RateLimiter (name = "retryAndRateLimitExample" )
77
+ public List <Flight > retryAndRateLimit (SearchRequest request ) {
78
+ return remoteSearchService .searchFlights (request );
79
+ }
80
+
81
+ @ RateLimiter (name = "rateLimiterEventsExample" )
82
+ public List <Flight > rateLimiterEventsExample (SearchRequest request ) {
83
+ return remoteSearchService .searchFlights (request );
84
+ }
85
+
86
+ public void updateRateLimits (String rateLimiterName , int newLimitForPeriod , Duration newTimeoutDuration ) {
87
+ io .github .resilience4j .ratelimiter .RateLimiter limiter = registry .rateLimiter (rateLimiterName );
88
+ limiter .changeLimitForPeriod (newLimitForPeriod );
89
+ limiter .changeTimeoutDuration (newTimeoutDuration );
90
+ }
91
+
92
+ @ RateLimiter (name = "fallbackExample" , fallbackMethod = "localCacheFlightSearch" )
93
+ public List <Flight > fallbackExample (SearchRequest request ) {
94
+ return remoteSearchService .searchFlights (request );
95
+ }
96
+
97
+ private List <Flight > localCacheFlightSearch (SearchRequest request , RequestNotPermitted rnp ) {
98
+ System .out .println ("Returning search results from cache" );
99
+ return Arrays .asList (
100
+ new Flight ("XY 765" , request .getFlightDate (), request .getFrom (), request .getTo ()),
101
+ new Flight ("XY 781" , request .getFlightDate (), request .getFrom (), request .getTo ()));
102
+ }
103
+
104
+ @ PostConstruct
105
+ public void postConstruct () {
106
+ io .github .resilience4j .retry .Retry .EventPublisher retryEventPublisher = retryRegistry
107
+ .retry ("retryAndRateLimitExample" )
108
+ .getEventPublisher ();
109
+
110
+ retryEventPublisher .onRetry (System .out ::println );
111
+ retryEventPublisher .onSuccess (System .out ::println );
112
+
113
+ io .github .resilience4j .ratelimiter .RateLimiter .EventPublisher eventPublisher = registry
114
+ .rateLimiter ("rateLimiterEventsExample" )
115
+ .getEventPublisher ();
116
+
117
+ eventPublisher .onSuccess (System .out ::println );
118
+ eventPublisher .onFailure (System .out ::println );
119
+ }
120
+ }
121
+
122
+ @ Component
123
+ class RPMRateLimitedFlightSearchSearch {
124
+ @ RateLimiter (name = "multipleRateLimiters_rpm_limiter" )
125
+ List <Flight > searchFlights (SearchRequest request , FlightSearchService remoteSearchService ) {
126
+ return remoteSearchService .searchFlights (request );
127
+ }
128
+ }
0 commit comments