I need to implement following behavior:
429 Too many requests
, retry up to 3 times with a delay of 1 secondI would like to use Spring WebClient for this purpose and came up with this code:
Mono<ClientResponse> response = webClient.post()
.uri(URI.create("/myuri"))
.body(BodyInserters.fromObject(request))
.retrieve()
.onStatus(httpStatus -> httpStatus.equals(HttpStatus.TOO_MANY_REQUESTS),
response -> Mono.error(new TooManyRequestsException("System is overloaded")))
.bodyToMono(ClientResponse.class)
.retryWhen(Retry.anyOf(TooManyRequestsException.class)
.fixedBackoff(Duration.ofSeconds(1)).retryMax(3))
.doOnError(throwable -> saveToDB(some_id, throwable))
.subscribe(response -> logResponse(some_id, response));
Now I would like to test if the retry mechanism and error handling works as I expect. May be I could use StepVerifier for this purpose, but I just cannot figure out how to use it in my case. Any useful hints?
I think that you might be able to test this with a mock web server, e.g. MockWebServer.
@Test
public void testReactiveWebClient() throws IOException
{
MockWebServer mockWebServer = new MockWebServer();
String expectedResponse = "expect that it works";
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(429));
mockWebServer.enqueue(new MockResponse().setResponseCode(200)
.setBody(expectedResponse));
mockWebServer.start();
HttpUrl url = mockWebServer.url("/mvuri");
WebClient webClient = WebClient.create();
Mono<String> responseMono = webClient.post()
.uri(url.uri())
.body(BodyInserters.fromObject("myRequest"))
.retrieve()
.onStatus(
httpStatus -> httpStatus.equals(HttpStatus.TOO_MANY_REQUESTS),
response -> Mono.error(new TestStuff.TooManyRequestsException("System is overloaded")))
.bodyToMono(String.class)
.retryWhen(Retry.anyOf(TestStuff.TooManyRequestsException.class)
.fixedBackoff(Duration.ofSeconds(1)).retryMax(3));
StepVerifier.create(responseMono)
.expectNext(expectedResponse)
.expectComplete().verify();
mockWebServer.shutdown();
}
If you enqueue another MockResponse
with a statuscode 429
, the verification will fail, same with e.g. errorcode 500
.