From 15fbdca89e47395bbe5dc2d3f7566319ccd4c5a0 Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 14 Jan 2026 18:54:30 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=B6=94=EB=A1=A0=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20=EC=B6=94=EB=A1=A0=20=EC=A2=85=EB=A3=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resttemplate/ExternalHttpClient.java | 60 ++++++++++++++++--- .../InferenceResultApiController.java | 20 +++++++ .../service/InferenceResultService.java | 31 +++++++++- .../core/InferenceResultCoreService.java | 22 ++++++- .../MapSheetLearnRepositoryCustom.java | 2 +- .../MapSheetLearnRepositoryImpl.java | 4 +- .../service/MapSheetInferenceJobService.java | 6 +- 7 files changed, 128 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java b/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java index 4e7b7acf..684e7ca7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java @@ -1,30 +1,72 @@ package com.kamco.cd.kamcoback.config.resttemplate; import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; 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.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; @Component +@Log4j2 @RequiredArgsConstructor public class ExternalHttpClient { private final RestTemplate restTemplate; - public ResponseEntity exchange( - String url, HttpMethod method, Object body, HttpHeaders headers, Class responseType) { - HttpEntity entity = new HttpEntity<>(body, headers); - return restTemplate.exchange(url, method, entity, responseType); - } - public ExternalCallResult call( String url, HttpMethod method, Object body, HttpHeaders headers, Class responseType) { - ResponseEntity res = exchange(url, method, body, headers, responseType); - int code = res.getStatusCodeValue(); - return new ExternalCallResult<>(code, code >= 200 && code < 300, res.getBody()); + + HttpEntity entity = new HttpEntity<>(body, headers); + + // 요청 로그 + log.info("[HTTP-REQ] {} {}", method, url); + if (body != null) { + log.debug("[HTTP-REQ-BODY] {}", body); + } + + try { + ResponseEntity res = restTemplate.exchange(url, method, entity, responseType); + + int code = res.getStatusCodeValue(); + + // 응답 로그 + log.info("[HTTP-RES] {} {} -> {}", method, url, code); + log.debug("[HTTP-RES-BODY] {}", res.getBody()); + + return new ExternalCallResult<>(code, code >= 200 && code < 300, res.getBody()); + + } catch (HttpClientErrorException.NotFound e) { + // ⭐ 핵심: 404를 예외가 아닌 결과로 처리 + log.info("[HTTP-RES] {} {} -> 404 (Not Found)", method, url); + log.debug("[HTTP-RES-BODY] {}", e.getResponseBodyAsString()); + + return new ExternalCallResult<>(404, false, null); + + } catch (HttpClientErrorException e) { + // 기타 4xx + log.warn( + "[HTTP-ERR] {} {} -> {} body={}", + method, + url, + e.getStatusCode().value(), + e.getResponseBodyAsString()); + throw e; + + } catch (HttpServerErrorException e) { + // 5xx + log.error( + "[HTTP-ERR] {} {} -> {} body={}", + method, + url, + e.getStatusCode().value(), + e.getResponseBodyAsString()); + throw e; + } } public record ExternalCallResult(int statusCode, boolean success, T body) {} 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 b946c6ab..19deebad 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -139,6 +140,25 @@ public class InferenceResultApiController { return ApiResponseDto.ok(uuid); } + @Operation(summary = "추론 종료", description = "추론 종료") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "종료 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Page.class))), + @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @DeleteMapping("/end") + public ApiResponseDto getInferenceGeomList() { + inferenceResultService.deleteInferenceEnd(); + return null; + } + @Operation(summary = "분석 모델 선택 조회", description = "변화탐지 실행 정보 입력 모델선택 팝업 ") @ApiResponses( value = { 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 1af57e25..e9c04006 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 @@ -84,7 +84,11 @@ public class InferenceResultService { * @return */ public UUID getProcessing() { - return inferenceResultCoreService.getProcessing(); + SaveInferenceAiDto dto = inferenceResultCoreService.getProcessing(); + if (dto == null) { + return null; + } + return dto.getUuid(); } /** @@ -184,7 +188,7 @@ public class InferenceResultService { m1.setPred_requests_areas(predRequestsAreas); // ai 추론 실행 api 호출 - Long batchId = 0L; // ensureAccepted(m1); + Long batchId = ensureAccepted(m1); // ai 추론 실행후 응답값 update SaveInferenceAiDto saveInferenceAiDto = new SaveInferenceAiDto(); @@ -487,4 +491,27 @@ public class InferenceResultService { public Page getInferenceGeomList(String uuid, SearchGeoReq searchGeoReq) { return inferenceResultCoreService.getInferenceGeomList(uuid, searchGeoReq); } + + public void deleteInferenceEnd() { + SaveInferenceAiDto dto = inferenceResultCoreService.getProcessing(); + if (dto == null) { + throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND); + } + Long batchId = dto.getBatchId(); + String url = inferenceUrl + "/" + batchId; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + + ExternalCallResult result = + externalHttpClient.call(url, HttpMethod.DELETE, dto, headers, String.class); + + System.out.println(result); + + SaveInferenceAiDto request = new SaveInferenceAiDto(); + request.setStatus(Status.END.getId()); + request.setUuid(dto.getUuid()); + inferenceResultCoreService.update(request); + } } 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 a78ff0b4..3cd55126 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 @@ -379,8 +379,26 @@ public class InferenceResultCoreService { * * @return */ - public UUID getProcessing() { - return mapSheetLearnRepository.getProcessing(); + public SaveInferenceAiDto getProcessing() { + MapSheetLearnEntity entity = mapSheetLearnRepository.getProcessing(); + + if (entity == null) { + return null; + } + + SaveInferenceAiDto dto = new SaveInferenceAiDto(); + dto.setUuid(entity.getUuid()); + + if (entity.getM3ModelBatchId() != null) { + dto.setBatchId(entity.getM3ModelBatchId()); + } + if (entity.getM2ModelBatchId() != null) { + dto.setBatchId(entity.getM2ModelBatchId()); + } + if (entity.getM1ModelBatchId() != null) { + dto.setBatchId(entity.getM1ModelBatchId()); + } + return dto; } /** diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryCustom.java index ec5f5eda..d6c4b8b0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryCustom.java @@ -28,7 +28,7 @@ public interface MapSheetLearnRepositoryCustom { InferenceStatusDetailDto getInferenceStatus(UUID uuid); - UUID getProcessing(); + MapSheetLearnEntity getProcessing(); Integer getLearnStage(Integer compareYear, Integer targetYear); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java index d58f9b53..381b63b5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/MapSheetLearnRepositoryImpl.java @@ -259,9 +259,9 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto * * @return */ - public UUID getProcessing() { + public MapSheetLearnEntity getProcessing() { return queryFactory - .select(mapSheetLearnEntity.uuid) + .select(mapSheetLearnEntity) .from(mapSheetLearnEntity) .where(mapSheetLearnEntity.status.eq("IN_PROGRESS")) .fetchOne(); diff --git a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java index fb640a53..7a7bd955 100644 --- a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java +++ b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java @@ -52,7 +52,7 @@ public class MapSheetInferenceJobService { @Transactional public void runBatch() { if (isLocalProfile()) { - return; + // return; } try { @@ -133,6 +133,10 @@ public class MapSheetInferenceJobService { externalHttpClient.call(url, HttpMethod.GET, null, jsonHeaders(), String.class); int status = result.statusCode(); + if (status == 404) { + log.info("Batch not found. batchId={}", batchId); + return null; + } if (status < 200 || status >= 300) { return null; } From 5b6f24d4e346be311916fc6dce44e5f5ad39e155 Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 14 Jan 2026 19:39:58 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=B6=94=EB=A1=A0=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20=EC=B6=94=EB=A1=A0=20=EC=A2=85=EB=A3=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/resttemplate/ExternalHttpClient.java | 1 - .../inference/service/InferenceResultService.java | 14 +++++++++++++- .../postgres/core/InferenceResultCoreService.java | 15 ++++++--------- .../service/MapSheetInferenceJobService.java | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java b/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java index 684e7ca7..013e01b5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/resttemplate/ExternalHttpClient.java @@ -41,7 +41,6 @@ public class ExternalHttpClient { return new ExternalCallResult<>(code, code >= 200 && code < 300, res.getBody()); } catch (HttpClientErrorException.NotFound e) { - // ⭐ 핵심: 404를 예외가 아닌 결과로 처리 log.info("[HTTP-RES] {} {} -> 404 (Not Found)", method, url); log.debug("[HTTP-RES-BODY] {}", e.getResponseBodyAsString()); 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 e9c04006..653e1aef 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 @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.kamco.cd.kamcoback.common.exception.CustomApiException; +import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient; import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult; import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto; @@ -65,9 +66,14 @@ public class InferenceResultService { @Value("${inference.url}") private String inferenceUrl; + @Value("${inference.batch-url}") + private String batchUrl; + @Value("${spring.profiles.active}") private String profile; + private final UserUtil userUtil; + /** * 추론관리 목록 * @@ -492,13 +498,15 @@ public class InferenceResultService { return inferenceResultCoreService.getInferenceGeomList(uuid, searchGeoReq); } + /** 추론 종료 */ + @Transactional public void deleteInferenceEnd() { SaveInferenceAiDto dto = inferenceResultCoreService.getProcessing(); if (dto == null) { throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND); } Long batchId = dto.getBatchId(); - String url = inferenceUrl + "/" + batchId; + String url = batchUrl + "/" + batchId; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); @@ -507,11 +515,15 @@ public class InferenceResultService { ExternalCallResult result = externalHttpClient.call(url, HttpMethod.DELETE, dto, headers, String.class); + if (!result.success()) { + throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND); + } System.out.println(result); SaveInferenceAiDto request = new SaveInferenceAiDto(); request.setStatus(Status.END.getId()); request.setUuid(dto.getUuid()); + request.setUpdateUid(userUtil.getId()); inferenceResultCoreService.update(request); } } 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 3cd55126..0a521c4d 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 @@ -21,6 +21,7 @@ import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearn5kEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity; +import com.kamco.cd.kamcoback.postgres.repository.Inference.InferenceResultRepository; import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetAnalDataInferenceRepository; import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetLearn5kRepository; import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetLearnRepository; @@ -50,6 +51,7 @@ public class InferenceResultCoreService { private final MapSheetLearnRepository mapSheetLearnRepository; private final MapInkx5kRepository mapInkx5kRepository; private final MapSheetLearn5kRepository mapSheetLearn5kRepository; + private final InferenceResultRepository inferenceResultRepository; private final EntityManager entityManager; private final UserUtil userUtil; @@ -401,15 +403,6 @@ public class InferenceResultCoreService { return dto; } - /** - * @param compareYear 비교년도 - * @param targetYear 기준년도 - * @return - */ - public Integer getLearnStage(Integer compareYear, Integer targetYear) { - return mapSheetLearnRepository.getLearnStage(compareYear, targetYear); - } - public AnalResultInfo getInferenceResultInfo(String uuid) { return mapSheetLearnRepository.getInferenceResultInfo(uuid); } @@ -421,4 +414,8 @@ public class InferenceResultCoreService { public Page getInferenceGeomList(String uuid, SearchGeoReq searchGeoReq) { return mapSheetLearnRepository.getInferenceGeomList(uuid, searchGeoReq); } + + public void upsertGeomsFromInferenceResults(Long id) { + int inferenceGeomCnt = inferenceResultRepository.upsertGeomsFromInferenceResults(); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java index 7a7bd955..56980e25 100644 --- a/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java +++ b/src/main/java/com/kamco/cd/kamcoback/scheduler/service/MapSheetInferenceJobService.java @@ -52,7 +52,7 @@ public class MapSheetInferenceJobService { @Transactional public void runBatch() { if (isLocalProfile()) { - // return; + return; } try {