From aba878d845f28b4ab2e90f5d94a532564c74b41b Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 9 Jan 2026 17:51:35 +0900 Subject: [PATCH] =?UTF-8?q?[KC-99]=20=EC=B6=94=EB=A1=A0=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20=EB=93=B1=EB=A1=9D=20=EC=88=98=EC=A0=95,=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/GlobalExceptionHandler.java | 15 ++---- .../kamcoback/config/api/ApiResponseDto.java | 21 ++++++++ .../InferenceResultApiController.java | 32 +++++++++++++ .../service/InferenceResultService.java | 24 ++++++---- .../core/InferenceResultCoreService.java | 48 ++++++++++++++++--- .../scene/MapInkx5kRepositoryCustom.java | 5 ++ .../scene/MapInkx5kRepositoryImpl.java | 20 ++++++++ 7 files changed, 137 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java index bff7b299..8eaea370 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/GlobalExceptionHandler.java @@ -487,22 +487,13 @@ public class GlobalExceptionHandler { this.errorLog(request, e); String codeName = e.getCodeName(); HttpStatus status = e.getStatus(); - // String message = e.getMessage() == null ? ApiResponseCode.getMessage(codeName) : - // e.getMessage(); - // - // ApiResponseCode apiCode = ApiResponseCode.getCode(codeName); - // - // ErrorLogEntity errorLog = - // saveErrorLogData( - // request, apiCode, status, ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace()); - // - // ApiResponseDto body = - // ApiResponseDto.createException(apiCode, message, status, errorLog.getId()); + + ApiResponseCode responseCode = ApiResponseCode.from(codeName, status); ErrorLogEntity errorLog = saveErrorLogData( request, - ApiResponseCode.getCode(codeName), + responseCode, HttpStatus.valueOf(status.value()), ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace()); diff --git a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java index e0767419..827b606e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiResponseDto.java @@ -194,5 +194,26 @@ public class ApiResponseDto { public static String getMessage(String name) { return ApiResponseCode.valueOf(name.toUpperCase()).getText(); } + + public static ApiResponseCode from(String codeName, HttpStatus status) { + + if (codeName != null && !codeName.isBlank()) { + try { + return ApiResponseCode.valueOf(codeName.toUpperCase()); + } catch (IllegalArgumentException ignore) { + // fallback + } + } + + if (status != null) { + try { + return ApiResponseCode.valueOf(status.name()); + } catch (IllegalArgumentException ignore) { + // fallback + } + } + + return INTERNAL_SERVER_ERROR; + } } } diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java index 5215dc2e..0711f5ee 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java @@ -5,6 +5,8 @@ import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList; import com.kamco.cd.kamcoback.inference.service.InferenceResultService; import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngService; +import com.kamco.cd.kamcoback.model.dto.ModelMngDto; +import com.kamco.cd.kamcoback.model.service.ModelMngService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -34,6 +36,7 @@ public class InferenceResultApiController { private final InferenceResultService inferenceResultService; private final MapSheetMngService mapSheetMngService; + private final ModelMngService modelMngService; @Operation(summary = "추론관리 목록", description = "어드민 홈 > 추론관리 > 추론관리 > 추론관리 목록") @ApiResponses( @@ -110,6 +113,35 @@ public class InferenceResultApiController { return ApiResponseDto.ok(uuid); } + @Operation(summary = "분석 모델 선택 조회", description = "변화탐지 실행 정보 입력 모델선택 팝업 ") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "분석 모델 조회 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(description = "분석 모델", implementation = Page.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/model") + public ApiResponseDto> saveInferenceInfo( + @Parameter(description = "모델 생성일 시작", example = "2025-12-01") @RequestParam(required = false) + LocalDate strtDttm, + @Parameter(description = "모델 생성일 종료", example = "2026-01-09") @RequestParam(required = false) + LocalDate endDttm, + @Parameter(description = "키워드 (모델버전)", example = "M1.H1.E28") @RequestParam(required = false) + String searchVal, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "20") int size) { + ModelMngDto.searchReq searchReq = new ModelMngDto.searchReq(page, size, null); + Page result = + modelMngService.findModelMgmtList(searchReq, strtDttm, endDttm, null, searchVal); + return ApiResponseDto.ok(result); + } + // @ApiResponses( // value = { // @ApiResponse( diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java index 02e22caa..e1f99c9a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java @@ -61,13 +61,13 @@ public class InferenceResultService { // TODO tif 없으면 전년도 파일 조회 쿼리 추가해야함 // TODO 도엽 개수를 target 기준으로 맞춰야함 - this.getSceneInference(String.valueOf(req.getCompareYyyy()), req.getMapSheetNum()); - this.getSceneInference(String.valueOf(req.getTargetYyyy()), req.getMapSheetNum()); - - InferenceSendDto m1 = this.getModelInfo(req.getModel1Uuid()); - InferenceSendDto m2 = this.getModelInfo(req.getModel2Uuid()); - InferenceSendDto m3 = this.getModelInfo(req.getModel3Uuid()); - + // this.getSceneInference(String.valueOf(req.getCompareYyyy()), req.getMapSheetNum()); + // this.getSceneInference(String.valueOf(req.getTargetYyyy()), req.getMapSheetNum()); + // + // InferenceSendDto m1 = this.getModelInfo(req.getModel1Uuid()); + // InferenceSendDto m2 = this.getModelInfo(req.getModel2Uuid()); + // InferenceSendDto m3 = this.getModelInfo(req.getModel3Uuid()); + // // ensureAccepted(m1); // ensureAccepted(m2); // ensureAccepted(m3); @@ -93,16 +93,20 @@ public class InferenceResultService { .onErrorReturn(false); } + /** + * api 호출 실패시 예외처리 + * + * @param dto + */ private void ensureAccepted(InferenceSendDto dto) { Boolean ok = this.inferenceSend(dto) - .timeout(java.time.Duration.ofSeconds(3)) // 접수는 빨리 와야 함 + .timeout(java.time.Duration.ofSeconds(3)) .onErrorReturn(false) // 타임아웃/통신오류도 실패 처리 - .block(java.time.Duration.ofSeconds(4)); // 최종 안전장치 (짧게!) + .block(java.time.Duration.ofSeconds(4)); if (!Boolean.TRUE.equals(ok)) { - // 여기서 예외가 터져야 @Transactional 롤백됨 throw new CustomApiException("BAD_GATEWAY", HttpStatus.BAD_GATEWAY); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java index 8eaeb774..157e92c4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java @@ -1,5 +1,6 @@ package com.kamco.cd.kamcoback.postgres.core; +import com.kamco.cd.kamcoback.common.enums.CommonUseStatus; import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto; import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard; @@ -20,6 +21,7 @@ import jakarta.persistence.EntityNotFoundException; import jakarta.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -69,6 +71,14 @@ public class InferenceResultCoreService { // learn 테이블 저장 MapSheetLearnEntity savedLearn = mapSheetLearnRepository.save(mapSheetLearnEntity); + // if (req.getMapSheetScope().equals(MapSheetScope.ALL)) { + // List mapSheetIds = new ArrayList<>(); + // mapInkx5kRepository.findAll().forEach(mapInkx5kEntity -> { + // mapSheetIds.add(mapInkx5kEntity.getMapidcdNo()); + // }); + // req.setMapSheetNum(mapSheetIds); + // } + final int CHUNK = 1000; List buffer = new ArrayList<>(CHUNK); List mapSheetNumList = req.getMapSheetNum(); @@ -82,22 +92,48 @@ public class InferenceResultCoreService { buffer.add(e); if (buffer.size() == CHUNK) { - mapSheetLearn5kRepository.saveAll(buffer); - mapSheetLearn5kRepository.flush(); - entityManager.clear(); + this.flushChunk(buffer); buffer.clear(); } } if (!buffer.isEmpty()) { - mapSheetLearn5kRepository.saveAll(buffer); - mapSheetLearn5kRepository.flush(); - entityManager.clear(); + this.flushChunk(buffer); + buffer.clear(); } return savedLearn.getUuid(); } + private void flushChunk(List buffer) { + + // 청크 번호 추출 in 조건 만들기 + List chunkNums = + buffer.stream().map(e -> String.valueOf(e.getMapSheetNum())).distinct().toList(); + + // 추론 제외 + List usedEntities = + mapInkx5kRepository.findByMapSheetNumInAndUseInference(chunkNums, CommonUseStatus.USE); + + // TODO 추론 제외 했으면 파일 있는지도 확인 해야함 + // 조회 결과에서 번호만 Set으로 + Set usedSet = + usedEntities.stream() + .map(MapInkx5kEntity::getMapidcdNo) + .collect(java.util.stream.Collectors.toSet()); + + // 필터 후 저장 + List toSave = + buffer.stream().filter(e -> usedSet.contains(String.valueOf(e.getMapSheetNum()))).toList(); + + if (!toSave.isEmpty()) { + mapSheetLearn5kRepository.saveAll(toSave); + mapSheetLearn5kRepository.flush(); + } + + entityManager.clear(); + } + /****/ /** diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryCustom.java index ee971c5c..7ec9bc0e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryCustom.java @@ -22,4 +22,9 @@ public interface MapInkx5kRepositoryCustom { Page getSceneListByPage( CommonUseStatus useInference, String searchVal, searchReq searchReq); + + List findByMapSheetNumInAndUseInference( + List mapSheetNums, CommonUseStatus use); + + Optional findByMapidList(); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryImpl.java index 6e3789d3..036d704b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/scene/MapInkx5kRepositoryImpl.java @@ -20,7 +20,9 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; +import org.springframework.stereotype.Repository; +@Repository public class MapInkx5kRepositoryImpl extends QuerydslRepositorySupport implements MapInkx5kRepositoryCustom { @@ -127,6 +129,24 @@ public class MapInkx5kRepositoryImpl extends QuerydslRepositorySupport return new PageImpl<>(content, pageable, count); } + @Override + public List findByMapSheetNumInAndUseInference( + List mapSheetNums, CommonUseStatus use) { + if (mapSheetNums == null || mapSheetNums.isEmpty()) { + return List.of(); + } + + return queryFactory + .selectFrom(mapInkx5kEntity) + .where(mapInkx5kEntity.mapidcdNo.in(mapSheetNums), mapInkx5kEntity.useInference.eq(use)) + .fetch(); + } + + @Override + public Optional findByMapidList() { + return Optional.empty(); + } + private BooleanExpression searchUseInference(CommonUseStatus useInference) { if (Objects.isNull(useInference)) { return null;