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