[KC-103] 추론 실행 배치 수정

This commit is contained in:
2026-01-14 15:24:14 +09:00
parent 326591c4bd
commit 4d52e2a97a
5 changed files with 499 additions and 308 deletions

View File

@@ -23,7 +23,9 @@ import org.springframework.data.domain.Pageable;
public class InferenceResultDto {
/** 목록조회 dto */
/**
* 목록조회 dto
*/
@Getter
@Setter
@AllArgsConstructor
@@ -35,11 +37,15 @@ public class InferenceResultDto {
private String status;
private String mapSheetCnt;
private Long detectingCnt;
@JsonFormatDttm private ZonedDateTime startTime;
@JsonFormatDttm private ZonedDateTime endTime;
@JsonFormatDttm private ZonedDateTime elapsedTime;
@JsonFormatDttm
private ZonedDateTime startTime;
@JsonFormatDttm
private ZonedDateTime endTime;
@JsonFormatDttm
private ZonedDateTime elapsedTime;
private Boolean applyYn;
@JsonFormatDttm private ZonedDateTime applyDttm;
@JsonFormatDttm
private ZonedDateTime applyDttm;
@JsonProperty("statusName")
public String statusName() {
@@ -47,7 +53,9 @@ public class InferenceResultDto {
}
}
/** 목록조회 검색 조건 dto */
/**
* 목록조회 검색 조건 dto
*/
@Getter
@Setter
@NoArgsConstructor
@@ -69,7 +77,9 @@ public class InferenceResultDto {
}
}
/** 탐지 데이터 옵션 dto */
/**
* 탐지 데이터 옵션 dto
*/
@Getter
@AllArgsConstructor
public enum MapSheetScope implements EnumType {
@@ -90,7 +100,9 @@ public class InferenceResultDto {
}
}
/** 분석대상 도엽 enum */
/**
* 분석대상 도엽 enum
*/
@Getter
@AllArgsConstructor
public enum DetectOption implements EnumType {
@@ -138,7 +150,9 @@ public class InferenceResultDto {
}
}
/** 변화탐지 실행 정보 저장 요청 정보 */
/**
* 변화탐지 실행 정보 저장 요청 정보
*/
@Getter
@Setter
@NoArgsConstructor
@@ -177,8 +191,8 @@ public class InferenceResultDto {
@Schema(description = "탐지 데이터 옵션 - 추론제외(EXCL), 이전 년도 도엽 사용(PREV)", example = "EXCL")
@NotBlank
@EnumValid(
enumClass = DetectOption.class,
message = "탐지 데이터 옵션은 '추론제외', '이전 년도 도엽 사용' 만 사용 가능합니다.")
enumClass = DetectOption.class,
message = "탐지 데이터 옵션은 '추론제외', '이전 년도 도엽 사용' 만 사용 가능합니다.")
private String detectOption;
@Schema(description = "5k 도협 번호 목록", example = "[33605,33606, 33610, 34802, 35603, 35611]")
@@ -205,41 +219,49 @@ public class InferenceResultDto {
private Integer targetYyyy;
private String detectOption;
private String mapSheetScope;
@JsonFormatDttm private ZonedDateTime inferStartDttm;
@JsonFormatDttm private ZonedDateTime inferEndDttm;
@JsonFormatDttm
private ZonedDateTime inferStartDttm;
@JsonFormatDttm
private ZonedDateTime inferEndDttm;
private Long detectingCnt = 0L;
private Long detectingEndCnt = 0L;
@JsonFormatDttm private ZonedDateTime m1ModelStartDttm;
@JsonFormatDttm private ZonedDateTime m1ModelEndDttm;
@JsonFormatDttm private ZonedDateTime m2ModelStartDttm;
@JsonFormatDttm private ZonedDateTime m2ModelEndDttm;
@JsonFormatDttm private ZonedDateTime m3ModelStartDttm;
@JsonFormatDttm private ZonedDateTime m3ModelEndDttm;
@JsonFormatDttm
private ZonedDateTime m1ModelStartDttm;
@JsonFormatDttm
private ZonedDateTime m1ModelEndDttm;
@JsonFormatDttm
private ZonedDateTime m2ModelStartDttm;
@JsonFormatDttm
private ZonedDateTime m2ModelEndDttm;
@JsonFormatDttm
private ZonedDateTime m3ModelStartDttm;
@JsonFormatDttm
private ZonedDateTime m3ModelEndDttm;
private String model1Ver;
private String model2Ver;
private String model3Ver;
public InferenceStatusDetailDto(
String title,
Integer compareYyyy,
Integer targetYyyy,
String detectOption,
String mapSheetScope,
ZonedDateTime inferStartDttm,
ZonedDateTime inferEndDttm,
Long detectingCnt,
Long detectingEndCnt,
ZonedDateTime m1ModelStartDttm,
ZonedDateTime m1ModelEndDttm,
ZonedDateTime m2ModelStartDttm,
ZonedDateTime m2ModelEndDttm,
ZonedDateTime m3ModelStartDttm,
ZonedDateTime m3ModelEndDttm,
String model1Ver,
String model2Ver,
String model3Ver) {
String title,
Integer compareYyyy,
Integer targetYyyy,
String detectOption,
String mapSheetScope,
ZonedDateTime inferStartDttm,
ZonedDateTime inferEndDttm,
Long detectingCnt,
Long detectingEndCnt,
ZonedDateTime m1ModelStartDttm,
ZonedDateTime m1ModelEndDttm,
ZonedDateTime m2ModelStartDttm,
ZonedDateTime m2ModelEndDttm,
ZonedDateTime m3ModelStartDttm,
ZonedDateTime m3ModelEndDttm,
String model1Ver,
String model2Ver,
String model3Ver) {
this.title = title;
this.compareYyyy = compareYyyy;
this.targetYyyy = targetYyyy;
@@ -342,9 +364,12 @@ public class InferenceResultDto {
public static class InferenceServerStatusDto {
private String serverName;
@JsonIgnore private float cpu_user;
@JsonIgnore private float cpu_system;
@JsonIgnore private float memused;
@JsonIgnore
private float cpu_user;
@JsonIgnore
private float cpu_system;
@JsonIgnore
private float memused;
private Long kbmemused;
private float gpuUtil;
@@ -458,5 +483,9 @@ public class InferenceResultDto {
private ZonedDateTime modelEndDttm;
private Long updateUid;
private String runningModelType;
private Integer pendingJobs;
private Integer runningJobs;
private Integer completedJobs;
private Integer failedJobs;
}
}

View File

@@ -106,7 +106,7 @@ public class InferenceResultService {
// 변화탐지 실행 가능 비교년도 조회
List<MngListCompareDto> compareList =
mapSheetMngCoreService.getByHstMapSheetCompareList(req.getCompareYyyy(), mapTargetIds);
mapSheetMngCoreService.getByHstMapSheetCompareList(req.getCompareYyyy(), mapTargetIds);
if (compareList.isEmpty()) {
throw new CustomApiException("NOT_FOUND_COMPARE_YEAR", HttpStatus.NOT_FOUND);
@@ -140,6 +140,7 @@ public class InferenceResultService {
throw new CustomApiException("NOT_FOUND_COMPARE_YEAR", HttpStatus.NOT_FOUND);
}
// 사용할 영상파일 년도 기록 및 추론에 포함되는지 설정
for (MngListDto target : targetList) {
for (Map<String, Object> map : totalNumList) {
if (target.getMapSheetNum().equals(map.get("mapSheetNum").toString())) {
@@ -154,20 +155,20 @@ public class InferenceResultService {
// 추론에 필요한 geojson 파일 생성
List<String> mapSheetNumList =
targetList.stream()
.filter(t -> Boolean.TRUE.equals(t.getIsSuccess()))
.map(MngListDto::getMapSheetNum)
.toList();
targetList.stream()
.filter(t -> Boolean.TRUE.equals(t.getIsSuccess()))
.map(MngListDto::getMapSheetNum)
.toList();
// 비교년도 geojson 파일 생성하여 경로 받기
String modelComparePath =
getSceneInference(
String.valueOf(req.getCompareYyyy()), mapSheetNumList, req.getMapSheetScope());
getSceneInference(
String.valueOf(req.getCompareYyyy()), mapSheetNumList, req.getMapSheetScope());
// 기준년도 geojson 파일 생성하여 경로 받기
String modelTargetPath =
getSceneInference(
String.valueOf(req.getTargetYyyy()), mapSheetNumList, req.getMapSheetScope());
getSceneInference(
String.valueOf(req.getTargetYyyy()), mapSheetNumList, req.getMapSheetScope());
// ai 서버에 전달할 파라미터 생성
pred_requests_areas predRequestsAreas = new pred_requests_areas();
@@ -199,19 +200,19 @@ public class InferenceResultService {
// 비교년도 탐지 제이터 옵션 별로 조회하여 req에 적용
private List<MapSheetNumDto> createdMngDto(
InferenceResultDto.RegReq req, List<MngListDto> targetList) {
InferenceResultDto.RegReq req, List<MngListDto> targetList) {
List<String> mapTargetIds = new ArrayList<>();
targetList.forEach(
hstMapSheet -> {
// 비교년도는 target 년도 기준으로 가져옴 파라미터 만들기
mapTargetIds.add(hstMapSheet.getMapSheetNum());
});
hstMapSheet -> {
// 비교년도는 target 년도 기준으로 가져옴 파라미터 만들기
mapTargetIds.add(hstMapSheet.getMapSheetNum());
});
// 비교년도 조회
List<String> mapCompareIds = new ArrayList<>();
List<MngListCompareDto> compareList =
mapSheetMngCoreService.getByHstMapSheetCompareList(req.getCompareYyyy(), mapTargetIds);
mapSheetMngCoreService.getByHstMapSheetCompareList(req.getCompareYyyy(), mapTargetIds);
for (MngListCompareDto dto : compareList) {
// 추론 제외일때 이전년도 파일이 없으면 제외
@@ -226,35 +227,35 @@ public class InferenceResultService {
}
Set<String> compareSet =
mapCompareIds.stream()
.filter(Objects::nonNull)
.map(String::trim) // 공백/개행 방지
.collect(Collectors.toSet());
mapCompareIds.stream()
.filter(Objects::nonNull)
.map(String::trim) // 공백/개행 방지
.collect(Collectors.toSet());
// target 기준 compare 비교하여 서로 있는것만 저장
List<String> commonIds =
mapTargetIds.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(compareSet::contains)
.toList();
mapTargetIds.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(compareSet::contains)
.toList();
Set<String> commonIdSet =
commonIds.stream().filter(Objects::nonNull).map(String::trim).collect(Collectors.toSet());
commonIds.stream().filter(Objects::nonNull).map(String::trim).collect(Collectors.toSet());
// 저장하기위해 파라미터 다시 구성
List<MapSheetNumDto> mapSheetNum =
targetList.stream()
.filter(dto -> dto.getMapSheetNum() != null)
.filter(dto -> commonIdSet.contains(dto.getMapSheetNum().trim()))
.map(
dto -> {
MapSheetNumDto mapSheetNumDto = new MapSheetNumDto();
mapSheetNumDto.setMapSheetNum(dto.getMapSheetNum());
mapSheetNumDto.setMapSheetName(dto.getMapSheetName());
return mapSheetNumDto;
})
.toList();
targetList.stream()
.filter(dto -> dto.getMapSheetNum() != null)
.filter(dto -> commonIdSet.contains(dto.getMapSheetNum().trim()))
.map(
dto -> {
MapSheetNumDto mapSheetNumDto = new MapSheetNumDto();
mapSheetNumDto.setMapSheetNum(dto.getMapSheetNum());
mapSheetNumDto.setMapSheetName(dto.getMapSheetName());
return mapSheetNumDto;
})
.toList();
return mapSheetNum;
}
@@ -271,14 +272,14 @@ public class InferenceResultService {
throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST);
}
// 1) 요청 로그 (debug 권장)
// 1) 요청 로그
try {
log.debug("Inference request dto={}", objectMapper.writeValueAsString(dto));
} catch (JsonProcessingException e) {
log.warn("Failed to serialize inference dto", e);
}
// 2) local 환경 임시 처리 (NPE 방어)
// 2) local 환경 임시 처리
if ("local".equals(profile)) {
if (dto.getPred_requests_areas() == null) {
throw new IllegalStateException("pred_requests_areas is null");
@@ -293,7 +294,7 @@ public class InferenceResultService {
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
ExternalCallResult<String> result =
externalHttpClient.call(inferenceUrl, HttpMethod.POST, dto, headers, String.class);
externalHttpClient.call(inferenceUrl, HttpMethod.POST, dto, headers, String.class);
if (result.statusCode() < 200 || result.statusCode() >= 300) {
log.error("Inference API failed. status={}, body={}", result.statusCode(), result.body());
@@ -303,7 +304,8 @@ public class InferenceResultService {
// 4) 응답 파싱
try {
List<Map<String, Object>> list =
objectMapper.readValue(result.body(), new TypeReference<>() {});
objectMapper.readValue(result.body(), new TypeReference<>() {
});
if (list.isEmpty()) {
throw new IllegalStateException("Inference response is empty");
@@ -372,8 +374,8 @@ public class InferenceResultService {
/**
* geojson 파일 생성
*
* @param yyyy 영상관리 파일별 년도
* @param mapSheetNums 5k 도엽 번호 리스트
* @param yyyy 영상관리 파일별 년도
* @param mapSheetNums 5k 도엽 번호 리스트
* @param mapSheetScope EXCL : 추론제외, PREV 이전 년도 도엽 사용
* @return
*/
@@ -408,7 +410,7 @@ public class InferenceResultService {
* @return
*/
public Page<InferenceDetailDto.Geom> getInferenceResultGeomList(
Long id, InferenceDetailDto.SearchGeoReq searchGeoReq) {
Long id, InferenceDetailDto.SearchGeoReq searchGeoReq) {
return inferenceResultCoreService.getInferenceResultGeomList(id, searchGeoReq);
}
@@ -419,7 +421,7 @@ public class InferenceResultService {
* @return
*/
public Page<InferenceDetailDto.DetailListEntity> listInferenceResultWithGeom(
@NotNull Long id, InferenceDetailDto.SearchGeoReq searchReq) {
@NotNull Long id, InferenceDetailDto.SearchGeoReq searchReq) {
return inferenceResultCoreService.listInferenceResultWithGeom(id, searchReq);
}
@@ -464,7 +466,7 @@ public class InferenceResultService {
public InferenceStatusDetailDto getInferenceStatus(UUID uuid) {
List<InferenceServerStatusDto> servers =
inferenceResultCoreService.getInferenceServerStatusList();
inferenceResultCoreService.getInferenceServerStatusList();
String serverNames = "";
for (InferenceServerStatusDto server : servers) {