From 98b971d7db5c08e838b9e1506594fa53e7385ea8 Mon Sep 17 00:00:00 2001 From: Paul-Christian Volkmer Date: Sun, 23 Mar 2025 13:35:24 +0100 Subject: [PATCH] feat: do not retry on validation issues (#89) This will prevent retry if response is HTTP 400 or HTTP 422. --- .../dnpm/etl/processor/config/AppConfiguration.kt | 3 +++ .../processor/output/RestDipMtbFileSenderTest.kt | 13 +++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt index 5fc1120..66af288 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt @@ -55,6 +55,7 @@ import org.springframework.retry.support.RetryTemplateBuilder import org.springframework.scheduling.annotation.EnableScheduling import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.provisioning.InMemoryUserDetailsManager +import org.springframework.web.client.HttpClientErrorException import org.springframework.web.client.RestTemplate import reactor.core.publisher.Sinks import java.io.BufferedInputStream @@ -224,6 +225,8 @@ class AppConfiguration { fun retryTemplate(configProperties: AppConfigProperties): RetryTemplate { return RetryTemplateBuilder() .notRetryOn(IllegalArgumentException::class.java) + .notRetryOn(HttpClientErrorException.BadRequest::class.java) + .notRetryOn(HttpClientErrorException.UnprocessableEntity::class.java) .exponentialBackoff(2.seconds.toJavaDuration(), 1.25, 5.seconds.toJavaDuration()) .customPolicy(SimpleRetryPolicy(configProperties.maxRetryAttempts)) .withListener(object : RetryListener { diff --git a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt index dac6496..26e25c6 100644 --- a/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt +++ b/src/test/kotlin/dev/dnpm/etl/processor/output/RestDipMtbFileSenderTest.kt @@ -22,6 +22,8 @@ package dev.dnpm.etl.processor.output import de.ukw.ccc.bwhc.dto.* import dev.dnpm.etl.processor.PatientPseudonym import dev.dnpm.etl.processor.RequestId +import dev.dnpm.etl.processor.config.AppConfigProperties +import dev.dnpm.etl.processor.config.AppConfiguration import dev.dnpm.etl.processor.config.RestTargetProperties import dev.dnpm.etl.processor.monitoring.RequestStatus import org.assertj.core.api.Assertions.assertThat @@ -30,6 +32,7 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus +import org.springframework.retry.backoff.NoBackOffPolicy import org.springframework.retry.policy.SimpleRetryPolicy import org.springframework.retry.support.RetryTemplateBuilder import org.springframework.test.web.client.ExpectedCount @@ -91,14 +94,15 @@ class RestDipMtbFileSenderTest { fun shouldRetryOnMtbFileHttpRequestError(requestWithResponse: RequestWithResponse) { val restTemplate = RestTemplate() val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false) - val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build() + val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties("http://localhost:9000")) + retryTemplate.setBackOffPolicy(NoBackOffPolicy()) this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate) this.restMtbFileSender = RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate) val expectedCount = when (requestWithResponse.httpStatus) { // OK - No Retry - HttpStatus.OK, HttpStatus.CREATED -> ExpectedCount.max(1) + HttpStatus.OK, HttpStatus.CREATED, HttpStatus.UNPROCESSABLE_ENTITY, HttpStatus.BAD_REQUEST -> ExpectedCount.max(1) // Request failed - Retry max 3 times else -> ExpectedCount.max(3) } @@ -120,14 +124,15 @@ class RestDipMtbFileSenderTest { fun shouldRetryOnDeleteHttpRequestError(requestWithResponse: RequestWithResponse) { val restTemplate = RestTemplate() val restTargetProperties = RestTargetProperties("http://localhost:9000/api", null, null, false) - val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(3)).build() + val retryTemplate = AppConfiguration().retryTemplate(AppConfigProperties("http://localhost:9000")) + retryTemplate.setBackOffPolicy(NoBackOffPolicy()) this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate) this.restMtbFileSender = RestDipMtbFileSender(restTemplate, restTargetProperties, retryTemplate) val expectedCount = when (requestWithResponse.httpStatus) { // OK - No Retry - HttpStatus.OK, HttpStatus.CREATED -> ExpectedCount.max(1) + HttpStatus.OK, HttpStatus.CREATED, HttpStatus.UNPROCESSABLE_ENTITY, HttpStatus.BAD_REQUEST -> ExpectedCount.max(1) // Request failed - Retry max 3 times else -> ExpectedCount.max(3) }