package kr.re.etri.autoflow.controllers; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import kr.re.etri.autoflow.entity.KubeflowRunEntity; import kr.re.etri.autoflow.payload.request.KubeflowRunSearchRequest; import kr.re.etri.autoflow.repository.KubeflowRunRepository; import kr.re.etri.autoflow.service.KubeflowRunService; import kr.re.etri.autoflow.service.PipelineUploadService; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springdoc.core.annotations.ParameterObject; import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @Tag(name = "Kubeflow Run", description = "Kubeflow Run 조회 API") @RestController @RequestMapping("/api/kubeflow/runs") @RequiredArgsConstructor public class KubeflowRunsController { private static final Logger log = LoggerFactory.getLogger(KubeflowRunsController.class); private final KubeflowRunRepository runRepository; private final KubeflowRunService kubeflowRunService; private final PipelineUploadService pipelineUploadService; @Operation(summary = "모든 Kubeflow Run 조회") @GetMapping public ResponseEntity> getAllRuns() { List runs = runRepository.findAll(); return ResponseEntity.ok(runs); } @Operation(summary = "Kubeflow Run 단건 조회") @GetMapping("/{runId}") public ResponseEntity getRun( @Parameter(description = "Kubeflow Run ID", example = "ad980d7f-050a-4c59-a775-94394befad40") @PathVariable("runId") String runId) { return runRepository.findByRunId(runId) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } @Operation(summary = "Kubeflow Run 검색 및 페이지네이션 조회") @GetMapping("/search") public ResponseEntity> searchRuns( @ParameterObject @ModelAttribute KubeflowRunSearchRequest request) { log.info("[KubeflowRuns] GET /api/kubeflow/runs/search 호출됨 (Run 목록 조회)"); Page page = kubeflowRunService.search(request); int total = page.getNumberOfElements(); String firstRunId = page.getContent().isEmpty() ? null : page.getContent().get(0).getRunId(); log.info("[KubeflowRuns] search 응답: content 개수={}, totalElements={}, 첫 run runId={}", total, page.getTotalElements(), firstRunId != null ? firstRunId : "(없음)"); return ResponseEntity.ok(page); } @Operation(summary = "Kubeflow Run 삭제 (KFP에서 삭제 성공 시에만 DB에서 제거)") @DeleteMapping("/{runId}") public ResponseEntity deleteRun( @Parameter(description = "Kubeflow Run ID", example = "ad980d7f-050a-4c59-a775-94394befad40") @PathVariable("runId") String runId) { return runRepository.findByRunId(runId) .map((entity) -> { try { pipelineUploadService.deleteKfpRun(runId, entity.getExperimentId()); } catch (Exception e) { log.warn("[KubeflowRuns] KFP Run 삭제 실패, DB는 유지: runId={}, error={}", runId, e.getMessage()); return ResponseEntity.status(HttpStatus.BAD_GATEWAY) .body("KFP Run 삭제 실패. 목록에서 제거되지 않습니다: " + e.getMessage()); } runRepository.delete(entity); return ResponseEntity.noContent().build(); }) .orElse(ResponseEntity.notFound().build()); } }