From a7ada857640bd53dcdf9acc5af12b54cbd07fcc8 Mon Sep 17 00:00:00 2001 From: kakusiA Date: Tue, 23 Sep 2025 09:52:06 +0900 Subject: [PATCH 1/6] =?UTF-8?q?fix:sql=EB=AC=B8=EC=88=98=EC=A0=95=20-=20wo?= =?UTF-8?q?rkflow=20insert=EB=AC=B8=20default=5Fconfig=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20-=20=EC=8A=A4=EC=BC=80=EC=A4=84=EB=9F=AC=20=EC=8A=A4?= =?UTF-8?q?=ED=82=A4=EB=A7=88=20workflow=5Fid=20=EC=9C=A0=EB=8B=88?= =?UTF-8?q?=ED=81=AC=20=ED=82=A4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user-service/src/main/resources/sql/01-schema.sql | 5 +++++ .../src/main/resources/sql/03-insert-workflow.sql | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/user-service/src/main/resources/sql/01-schema.sql b/apps/user-service/src/main/resources/sql/01-schema.sql index 31242c33..26f2fb1b 100644 --- a/apps/user-service/src/main/resources/sql/01-schema.sql +++ b/apps/user-service/src/main/resources/sql/01-schema.sql @@ -333,3 +333,8 @@ CREATE INDEX idx_log_level_status ON execution_log(log_level, status); CREATE INDEX idx_error_code ON execution_log(error_code); CREATE INDEX idx_duration ON execution_log(duration_ms); CREATE INDEX idx_execution_type_source ON execution_log(execution_type, source_id); + +-- v0.5 +-- 기존 schedule 테이블 유니크키 수정 +-- 컬럼 추가 (한 번에 하나씩) +ALTER TABLE schedule DROP CONSTRAINT uk_schedule_workflow; diff --git a/apps/user-service/src/main/resources/sql/03-insert-workflow.sql b/apps/user-service/src/main/resources/sql/03-insert-workflow.sql index 9b6db4c0..d2efbe91 100644 --- a/apps/user-service/src/main/resources/sql/03-insert-workflow.sql +++ b/apps/user-service/src/main/resources/sql/03-insert-workflow.sql @@ -14,10 +14,13 @@ DELETE FROM `workflow`; -- =================================================================== -- 워크플로우 생성 (ID: 1) -INSERT INTO `workflow` (`id`, `name`, `description`, `created_by`) VALUES - (1, '상품 분석 및 블로그 자동 발행', '키워드 검색부터 상품 분석 후 블로그 발행까지의 자동화 프로세스', 1) - ON DUPLICATE KEY UPDATE name = VALUES(name), description = VALUES(description), updated_at = NOW(); - +INSERT INTO `workflow` (`id`, `name`, `description`, `created_by`, `default_config`) VALUES + (1, '상품 분석 및 블로그 자동 발행', '키워드 검색부터 상품 분석 후 블로그 발행까지의 자동화 프로세스', 1, + JSON_OBJECT('keyword_search',json_object('tag',"naver"),'blog_publish',json_object('tag',"naver_blog",'blog_id', "wtecho331", 'blog_pw', "testpass"))) +ON DUPLICATE KEY UPDATE + name = VALUES(name), + description = VALUES(description), + updated_at = NOW(); -- Job 생성 (ID: 1, 2) INSERT INTO `job` (`id`, `name`, `description`, `created_by`) VALUES (1, '상품 분석', '키워드 검색, 상품 크롤링 및 유사도 분석 작업', 1), From 1ea2fecdfa363472c493cb082d6d8129d91186ff Mon Sep 17 00:00:00 2001 From: kakusiA Date: Tue, 23 Sep 2025 10:42:50 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EC=9B=8C=ED=81=AC=20=ED=94=8C?= =?UTF-8?q?=EB=A1=9C=EC=9A=B0=20=EB=94=94=ED=85=8C=EC=9D=BC=20API=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20-=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0?= =?UTF-8?q?=20=EB=94=94=ED=85=8C=EC=9D=BC=20DTO=20=EC=83=9D=EC=84=B1=20-?= =?UTF-8?q?=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EB=94=94?= =?UTF-8?q?=ED=85=8C=EC=9D=BC=20=EC=9E=A1=20DTO=20=EC=83=9D=EC=84=B1=20-?= =?UTF-8?q?=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EB=94=94?= =?UTF-8?q?=ED=85=8C=EC=9D=BC=20mybatis=20sql=EB=AC=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/WorkflowController.java | 8 ++ .../domain/workflow/dto/ScheduleDto.java | 16 ++++ .../workflow/dto/WorkflowDetailCardDto.java | 16 ++++ .../workflow/mapper/WorkflowMapper.java | 8 ++ .../workflow/service/WorkflowService.java | 25 ++++++ .../mybatis/mapper/WorkflowMapper.xml | 90 +++++++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 apps/user-service/src/main/java/site/icebang/domain/workflow/dto/ScheduleDto.java create mode 100644 apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowDetailCardDto.java diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java index 348058ee..155d13df 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java @@ -1,5 +1,6 @@ package site.icebang.domain.workflow.controller; +import java.math.BigInteger; import java.util.concurrent.CompletableFuture; import org.springframework.http.ResponseEntity; @@ -11,6 +12,7 @@ import site.icebang.common.dto.PageParams; import site.icebang.common.dto.PageResult; import site.icebang.domain.workflow.dto.WorkflowCardDto; +import site.icebang.domain.workflow.dto.WorkflowDetailCardDto; import site.icebang.domain.workflow.service.WorkflowExecutionService; import site.icebang.domain.workflow.service.WorkflowService; @@ -34,4 +36,10 @@ public ResponseEntity runWorkflow(@PathVariable Long workflowId) { CompletableFuture.runAsync(() -> workflowExecutionService.executeWorkflow(workflowId)); return ResponseEntity.accepted().build(); } + + @GetMapping("/{workflowId}/detail") + public ApiResponse getWorkflowDetail(@PathVariable BigInteger workflowId) { + WorkflowDetailCardDto result = workflowService.getWorkflowDetail(workflowId); + return ApiResponse.success(result); + } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/ScheduleDto.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/ScheduleDto.java new file mode 100644 index 00000000..397285cb --- /dev/null +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/ScheduleDto.java @@ -0,0 +1,16 @@ +package site.icebang.domain.workflow.dto; + +import java.time.LocalDateTime; + +import lombok.Data; + +@Data +public class ScheduleDto { + private Long id; + private String cronExpression; + private Boolean isActive; + private String lastRunStatus; + private LocalDateTime lastRunAt; + private String scheduleText; + private LocalDateTime createdAt; +} diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowDetailCardDto.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowDetailCardDto.java new file mode 100644 index 00000000..a2ef46b8 --- /dev/null +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowDetailCardDto.java @@ -0,0 +1,16 @@ +package site.icebang.domain.workflow.dto; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +import lombok.Data; + +@Data +public class WorkflowDetailCardDto extends WorkflowCardDto { + private String defaultConfig; + private LocalDateTime updatedAt; + private String updatedBy; + private List schedules; + private List> jobs; +} diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java index 00afbebc..82381737 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java @@ -4,7 +4,9 @@ import java.util.*; import site.icebang.common.dto.PageParams; +import site.icebang.domain.workflow.dto.ScheduleDto; import site.icebang.domain.workflow.dto.WorkflowCardDto; +import site.icebang.domain.workflow.dto.WorkflowDetailCardDto; public interface WorkflowMapper { List selectWorkflowList(PageParams pageParams); @@ -12,4 +14,10 @@ public interface WorkflowMapper { int selectWorkflowCount(PageParams pageParams); WorkflowCardDto selectWorkflowById(BigInteger id); + + WorkflowDetailCardDto selectWorkflowDetailById(BigInteger workflowId); + + List selectSchedulesByWorkflowId(BigInteger workflowId); + + List> selectWorkflowWithJobsAndTasks(BigInteger workflowId); } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java index 71600b4b..b994c82e 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java @@ -1,5 +1,9 @@ package site.icebang.domain.workflow.service; +import java.math.BigInteger; +import java.util.List; +import java.util.Map; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,7 +12,9 @@ import site.icebang.common.dto.PageParams; import site.icebang.common.dto.PageResult; import site.icebang.common.service.PageableService; +import site.icebang.domain.workflow.dto.ScheduleDto; import site.icebang.domain.workflow.dto.WorkflowCardDto; +import site.icebang.domain.workflow.dto.WorkflowDetailCardDto; import site.icebang.domain.workflow.mapper.WorkflowMapper; @Service @@ -25,4 +31,23 @@ public PageResult getPagedResult(PageParams pageParams) { () -> workflowMapper.selectWorkflowList(pageParams), () -> workflowMapper.selectWorkflowCount(pageParams)); } + + @Transactional(readOnly = true) + public WorkflowDetailCardDto getWorkflowDetail(BigInteger workflowId) { + + // 1. 워크플로우 기본 정보 조회 (단일 row, 효율적) + WorkflowDetailCardDto workflow = workflowMapper.selectWorkflowDetailById(workflowId); + if (workflow == null) { + throw new IllegalArgumentException("워크플로우를 찾을 수 없습니다: " + workflowId); + } + + // 2. 스케줄 목록 조회 (별도 쿼리로 성능 최적화) + List schedules = workflowMapper.selectSchedulesByWorkflowId(workflowId); + workflow.setSchedules(schedules); + + List> jobs = workflowMapper.selectWorkflowWithJobsAndTasks(workflowId); + workflow.setJobs(jobs); + + return workflow; + } } diff --git a/apps/user-service/src/main/resources/mybatis/mapper/WorkflowMapper.xml b/apps/user-service/src/main/resources/mybatis/mapper/WorkflowMapper.xml index dacade96..63a9f6db 100644 --- a/apps/user-service/src/main/resources/mybatis/mapper/WorkflowMapper.xml +++ b/apps/user-service/src/main/resources/mybatis/mapper/WorkflowMapper.xml @@ -39,4 +39,94 @@ LEFT JOIN user u ON w.created_by = u.id WHERE w.id = #{id} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From e977b39d9a7a77eedc20ea73ca88dd09b3eb1135 Mon Sep 17 00:00:00 2001 From: kakusiA Date: Tue, 23 Sep 2025 11:17:15 +0900 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20WorkflowController=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=A7=80=EC=95=8A=EB=8A=94=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../icebang/domain/workflow/controller/WorkflowController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java index d23b4335..fd42ea13 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java @@ -13,7 +13,6 @@ import site.icebang.domain.workflow.dto.WorkflowCardDto; import site.icebang.domain.workflow.dto.WorkflowDetailCardDto; import site.icebang.domain.workflow.service.WorkflowExecutionService; -import site.icebang.domain.workflow.service.WorkflowHistoryService; import site.icebang.domain.workflow.service.WorkflowService; @RestController @@ -22,7 +21,6 @@ public class WorkflowController { private final WorkflowService workflowService; private final WorkflowExecutionService workflowExecutionService; - private final WorkflowHistoryService workflowHistoryService; @GetMapping("") public ApiResponse> getWorkflowList( From 0f3e12ee0cf45860a947f586f9a821f3cf6cba66 Mon Sep 17 00:00:00 2001 From: kakusiA Date: Tue, 23 Sep 2025 11:32:35 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=EC=8A=A4=ED=82=A4=EB=A7=88=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=80=EC=A4=84=EB=9F=AC=20=EC=9C=A0=EB=8B=88=ED=81=AC?= =?UTF-8?q?=EA=B8=B0=20=EC=BF=BC=EB=A6=AC=20=EA=B5=AC=EB=AC=B8=20H2?= =?UTF-8?q?=EC=99=80=20=ED=98=B8=ED=99=98=EB=90=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/user-service/src/main/resources/sql/01-schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user-service/src/main/resources/sql/01-schema.sql b/apps/user-service/src/main/resources/sql/01-schema.sql index 26f2fb1b..875cd2fe 100644 --- a/apps/user-service/src/main/resources/sql/01-schema.sql +++ b/apps/user-service/src/main/resources/sql/01-schema.sql @@ -337,4 +337,4 @@ CREATE INDEX idx_execution_type_source ON execution_log(execution_type, source_i -- v0.5 -- 기존 schedule 테이블 유니크키 수정 -- 컬럼 추가 (한 번에 하나씩) -ALTER TABLE schedule DROP CONSTRAINT uk_schedule_workflow; +ALTER TABLE schedule DROP CONSTRAINT IF EXISTS uk_schedule_workflow; From 83ccf859399235a3d2f9e138974f8f1083419653 Mon Sep 17 00:00:00 2001 From: kakusiA Date: Tue, 23 Sep 2025 11:51:01 +0900 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20schema.sql=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EB=8D=98=20Alter=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/user-service/src/main/resources/sql/01-schema.sql | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/user-service/src/main/resources/sql/01-schema.sql b/apps/user-service/src/main/resources/sql/01-schema.sql index 875cd2fe..31242c33 100644 --- a/apps/user-service/src/main/resources/sql/01-schema.sql +++ b/apps/user-service/src/main/resources/sql/01-schema.sql @@ -333,8 +333,3 @@ CREATE INDEX idx_log_level_status ON execution_log(log_level, status); CREATE INDEX idx_error_code ON execution_log(error_code); CREATE INDEX idx_duration ON execution_log(duration_ms); CREATE INDEX idx_execution_type_source ON execution_log(execution_type, source_id); - --- v0.5 --- 기존 schedule 테이블 유니크키 수정 --- 컬럼 추가 (한 번에 하나씩) -ALTER TABLE schedule DROP CONSTRAINT IF EXISTS uk_schedule_workflow; From 74a471a8be76cf86f87eb029a00342f68f3c8d0c Mon Sep 17 00:00:00 2001 From: kakusiA Date: Tue, 23 Sep 2025 12:02:46 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20workflow=20insert=20sql=EB=AC=B8=20?= =?UTF-8?q?=ED=8F=AC=EB=A7=B7=20""=20->=20''=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/user-service/src/main/resources/sql/03-insert-workflow.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user-service/src/main/resources/sql/03-insert-workflow.sql b/apps/user-service/src/main/resources/sql/03-insert-workflow.sql index 0003bcef..0660b31f 100644 --- a/apps/user-service/src/main/resources/sql/03-insert-workflow.sql +++ b/apps/user-service/src/main/resources/sql/03-insert-workflow.sql @@ -16,7 +16,7 @@ DELETE FROM `workflow`; -- 워크플로우 생성 (ID: 1) INSERT INTO `workflow` (`id`, `name`, `description`, `created_by`, `default_config`) VALUES (1, '상품 분석 및 블로그 자동 발행', '키워드 검색부터 상품 분석 후 블로그 발행까지의 자동화 프로세스', 1, - JSON_OBJECT('keyword_search',json_object('tag',"naver"),'blog_publish',json_object('tag',"naver_blog",'blog_id', "wtecho331", 'blog_pw', "testpass"))) + JSON_OBJECT('keyword_search',json_object('tag','naver'),'blog_publish',json_object('tag','naver_blog','blog_id', 'wtecho331', 'blog_pw', 'testpass'))) ON DUPLICATE KEY UPDATE name = VALUES(name), description = VALUES(description),