client 호출 용량 상향 조정. chunk 방식 추가했지만 사용은 아직 안함.
This commit is contained in:
parent
e8eb4381f2
commit
3ed7f0c7f1
|
|
@ -2,57 +2,117 @@ package com.goi.erp.client;
|
||||||
|
|
||||||
import com.goi.erp.dto.ScheduleWorkerRequestDto;
|
import com.goi.erp.dto.ScheduleWorkerRequestDto;
|
||||||
import com.goi.erp.dto.ext.ExtSamsaraOdometerFetchCommand;
|
import com.goi.erp.dto.ext.ExtSamsaraOdometerFetchCommand;
|
||||||
|
import com.goi.erp.dto.ext.ExtSamsaraOdometerRecordDto;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class SamsaraStatOdometerClient {
|
public class SamsaraStatOdometerClient {
|
||||||
|
|
||||||
private final WebClient webClient;
|
/** WebClient in-memory 버퍼 한계 (기본 256KB → 16MB로 상향) */
|
||||||
|
private static final int MAX_IN_MEMORY_SIZE = 16 * 1024 * 1024; // 16MB
|
||||||
|
|
||||||
|
private final WebClient webClient;
|
||||||
|
|
||||||
|
/** 한 번 호출 시 보낼 externalId 최대 개수 (기본 100) */
|
||||||
|
private final int chunkSize;
|
||||||
|
|
||||||
public SamsaraStatOdometerClient(
|
public SamsaraStatOdometerClient(
|
||||||
WebClient.Builder webClientBuilder,
|
WebClient.Builder webClientBuilder,
|
||||||
@Value("${integration.api.base-url}") String integrationBaseUrl
|
@Value("${integration.api.base-url}") String integrationBaseUrl,
|
||||||
|
@Value("${integration.api.odometer.chunk-size:100}") int chunkSize
|
||||||
) {
|
) {
|
||||||
this.webClient = webClientBuilder
|
this.webClient = webClientBuilder
|
||||||
.baseUrl(integrationBaseUrl)
|
.baseUrl(integrationBaseUrl)
|
||||||
|
// DataBufferLimitException(262144) 방지
|
||||||
|
.codecs(configurer ->
|
||||||
|
configurer.defaultCodecs().maxInMemorySize(MAX_IN_MEMORY_SIZE))
|
||||||
.build();
|
.build();
|
||||||
|
this.chunkSize = chunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* integration-service 호출
|
* integration-service 호출
|
||||||
* POST /vehicle/odometer/fetch
|
* POST /vehicle/stat/odometer/fetch
|
||||||
|
*
|
||||||
|
* externalIds 가 chunkSize 를 넘으면 나눠서 호출하고 records 를 병합한다.
|
||||||
*/
|
*/
|
||||||
public ExtSamsaraOdometerFetchCommand fetchOdometer(
|
public ExtSamsaraOdometerFetchCommand fetchOdometer(
|
||||||
ScheduleWorkerRequestDto request
|
ScheduleWorkerRequestDto request
|
||||||
) {
|
) {
|
||||||
|
List<String> externalIds = request.getVehicleExternalIds();
|
||||||
|
|
||||||
try {
|
// externalIds 가 없거나 chunkSize 이하이면 단건 호출
|
||||||
return webClient.post()
|
if (externalIds == null || externalIds.size() <= chunkSize) {
|
||||||
|
return callOnce(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// chunk 단위로 나눠서 호출 → records 병합
|
||||||
|
final List<String> originalIds = externalIds;
|
||||||
|
List<ExtSamsaraOdometerRecordDto> mergedRecords = new ArrayList<>();
|
||||||
|
String source = null;
|
||||||
|
LocalDateTime fetchedAt = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < originalIds.size(); i += chunkSize) {
|
||||||
|
List<String> chunk = originalIds.subList(
|
||||||
|
i, Math.min(i + chunkSize, originalIds.size()));
|
||||||
|
|
||||||
|
// 호출자 객체에 청크 세팅 (마지막에 원복)
|
||||||
|
request.setVehicleExternalIds(chunk);
|
||||||
|
|
||||||
|
ExtSamsaraOdometerFetchCommand part = callOnce(request);
|
||||||
|
if (part == null || part.getRecords() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// source / fetchedAt 은 첫 응답 기준으로 유지
|
||||||
|
if (source == null) {
|
||||||
|
source = part.getSource();
|
||||||
|
fetchedAt = part.getFetchedAt();
|
||||||
|
}
|
||||||
|
mergedRecords.addAll(part.getRecords());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// 호출자 request 객체 원복 (부수효과 방지)
|
||||||
|
request.setVehicleExternalIds(originalIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("[ODOMETER_RAW][CHUNK] totalExternalIds={} chunkSize={} mergedRecords={}",
|
||||||
|
originalIds.size(), chunkSize, mergedRecords.size());
|
||||||
|
|
||||||
|
return ExtSamsaraOdometerFetchCommand.builder()
|
||||||
|
.source(source)
|
||||||
|
.fetchedAt(fetchedAt)
|
||||||
|
.records(mergedRecords)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 실제 단건 호출. 현재 request 에 세팅된 externalIds 로 그대로 호출한다.
|
||||||
|
*/
|
||||||
|
private ExtSamsaraOdometerFetchCommand callOnce(
|
||||||
|
ScheduleWorkerRequestDto request
|
||||||
|
) {
|
||||||
|
return webClient.post()
|
||||||
.uri("/vehicle/stat/odometer/fetch")
|
.uri("/vehicle/stat/odometer/fetch")
|
||||||
.bodyValue(request)
|
.bodyValue(request)
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.onStatus(
|
.onStatus(
|
||||||
status -> status.is4xxClientError() || status.is5xxServerError(),
|
status -> status.is4xxClientError() || status.is5xxServerError(),
|
||||||
resp -> resp.bodyToMono(String.class)
|
resp -> resp.bodyToMono(String.class)
|
||||||
.map(body ->
|
.map(body ->
|
||||||
new RuntimeException(
|
new RuntimeException("INTEGRATION_ERROR: " + body)
|
||||||
"INTEGRATION_ERROR: " + body
|
)
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.bodyToMono(ExtSamsaraOdometerFetchCommand.class)
|
.bodyToMono(ExtSamsaraOdometerFetchCommand.class)
|
||||||
.block();
|
.block();
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 이 메시지가 OPR 서비스 레벨까지 올라감
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue