Selaa lähdekoodia

BuildApp 接口中添加构建任务管理方法

reghao 1 vuosi sitten
vanhempi
commit
7f93c81b38

+ 13 - 5
web/src/main/java/cn/reghao/devops/web/mgr/app/controller/BuildDeployController.java

@@ -4,6 +4,7 @@ import cn.reghao.devops.web.mgr.app.service.bd.BuildApp;
 import cn.reghao.devops.web.mgr.app.service.bd.BuildStat;
 import cn.reghao.devops.web.mgr.app.service.bd.DeployApp;
 import cn.reghao.devops.web.mgr.app.service.bd.webhook.WebhookService;
+import cn.reghao.jutil.jdk.result.Result;
 import cn.reghao.jutil.jdk.result.WebResult;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -39,16 +40,16 @@ public class BuildDeployController {
     @ApiImplicitParams(@ApiImplicitParam(name="appId", value="应用 ID", paramType="path", dataType = "String"))
     @PostMapping(value = "/update/{appId}", produces = MediaType.APPLICATION_JSON_VALUE)
     public String buildAndDeploy(@PathVariable("appId") String appId) throws Exception {
-        buildApp.buildAndDeploy(appId, true);
-        return WebResult.successWithMsg("构建部署请求已提交");
+        Result result = buildApp.buildAndDeploy(appId, true);
+        return WebResult.result(result);
     }
 
     @ApiOperation(value = "构建应用")
     @ApiImplicitParams(@ApiImplicitParam(name="appId", value="应用 ID", paramType="path", dataType = "String"))
     @PostMapping(value = "/build/{appId}", produces = MediaType.APPLICATION_JSON_VALUE)
     public String build(@PathVariable("appId") String appId) throws Exception {
-        buildApp.buildAndDeploy(appId, false);
-        return WebResult.successWithMsg("构建请求已提交");
+        Result result = buildApp.buildAndDeploy(appId, false);
+        return WebResult.result(result);
     }
 
     @ApiOperation(value = "部署应用")
@@ -72,7 +73,14 @@ public class BuildDeployController {
     public String resetState() {
         // TODO 暂不启用 web 接口, 只在应用启动时执行
         //buildStat.resetState();
-        return WebResult.successWithMsg("尚未实现");
+        return WebResult.failWithMsg("接口未实现");
+    }
+
+    @ApiOperation(value = "取消构建任务")
+    @PostMapping(value = "/task/cancel/{appId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public String cancelTask(@PathVariable("appId") String appId) {
+        buildApp.cancelTask(appId);
+        return WebResult.success();
     }
 
     @ApiOperation(value = "webhook 自动构建部署")

+ 7 - 2
web/src/main/java/cn/reghao/devops/web/mgr/app/controller/page/BuildDeployPageController.java

@@ -6,6 +6,8 @@ import cn.reghao.devops.web.mgr.app.model.po.log.BuildLog;
 import cn.reghao.devops.web.mgr.app.model.vo.AppBuildingVO;
 import cn.reghao.devops.web.mgr.app.model.vo.AppDeployingVO;
 import cn.reghao.devops.web.mgr.app.model.vo.BuildLogVO;
+import cn.reghao.devops.web.mgr.app.model.vo.BuildTask;
+import cn.reghao.devops.web.mgr.app.service.bd.BuildApp;
 import cn.reghao.devops.web.mgr.app.service.bd.BuildService;
 import cn.reghao.devops.web.mgr.app.service.bd.BuildStat;
 import cn.reghao.devops.web.mgr.app.service.bd.DeployStat;
@@ -38,13 +40,15 @@ public class BuildDeployPageController {
     private final DeployStat deployStat;
     private final BuildDeployLogPage buildDeployLogPage;
     private final BuildService buildService;
+    private BuildApp buildApp;
 
     public BuildDeployPageController(BuildStat buildStat, DeployStat deployStat, BuildDeployLogPage buildDeployLogPage,
-                                     BuildService buildService) {
+                                     BuildService buildService, BuildApp buildApp) {
         this.buildStat = buildStat;
         this.deployStat = deployStat;
         this.buildDeployLogPage = buildDeployLogPage;
         this.buildService = buildService;
+        this.buildApp = buildApp;
     }
 
     @ApiOperation(value = "应用构建页面")
@@ -84,7 +88,8 @@ public class BuildDeployPageController {
     @ApiOperation(value = "构建任务页面")
     @GetMapping(value = "/task")
     public String buildTaskPage(Model model) {
-        model.addAttribute("list", Collections.emptyList());
+        List<BuildTask> list = buildApp.getBuildTasks();
+        model.addAttribute("list", list);
         return "/devops/app/bd/taskindex";
     }
 

+ 19 - 0
web/src/main/java/cn/reghao/devops/web/mgr/app/model/vo/AppTask.java

@@ -0,0 +1,19 @@
+package cn.reghao.devops.web.mgr.app.model.vo;
+
+import cn.reghao.devops.web.mgr.build.chain.HandlerResult;
+import cn.reghao.devops.web.mgr.build.model.AppDto;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author reghao
+ * @date 2024-08-02 09:18:33
+ */
+@AllArgsConstructor
+@Getter
+public class AppTask {
+    private AppDto app;
+    private CompletableFuture<HandlerResult> future;
+}

+ 24 - 0
web/src/main/java/cn/reghao/devops/web/mgr/app/model/vo/BuildTask.java

@@ -0,0 +1,24 @@
+package cn.reghao.devops.web.mgr.app.model.vo;
+
+import cn.reghao.devops.web.mgr.build.model.AppDto;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2024-08-02 09:10:23
+ */
+@Getter
+public class BuildTask {
+    private String appId;
+    private String type;
+    private String env;
+    private String stat;
+
+    public BuildTask(AppDto appDto, String stat) {
+        this.appId = appDto.getAppId();
+        this.type = appDto.getAppType();
+        this.env = appDto.getEnv();
+        this.stat = stat;
+    }
+}

+ 8 - 1
web/src/main/java/cn/reghao/devops/web/mgr/app/service/bd/BuildApp.java

@@ -1,5 +1,10 @@
 package cn.reghao.devops.web.mgr.app.service.bd;
 
+import cn.reghao.devops.web.mgr.app.model.vo.BuildTask;
+import cn.reghao.jutil.jdk.result.Result;
+
+import java.util.List;
+
 /**
  * 构建部署应用
  *
@@ -7,5 +12,7 @@ package cn.reghao.devops.web.mgr.app.service.bd;
  * @date 2023-02-24 21:15:08
  */
 public interface BuildApp {
-    void buildAndDeploy(String appId, boolean deploy) throws Exception;
+    Result buildAndDeploy(String appId, boolean deploy) throws Exception;
+    List<BuildTask> getBuildTasks();
+    void cancelTask(String appId);
 }

+ 38 - 19
web/src/main/java/cn/reghao/devops/web/mgr/app/service/bd/impl/BuildAppImpl.java

@@ -3,6 +3,8 @@ package cn.reghao.devops.web.mgr.app.service.bd.impl;
 import cn.reghao.devops.web.admin.account.model.po.User;
 import cn.reghao.devops.web.mgr.app.model.po.AppBuilding;
 import cn.reghao.devops.web.mgr.app.model.po.config.AppConfig;
+import cn.reghao.devops.web.mgr.app.model.vo.AppTask;
+import cn.reghao.devops.web.mgr.app.model.vo.BuildTask;
 import cn.reghao.devops.web.mgr.app.service.PermissionCheck;
 import cn.reghao.devops.web.mgr.app.service.bd.BuildApp;
 import cn.reghao.devops.web.mgr.app.service.bd.BuildDeployNotify;
@@ -19,11 +21,10 @@ import cn.reghao.jutil.tool.id.IdGenerator;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
 
 /**
  * @author reghao
@@ -34,7 +35,7 @@ import java.util.concurrent.ExecutorService;
 public class BuildAppImpl implements BuildApp {
     private final IdGenerator idGenerator = new IdGenerator(10, "build-log-id");
     private final ExecutorService threadPool = ThreadPoolWrapper.threadPool("build-pool", 10);
-    private final Map<String, CompletableFuture<HandlerResult>> buildMap = new HashMap<>(10);
+    private final Map<String, AppTask> taskMap = new HashMap<>(10);
     private final BuildStat buildStat;
     private final DeployApp deployApp;
     private final BuildDeployNotify buildDeployNotify;
@@ -48,15 +49,15 @@ public class BuildAppImpl implements BuildApp {
     }
 
     @Override
-    public void buildAndDeploy(String appId, boolean deploy) throws Exception {
+    public Result buildAndDeploy(String appId, boolean deploy) throws Exception {
         if (buildStat.isBuilding(appId)) {
-            log.info("{} 正在构建中", appId);
-            return;
+            String msg = String.format("%s 正在构建中", appId);
+            return Result.result(ResultStatus.FAIL, msg);
         }
 
-        if (buildMap.size() >= 10) {
-            log.info("已有 {} 个 app 正在构建中", buildMap.size());
-            return;
+        if (taskMap.size() >= 10) {
+            String msg = String.format("已有 %s 个 app 正在构建中", taskMap.size());
+            return Result.result(ResultStatus.FAIL, msg);
         }
 
         AppConfig appConfig = buildStat.getAppConfig(appId);
@@ -68,6 +69,7 @@ public class BuildAppImpl implements BuildApp {
         String buildBy = user.getScreenName();
         AppDto appDto = appConfig.getAppDto();
         localBuild(appDto, buildBy, deploy);
+        return Result.success("构建部署任务已提交");
     }
 
     private void localBuild(AppDto appDto, String buildBy, boolean deploy) throws Exception {
@@ -86,7 +88,7 @@ public class BuildAppImpl implements BuildApp {
                     Result result = buildChainResult.getResult();
                     AppBuilding appBuilding = buildStat.afterBuild(buildChainResult);
                     log.info("{} 异步构建完成", appId);
-                    buildMap.remove(appId);
+                    taskMap.remove(appId);
                     if (appBuilding == null) {
                         return;
                     }
@@ -97,20 +99,37 @@ public class BuildAppImpl implements BuildApp {
                         buildDeployNotify.buildNotify(appBuilding);
                     }
                 });
-        buildMap.put(appId, future);
+        taskMap.put(appId, new AppTask(appDto, future));
     }
 
-    public void getBuildStat() {
-        buildMap.forEach((appId, future) -> {
-            if (future.isDone()) {
+    @Override
+    public List<BuildTask> getBuildTasks() {
+        ThreadPoolExecutor tpe = (ThreadPoolExecutor) threadPool;
+        int active = tpe.getActiveCount();
+        long total = tpe.getTaskCount();
+        log.info("total -> {}, active -> {}", total, active);
+
+        List<BuildTask> list = new ArrayList<>();
+        taskMap.forEach((appId, appTask) -> {
+            AppDto appDto = appTask.getApp();
+            if (appTask.getFuture().isDone()) {
+                list.add(new BuildTask(appDto, "已完成"));
+            } else {
+                list.add(new BuildTask(appDto, "进行中"));
             }
         });
+
+        return list;
     }
 
-    public synchronized void cancel(String appId) {
-        CompletableFuture<HandlerResult> future = buildMap.get(appId);
-        if (future != null && !future.isDone()) {
-            future.cancel(true);
+    @Override
+    public synchronized void cancelTask(String appId) {
+        AppTask appTask = taskMap.get(appId);
+        if (appTask != null) {
+            CompletableFuture<HandlerResult> future = appTask.getFuture();
+            if (!future.isDone()) {
+                future.cancel(true);
+            }
         }
     }
 

+ 9 - 8
web/src/main/resources/templates/devops/app/bd/taskindex.html

@@ -9,20 +9,21 @@
             <table class="layui-table timo-table">
                 <thead>
                 <tr>
-                    <th class="sortable" data-field="appName">应用</th>
-                    <th class="sortable" data-field="appType">类型</th>
+                    <th class="sortable" data-field="appId">应用</th>
+                    <th class="sortable" data-field="type">类型</th>
+                    <th class="sortable" data-field="env">环境</th>
+                    <th class="sortable" data-field="stat">状态</th>
                     <th>操作</th>
                 </tr>
                 </thead>
                 <tbody>
                 <tr th:each="item:${list}">
+                    <td th:text="${item.appId}">类型</td>
+                    <td th:text="${item.type}">类型</td>
+                    <td th:text="${item.env}">类型</td>
+                    <td th:text="${item.stat}">类型</td>
                     <td>
-                        <a class="open-popup" data-title="应用配置详情" data-size="1200,500" href="#"
-                           th:text="${item.appName}" th:attr="data-url=@{'/app/config/app/detail/'+${item.appId}}"></a>
-                    </td>
-                    <td th:text="${item.appType}">类型</td>
-                    <td>
-                        <a class="ajax-post" th:href="@{'/api/app/bd/task/cancel'+${item.appId}}">取消</a>
+                        <a class="ajax-post" th:href="@{'/api/app/bd/task/cancel/'+${item.appId}}">取消</a>
                     </td>
                 </tr>
                 </tbody>