[KC-108] 분석도엽 ai api호출 테스트
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
package com.kamco.cd.kamcoback.config;
|
||||
|
||||
import io.netty.channel.ChannelOption;
|
||||
import java.time.Duration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
|
||||
@Configuration
|
||||
public class WebClientConfig {
|
||||
|
||||
@Bean
|
||||
public WebClient webClient() {
|
||||
|
||||
HttpClient httpClient =
|
||||
HttpClient.create()
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
|
||||
.responseTimeout(Duration.ofSeconds(5));
|
||||
|
||||
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.kamco.cd.kamcoback.config.resttemplate;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ExternalHttpClient {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
public ResponseEntity<String> exchange(
|
||||
String url, HttpMethod method, Object body, HttpHeaders headers) {
|
||||
HttpEntity<Object> entity = new HttpEntity<>(body, headers);
|
||||
return restTemplate.exchange(url, method, entity, String.class);
|
||||
}
|
||||
|
||||
public ExternalCallResult call(String url, HttpMethod method, Object body, HttpHeaders headers) {
|
||||
ResponseEntity<String> res = exchange(url, method, body, headers);
|
||||
int code = res.getStatusCodeValue();
|
||||
return new ExternalCallResult(code, code >= 200 && code < 300, res.getBody());
|
||||
}
|
||||
|
||||
public record ExternalCallResult(int statusCode, boolean success, String body) {}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.kamco.cd.kamcoback.config.resttemplate;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||
return builder
|
||||
.connectTimeout(Duration.ofSeconds(2))
|
||||
.readTimeout(Duration.ofSeconds(3))
|
||||
.additionalInterceptors(List.of(new RetryInterceptor()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.kamco.cd.kamcoback.config.resttemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
public class RetryInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
private static final int MAX_RETRY = 3;
|
||||
private static final long WAIT_MILLIS = 3000;
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(
|
||||
HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
|
||||
|
||||
IOException lastException = null;
|
||||
|
||||
for (int attempt = 1; attempt <= MAX_RETRY; attempt++) {
|
||||
try {
|
||||
// HTTP 응답을 받으면(2xx/4xx/5xx 포함) 그대로 반환
|
||||
return execution.execute(request, body);
|
||||
|
||||
} catch (IOException e) {
|
||||
// 네트워크/타임아웃 등 I/O 예외만 재시도
|
||||
lastException = e;
|
||||
}
|
||||
|
||||
// 마지막 시도가 아니면 대기
|
||||
if (attempt < MAX_RETRY) {
|
||||
sleep();
|
||||
}
|
||||
}
|
||||
|
||||
// 마지막 예외를 그대로 던져서 원인이 로그에 남게 함
|
||||
throw lastException;
|
||||
}
|
||||
|
||||
private void sleep() throws IOException {
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(WAIT_MILLIS);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("Retry interrupted", ie);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user