From d9bf2f64b822abc87f57ede53cb7f090b8ded1b0 Mon Sep 17 00:00:00 2001 From: bjkim Date: Tue, 23 Sep 2025 17:45:07 +0900 Subject: [PATCH] =?UTF-8?q?[UPDATE]=20Experiments=20API=20Kubeflow=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9D=91=EB=8B=B5=20=EC=B2=98=EB=A6=AC=20=EA=B0=84?= =?UTF-8?q?=EC=86=8C=ED=99=94=20(ExperimentsController)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/ExperimentsController.java | 78 +++++++++++++++---- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/src/main/java/kr/re/etri/autoflow/controllers/ExperimentsController.java b/src/main/java/kr/re/etri/autoflow/controllers/ExperimentsController.java index 3df3595..bc7c10b 100644 --- a/src/main/java/kr/re/etri/autoflow/controllers/ExperimentsController.java +++ b/src/main/java/kr/re/etri/autoflow/controllers/ExperimentsController.java @@ -64,6 +64,56 @@ public class ExperimentsController { return ResponseEntity.ok(page); } +// @Operation(summary = "Experiment 등록") +// @PostMapping +// public Mono> createExperiment(@RequestBody ExperimentsEntity experiment) { +// +// // 1️⃣ DB 저장 +// ExperimentsEntity saved = experimentsService.save(experiment); +// +// // 2️⃣ Kubeflow POST 요청 payload +// Map payload = new HashMap<>(); +// payload.put("display_name", saved.getDisplayName()); +// payload.put("description", saved.getDescription()); +// payload.put("namespace", "default"); // 필요에 따라 변경 +// +// // 3️⃣ WebClient POST +// return webClientBuilder.build() +// .post() +// .uri(kubeflowBaseUrl + "/apis/v2beta1/experiments") +// .contentType(MediaType.APPLICATION_JSON) +// .bodyValue(payload) +// .retrieve() +// .bodyToMono(Map.class) // Kubeflow 응답 +// .map(resp -> { +// // resp에서 필요한 값 추출 후 entity에 반영 +// if(resp.get("id") != null) { +// saved.setKubeFlowId(resp.get("id").toString()); +// } +// +// if (resp.get("storage_state") != null) { +// saved.setKubeflowStorageState(resp.get("storage_state").toString()); +// } +// +// if (resp.get("created_at") != null) { +// String lastRunStr = resp.get("created_at").toString(); +// OffsetDateTime odt = OffsetDateTime.parse(lastRunStr); +// saved.setKubeflowCreatedAt(odt.withOffsetSameInstant(ZoneId.of("Asia/Seoul").getRules().getOffset(odt.toInstant())) +// .toLocalDateTime()); +// } +// +// if (resp.get("last_run_created_at") != null) { +// String lastRunStr = resp.get("last_run_created_at").toString(); +// OffsetDateTime odt = OffsetDateTime.parse(lastRunStr); +// saved.setKubeflowLastRunCreatedAt(odt.withOffsetSameInstant(ZoneId.of("Asia/Seoul").getRules().getOffset(odt.toInstant())) +// .toLocalDateTime()); +// } +// return saved; +// }) +// .map(ResponseEntity::ok) +// .doOnError(e -> log.error("Kubeflow experiment 등록 실패", e)); +// } + @Operation(summary = "Experiment 등록") @PostMapping public Mono> createExperiment(@RequestBody ExperimentsEntity experiment) { @@ -77,6 +127,16 @@ public class ExperimentsController { payload.put("description", saved.getDescription()); payload.put("namespace", "default"); // 필요에 따라 변경 + // 날짜를 ISO 8601 UTC 포맷으로 + DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT; + + payload.computeIfPresent("created_at", (k, v) -> + saved.getKubeflowCreatedAt() != null + ? saved.getKubeflowCreatedAt().atZone(ZoneId.of("Asia/Seoul")).format(formatter) + : null + ); + + // 3️⃣ WebClient POST return webClientBuilder.build() .post() @@ -84,21 +144,9 @@ public class ExperimentsController { .contentType(MediaType.APPLICATION_JSON) .bodyValue(payload) .retrieve() - .bodyToMono(Map.class) // Kubeflow 응답 - .map(resp -> { - // resp에서 필요한 값 추출 후 entity에 반영 - if (resp.get("last_run_created_at") != null) { - String lastRunStr = resp.get("last_run_created_at").toString(); - OffsetDateTime odt = OffsetDateTime.parse(lastRunStr); - saved.setKubeflowLastRunCreatedAt(odt.withOffsetSameInstant(ZoneId.of("Asia/Seoul").getRules().getOffset(odt.toInstant())) - .toLocalDateTime()); - } - if(resp.get("id") != null) { - saved.setKubeFlowId(resp.get("id").toString()); - } - return saved; - }) - .map(entity -> ResponseEntity.ok(entity)) + .bodyToMono(Map.class) // 응답 필요 없으면 Void.class + .doOnNext(resp -> log.info("Kubeflow experiment 등록 완료: {}", resp)) + .then(Mono.just(ResponseEntity.ok(saved))) // DB 저장된 엔티티 반환 .doOnError(e -> log.error("Kubeflow experiment 등록 실패", e)); }