Initial check in

This commit is contained in:
Saajan
2021-10-23 18:48:50 +05:30
parent e4d52aa182
commit f46c7c7fa3
5 changed files with 372 additions and 0 deletions

View File

@@ -14,6 +14,9 @@ public class SpringbootResilience4jApplication {
@Autowired
private RateLimiterExamplesRunner rateLimiterExamplesRunner;
@Autowired
private TimeLimiterExamplesRunner timeLimiterExamplesRunner;
public static void main(String[] args) {
SpringApplication.run(SpringbootResilience4jApplication.class, args);
}
@@ -22,5 +25,6 @@ public class SpringbootResilience4jApplication {
public void runExamples() {
retryExamplesRunner.run();
rateLimiterExamplesRunner.run();
timeLimiterExamplesRunner.run();
}
}

View File

@@ -0,0 +1,142 @@
package io.reflectoring.resilience4j.springboot;
import io.reflectoring.resilience4j.springboot.model.Flight;
import io.reflectoring.resilience4j.springboot.model.SearchRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TimeLimiterExamplesRunner {
@Autowired
private TimeLimitingService service;
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss SSS");
public static void main(String[] args) {
TimeLimiterExamplesRunner runner = new TimeLimiterExamplesRunner();
runner.run();
}
static void delay(int seconds) {
// sleep to simulate delay
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
System.out.println("Running timelimiter examples");
System.out.println(
"----------------------- basicExample ----------------------------------------------------");
basicExample();
delay(2); // delay just to let the above async operation to complete
System.out.println(
"----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- timeoutExample ----------------------------------------------");
timeoutExample();
delay(2); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("----------------------- fallbackExample ----------------------------------------------");
fallbackExample();
delay(2); // delay just to let the above async operation to complete
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println(
"----------------------- eventsExample ----------------------------------------------------");
eventsExample();
delay(10); // delay just to let the above async operation to complete
System.out.println(
"----------------------------------------------------------------------------------------------------");
}
private void eventsExample() {
SearchRequest request = new SearchRequest("NYC", "LAX", "10/30/2021");
for (int i = 0; i < 10; i++) {
int attempt = i;
service.eventsExample(request)
.whenComplete((r, t) -> {
if (t != null) {
System.out.println("Error occurred on search " + attempt + ": " + t.getMessage());
}
if (r != null) {
System.out
.println("Search " + attempt + " successful, found " + r.size() + " flights");
}
});
}
}
private void timeoutExample() {
SearchRequest request = new SearchRequest("NYC", "LAX", "10/30/2021");
System.out.println("Calling search; current thread = " + Thread.currentThread().getName());
CompletableFuture<List<Flight>> results = service.timeoutExample(request);
results.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception " +
ex.getMessage() +
" on thread " +
Thread.currentThread().getName() +
" at " +
LocalDateTime.now().format(formatter));
ex.printStackTrace();
}
if (result != null) {
System.out.println(result + " on thread " + Thread.currentThread().getName());
}
});
}
private void basicExample() {
SearchRequest request = new SearchRequest("NYC", "LAX", "10/30/2021");
System.out.println("Calling search; current thread = " + Thread.currentThread().getName());
CompletableFuture<List<Flight>> results = service.basicExample(request);
results.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception " +
ex.getMessage() +
" on thread " +
Thread.currentThread().getName() +
" at " +
LocalDateTime.now().format(formatter));
}
if (result != null) {
System.out.println(result + " on thread " + Thread.currentThread().getName());
}
});
}
private void fallbackExample() {
SearchRequest request = new SearchRequest("NYC", "LAX", "10/30/2021");
System.out.println("Calling search; current thread = " + Thread.currentThread().getName());
CompletableFuture<List<Flight>> results = service.fallbackExample(request);
results.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception " +
ex.getMessage() +
" on thread " +
Thread.currentThread().getName() +
" at " +
LocalDateTime.now().format(formatter));
}
if (result != null) {
System.out.println(result + " on thread " + Thread.currentThread().getName());
}
});
}
}

View File

@@ -0,0 +1,167 @@
package io.reflectoring.resilience4j.springboot;
import io.github.resilience4j.micrometer.tagged.TaggedTimeLimiterMetrics;
import io.github.resilience4j.ratelimiter.RequestNotPermitted;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.timelimiter.TimeLimiter.EventPublisher;
import io.github.resilience4j.timelimiter.TimeLimiterConfig;
import io.github.resilience4j.timelimiter.TimeLimiterRegistry;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import io.micrometer.core.instrument.Measurement;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.reflectoring.resilience4j.springboot.model.Flight;
import io.reflectoring.resilience4j.springboot.model.SearchRequest;
import io.reflectoring.resilience4j.springboot.services.FlightSearchService;
import java.sql.Time;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TimeLimitingService {
@Autowired
private FlightSearchService remoteSearchService;
@Autowired
private TimeLimiterRegistry timeLimiterRegistry;
/*
void printDefaultValues() {
TimeLimiterConfig config = TimeLimiterConfig.ofDefaults();
System.out.println(
"getTimeoutDuration in ms = " + Duration.from(config.getTimeoutDuration()).toMillis());
System.out.println("shouldCancelRunningFuture = " + config.shouldCancelRunningFuture());
} */
@TimeLimiter(name = "basicExample")
CompletableFuture<List<Flight>> basicExample(SearchRequest request) {
return CompletableFuture.supplyAsync(() -> remoteSearchService.searchFlightsTakingOneSecond(request));
}
@TimeLimiter(name = "timeoutExample")
CompletableFuture<List<Flight>> timeoutExample(SearchRequest request) {
return CompletableFuture.supplyAsync(() -> remoteSearchService.searchFlightsTakingOneSecond(request));
}
@TimeLimiter(name = "timeAndRateLimiter")
@RateLimiter(name = "timeAndRateLimiter")
CompletableFuture<List<Flight>> aspectOrderExample(SearchRequest request) {
return CompletableFuture.supplyAsync(() -> remoteSearchService.searchFlightsTakingOneSecond(request));
}
/*
void basicExample_ExcecuteCompletionStage() {
TimeLimiterConfig config = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofMillis(500))
.build();
TimeLimiterRegistry registry = TimeLimiterRegistry.of(config);
TimeLimiter limiter = registry.timeLimiter("flightSearch");
FlightSearchService service = new FlightSearchService();
SearchRequest request = new SearchRequest("NYC", "LAX", "08/30/2020");
Supplier<List<Flight>> flightSupplier = () -> service.searchFlightsTakingOneSecond(request);
Supplier<CompletionStage<List<Flight>>> origCompletionStageSupplier = () -> CompletableFuture
.supplyAsync(flightSupplier);
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
CompletionStage<List<Flight>> decoratedCompletionStage = limiter
.executeCompletionStage(scheduler, origCompletionStageSupplier);
decoratedCompletionStage.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("Exception " +
ex.getMessage() +
" on thread " +
Thread.currentThread().getName() +
" at " +
LocalDateTime.now().format(formatter));
}
if (result != null) {
System.out.println(result + " on thread " + Thread.currentThread().getName());
}
});
scheduler.shutdown();
}
void whenToUseExample() {
CompletableFuture.supplyAsync(this::slowMethod).thenAccept(System.out::println);
}
void whenToUseExample_Blocking()
throws InterruptedException, ExecutionException, TimeoutException {
CompletableFuture<Integer> completableFuture = CompletableFuture
.supplyAsync(this::slowMethod);
Integer result = completableFuture.get(3000, TimeUnit.MILLISECONDS);
System.out.println(result);
}
int slowMethod() {
System.out.println(Thread.currentThread().getName());
// sleep to simulate delay
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
static void delay(int seconds) {
// sleep to simulate delay
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} */
@TimeLimiter(name = "eventsExample")
CompletableFuture<List<Flight>> eventsExample(SearchRequest request) {
return CompletableFuture.supplyAsync(() -> remoteSearchService.searchFlightsTakingRandomTime(request));
}
@TimeLimiter(name = "fallbackExample", fallbackMethod = "localCacheFlightSearch")
CompletableFuture<List<Flight>> fallbackExample(SearchRequest request) {
return CompletableFuture.supplyAsync(() -> remoteSearchService.searchFlightsTakingOneSecond(request));
}
private CompletableFuture<List<Flight>> localCacheFlightSearch(SearchRequest request, TimeoutException rnp) {
System.out.println("Returning search results from cache");
System.out.println(rnp.getMessage());
CompletableFuture<List<Flight>> result = new CompletableFuture<>();
result.complete(Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 781", request.getFlightDate(), request.getFrom(), request.getTo())));
return result;
}
@PostConstruct
void postConstruct() {
EventPublisher eventPublisher = timeLimiterRegistry.timeLimiter("eventsExample").getEventPublisher();
eventPublisher.onSuccess(System.out::println);
eventPublisher.onError(System.out::println);
eventPublisher.onTimeout(System.out::println);
}
}

View File

@@ -13,6 +13,7 @@ import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.springframework.stereotype.Service;
@Service
@@ -20,6 +21,7 @@ public class FlightSearchService {
PotentialFailure potentialFailure = new NoFailure();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss SSS");
Random random = new Random();
PotentialFailureCheckedException potentialFailureCheckedException = new NoCheckedExceptionFailure();
@@ -108,4 +110,42 @@ public class FlightSearchService {
response.setFlights(flights);
return response;
}
public List<Flight> searchFlightsTakingOneSecond(SearchRequest request) {
System.out.println("Searching for flights; "
+ "current time = " + LocalDateTime.now().format(formatter) +
"; current thread = " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
List<Flight> flights = Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 746", request.getFlightDate(), request.getFrom(), request.getTo())
);
System.out.println("Flight search successful at " + LocalDateTime.now().format(formatter));
return flights;
}
public List<Flight> searchFlightsTakingRandomTime(SearchRequest request) {
long delay = random.nextInt(3000);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Searching for flights; "
+ "current time = " + LocalDateTime.now().format(formatter) +
"; current thread = " + Thread.currentThread().getName());
List<Flight> flights = Arrays.asList(
new Flight("XY 765", request.getFlightDate(), request.getFrom(), request.getTo()),
new Flight("XY 746", request.getFlightDate(), request.getFrom(), request.getTo())
);
System.out.println("Flight search successful");
return flights;
}
}

View File

@@ -99,6 +99,25 @@ resilience4j:
limitRefreshPeriod: 1s
timeoutDuration: 500ms
timelimiter:
instances:
# TimeLimiter object used in TimeLimitingService.basicExample()
basicExample:
timeoutDuration: 2s
# TimeLimiter object used in TimeLimitingService.timeoutExample()
timeoutExample:
timeoutDuration: 500ms
# TimeLimiter object used in TimeLimitingService.eventsExample()
eventsExample:
timeoutDuration: 2s
# TimeLimiter object used in TimeLimitingService.fallbackExample()
fallbackExample:
timeoutDuration: 500ms
management:
endpoints:
web: