From f2acaf086c655375e55671cdb7e7637920fbf8f6 Mon Sep 17 00:00:00 2001 From: gaosaroma Date: Wed, 18 Dec 2024 17:58:20 +0800 Subject: [PATCH 1/6] feat: add batch install handler in arklet --- .../core/command/builtin/BuiltinCommand.java | 2 + .../handler/BatchInstallBizHandler.java | 104 ++++++++++++++++++ .../builtin/handler/InstallBizHandler.java | 30 ++--- .../common/model/BatchInstallRequest.java | 5 + .../core/ops/UnifiedOperationServiceImpl.java | 48 ++++---- ...chInstallBizInDirAbsolutePathStrategy.java | 55 +++++++++ .../BatchInstallBizInRequestStrategy.java | 53 +++++++++ .../ops/strategy/BatchInstallStrategy.java | 19 ++++ .../arklet/core/util/ResourceUtils.java | 24 ++++ .../tunnel/mqtt/paho/MqttMessageHandler.java | 33 +++--- 10 files changed, 320 insertions(+), 53 deletions(-) create mode 100644 arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java create mode 100644 arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java create mode 100644 arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java create mode 100644 arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java create mode 100644 arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java index b6c64ac27..671faf29e 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java @@ -31,6 +31,8 @@ public enum BuiltinCommand implements Command { INSTALL_BIZ("installBiz", "install one ark biz"), + BATCH_INSTALL_BIZ("batchInstallBiz", "install one ark biz"), + UNINSTALL_BIZ("uninstallBiz", "uninstall one ark biz"), diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java new file mode 100644 index 000000000..8063bbd0f --- /dev/null +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java @@ -0,0 +1,104 @@ +/** + * Alipay.com Inc. + * Copyright (c) 2004-2024 All Rights Reserved. + */ +package com.alipay.sofa.koupleless.arklet.core.command.builtin.handler; + +import com.alipay.sofa.ark.api.ResponseCode; +import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.BatchInstallBizHandler.BatchInstallInput; +import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.BatchInstallBizHandler.BatchInstallResponse; +import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.InstallBizHandler.Input; +import com.alipay.sofa.koupleless.arklet.core.command.meta.AbstractCommandHandler; +import com.alipay.sofa.koupleless.arklet.core.command.meta.Command; +import com.alipay.sofa.koupleless.arklet.core.command.meta.InputMeta; +import com.alipay.sofa.koupleless.arklet.core.command.meta.Output; +import com.alipay.sofa.koupleless.arklet.core.command.meta.bizops.ArkBizOps; +import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletRuntimeException; +import com.alipay.sofa.koupleless.arklet.core.common.exception.CommandValidationException; +import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallRequest; +import com.alipay.sofa.koupleless.arklet.core.common.model.InstallRequest; +import com.alipay.sofa.koupleless.arklet.core.util.ResourceUtils; +import lombok.Getter; +import lombok.Setter; + +import java.lang.management.MemoryPoolMXBean; +import java.util.ArrayList; + +import static com.alipay.sofa.koupleless.arklet.core.command.builtin.BuiltinCommand.BATCH_INSTALL_BIZ; + +/** + * @author lianglipeng.llp@alibaba-inc.com + * @version $Id: BatchInstallBizHandler.java, v 0.1 2024年12月18日 15:04 立蓬 Exp $ + */ +public class BatchInstallBizHandler extends AbstractCommandHandler implements ArkBizOps { + + @Override + public void validate(BatchInstallInput batchInstallInput) throws CommandValidationException { + notNull(batchInstallInput.getBizList(), "bizList is null"); + + for(Input bizInput: batchInstallInput.bizList){ + bizInput.setAsync(false); + InstallBizHandler.validateInput(bizInput); + } + } + + @Override + public Output handle(BatchInstallInput batchInstallInput) { + MemoryPoolMXBean metaSpaceMXBean = ResourceUtils.getMetaSpaceMXBean(); + long startSpace = metaSpaceMXBean.getUsage().getUsed(); + try { + BatchInstallResponse response = convertClientResponse( + getOperationService().batchInstall(convertBatchInstallRequest(batchInstallInput))); + response + .setElapsedSpace(metaSpaceMXBean.getUsage().getUsed() - startSpace); + if (ResponseCode.SUCCESS.equals(response.getCode())) { + return Output.ofSuccess(response); + } else { + return Output.ofFailed(response, "install biz not success!"); + } + } catch (Throwable e) { + throw new ArkletRuntimeException(e); + } + } + + @Override + public Command command() { + return BATCH_INSTALL_BIZ; + } + + private BatchInstallRequest convertBatchInstallRequest(BatchInstallInput input) { + ArrayList installRequestList = new ArrayList<>(); + + for(Input bizInput: input.getBizList()){ + installRequestList.add(InstallRequest.builder() + .bizName(bizInput.getBizName()) + .bizVersion(bizInput.getBizVersion()) + .bizUrl(bizInput.getBizUrl()) + .args(bizInput.getArgs()) + .envs(bizInput.getEnvs()) + .installStrategy(bizInput.getInstallStrategy()) + .build()); + } + return BatchInstallRequest.builder().installRequests(installRequestList.toArray(new InstallRequest[0])).build(); + } + + private BatchInstallResponse convertClientResponse(com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse res) { + BatchInstallResponse response = new BatchInstallResponse(); + response.setBizUrlToResponse(res.getBizUrlToResponse()); + response.setCode(res.getCode()); + response.setMessage(res.getMessage()); + return response; + } + + @Getter + @Setter + public static class BatchInstallInput extends InputMeta { + private Input[] bizList; + } + + @Getter + @Setter + public static class BatchInstallResponse extends com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse { + private long elapsedSpace; + } +} \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java index 72140d5e7..888bf8622 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java @@ -31,6 +31,7 @@ import com.alipay.sofa.koupleless.arklet.core.command.meta.bizops.ArkBizOps; import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletRuntimeException; import com.alipay.sofa.koupleless.arklet.core.common.exception.CommandValidationException; +import com.alipay.sofa.koupleless.arklet.core.util.ResourceUtils; import com.alipay.sofa.koupleless.common.log.ArkletLogger; import com.alipay.sofa.koupleless.common.log.ArkletLoggerFactory; import com.alipay.sofa.koupleless.arklet.core.common.model.InstallRequest; @@ -39,10 +40,8 @@ import java.io.File; import java.io.IOException; -import java.lang.management.ManagementFactory; import java.lang.management.MemoryPoolMXBean; import java.net.URL; -import java.util.List; import java.util.Map; import static com.alipay.sofa.koupleless.arklet.core.common.model.Constants.STRATEGY_INSTALL_ONLY_STRATEGY; @@ -62,7 +61,7 @@ public class InstallBizHandler extends /** {@inheritDoc} */ @Override public Output handle(Input input) { - MemoryPoolMXBean metaSpaceMXBean = getMetaSpaceMXBean(); + MemoryPoolMXBean metaSpaceMXBean = ResourceUtils.getMetaSpaceMXBean(); long startSpace = metaSpaceMXBean.getUsage().getUsed(); try { InstallBizClientResponse installBizClientResponse = convertClientResponse( @@ -85,15 +84,6 @@ private InstallRequest convertInstallRequest(Input input) { .envs(input.getEnvs()).installStrategy(input.getInstallStrategy()).build(); } - private MemoryPoolMXBean getMetaSpaceMXBean() { - MemoryPoolMXBean metaSpaceMXBean = null; - List memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); - for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeans) - if (memoryPoolMXBean.getName().equals("Metaspace")) - metaSpaceMXBean = memoryPoolMXBean; - return metaSpaceMXBean; - } - private InstallBizClientResponse convertClientResponse(ClientResponse res) { InstallBizClientResponse installBizClientResponse = new InstallBizClientResponse(); installBizClientResponse.setBizInfos(res.getBizInfos()); @@ -111,13 +101,17 @@ public Command command() { /** {@inheritDoc} */ @Override public void validate(Input input) throws CommandValidationException { + InstallBizHandler.validateInput(input); + } + + public static void validateInput(Input input) throws CommandValidationException { isTrue(!input.isAsync() || !StringUtils.isEmpty(input.getRequestId()), - "requestId should not be blank when async is true"); + "requestId should not be blank when async is true"); notBlank(input.getBizUrl(), "bizUrl should not be blank"); if (StringUtils.isEmpty(input.getBizName()) || StringUtils.isEmpty(input.getBizVersion())) { LOGGER.warn( - "biz name and version should not be empty, or it will reduce the performance."); + "biz name and version should not be empty, or it will reduce the performance."); } if (StringUtils.isEmpty(input.getBizName()) && StringUtils.isEmpty(input.getBizVersion())) { @@ -126,20 +120,20 @@ public void validate(Input input) throws CommandValidationException { refreshBizInfoFromJar(input); } catch (IOException e) { throw new CommandValidationException( - String.format("refresh biz info from jar failed: %s", e.getMessage())); + String.format("refresh biz info from jar failed: %s", e.getMessage())); } } else if (!StringUtils.isEmpty(input.getBizName()) - && !StringUtils.isEmpty(input.getBizVersion())) { + && !StringUtils.isEmpty(input.getBizVersion())) { // if bizName and bizVersion is not blank, it means that we should install the biz with the given bizName and bizVersion. // do nothing. } else { // if bizName or bizVersion is blank, it is invalid, throw exception. throw new CommandValidationException( - "bizName and bizVersion should be both blank or both not blank."); + "bizName and bizVersion should be both blank or both not blank."); } } - private void refreshBizInfoFromJar(Input input) throws IOException { + private static void refreshBizInfoFromJar(Input input) throws IOException { // 如果入参里没有jar,例如模块卸载,这里就直接返回 if (StringUtils.isEmpty(input.getBizUrl())) { return; diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java index bf15645d5..cd40f2552 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java @@ -43,4 +43,9 @@ public class BatchInstallRequest { */ @Builder.Default private String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; + + /** + * 模块批量发布请求。 + */ + private InstallRequest[] installRequests = new InstallRequest[0]; } diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java index be0addf20..22fcd7da1 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java @@ -21,7 +21,11 @@ import com.alipay.sofa.ark.api.ResponseCode; import com.alipay.sofa.ark.spi.constant.Constants; import com.alipay.sofa.ark.spi.model.Biz; +import com.alipay.sofa.common.utils.StringUtil; import com.alipay.sofa.koupleless.arklet.core.command.executor.ExecutorServiceManager; +import com.alipay.sofa.koupleless.arklet.core.ops.strategy.BatchInstallBizInDirAbsolutePathStrategy; +import com.alipay.sofa.koupleless.arklet.core.ops.strategy.BatchInstallBizInRequestStrategy; +import com.alipay.sofa.koupleless.arklet.core.ops.strategy.BatchInstallStrategy; import com.alipay.sofa.koupleless.common.log.ArkletLoggerFactory; import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallRequest; import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse; @@ -35,6 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ThreadPoolExecutor; @@ -47,8 +52,9 @@ */ @Singleton public class UnifiedOperationServiceImpl implements UnifiedOperationService { + private final BatchInstallStrategy batchInstallBizInDirAbsolutePathStrategy = new BatchInstallBizInDirAbsolutePathStrategy(); - private BatchInstallHelper batchInstallHelper = new BatchInstallHelper(); + private final BatchInstallStrategy batchInstallBizInRequestStrategy = new BatchInstallBizInRequestStrategy(); /** {@inheritDoc} */ @Override @@ -72,20 +78,12 @@ public ClientResponse install(InstallRequest request) throws Throwable { /** *

safeBatchInstall.

* - * @param bizAbsolutePath a {@link java.lang.String} object + * @param bizRequest a {@link InstallRequest} object * @return a {@link com.alipay.sofa.ark.api.ClientResponse} object */ - public ClientResponse safeBatchInstall(String bizAbsolutePath, String installStrategy) { + public ClientResponse safeBatchInstall(InstallRequest bizRequest) { try { - String bizUrl = OSUtils.getLocalFileProtocolPrefix() + bizAbsolutePath; - Map mainAttributes = batchInstallHelper - .getMainAttributes(bizAbsolutePath); - String bizName = (String) mainAttributes.get(Constants.ARK_BIZ_NAME); - String bizVersion = (String) mainAttributes.get(Constants.ARK_BIZ_VERSION); - - InstallRequest installRequest = InstallRequest.builder().bizUrl(bizUrl).bizName(bizName) - .bizVersion(bizVersion).installStrategy(installStrategy).build(); - return install(installRequest); + return install(bizRequest); } catch (Throwable throwable) { throwable.printStackTrace(); return new ClientResponse().setCode(ResponseCode.FAILED) @@ -103,18 +101,19 @@ public ClientResponse uninstall(String bizName, String bizVersion) throws Throwa @Override public BatchInstallResponse batchInstall(BatchInstallRequest request) throws Throwable { long startTimestamp = System.currentTimeMillis(); - Map> bizUrls = batchInstallHelper - .getBizUrlsFromLocalFileSystem(request.getBizDirAbsolutePath()); - ThreadPoolExecutor executorService = ExecutorServiceManager.getArkBizOpsExecutor(); + BatchInstallStrategy batchInstallStrategy = getBatchInstallStrategy(request); + Map> installRequestsWithOrder = batchInstallStrategy.convertToInstallInput(request); + + ThreadPoolExecutor executorService = ExecutorServiceManager.getArkBizOpsExecutor(); Map bizUrlToInstallResult = new HashMap<>(); boolean hasFailed = false; - for (Map.Entry> entry : bizUrls.entrySet()) { - List bizUrlsInSameOrder = entry.getValue(); + for (Entry> entry : installRequestsWithOrder.entrySet()) { + List bizRequestInSameOrder = entry.getValue(); List> futures = new ArrayList<>(); - for (String bizUrl : bizUrlsInSameOrder) { + for (InstallRequest bizRequest : bizRequestInSameOrder) { futures.add(CompletableFuture.supplyAsync( - () -> safeBatchInstall(bizUrl, request.getInstallStrategy()), executorService)); + () -> safeBatchInstall(bizRequest), executorService)); } // wait for all install futures done @@ -122,8 +121,8 @@ public BatchInstallResponse batchInstall(BatchInstallRequest request) throws Thr int counter = 0; for (CompletableFuture future : futures) { ClientResponse clientResponse = future.get(); - String bizUrl = bizUrlsInSameOrder.get(counter); - bizUrlToInstallResult.put(bizUrl, clientResponse); + InstallRequest bizRequest = bizRequestInSameOrder.get(counter); + bizUrlToInstallResult.put(bizRequest.getBizUrl(), clientResponse); hasFailed = hasFailed || clientResponse.getCode() != ResponseCode.SUCCESS; counter++; } @@ -139,6 +138,13 @@ public BatchInstallResponse batchInstall(BatchInstallRequest request) throws Thr .bizUrlToResponse(bizUrlToInstallResult).build(); } + private BatchInstallStrategy getBatchInstallStrategy(BatchInstallRequest request) { + if(StringUtil.isNotEmpty(request.getBizDirAbsolutePath())){ + return batchInstallBizInRequestStrategy; + } + return batchInstallBizInRequestStrategy; + } + /** {@inheritDoc} */ @Override public List queryBizList() { diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java new file mode 100644 index 000000000..1dce2a944 --- /dev/null +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java @@ -0,0 +1,55 @@ +/** + * Alipay.com Inc. + * Copyright (c) 2004-2024 All Rights Reserved. + */ +package com.alipay.sofa.koupleless.arklet.core.ops.strategy; + +import com.alipay.sofa.ark.spi.constant.Constants; +import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallRequest; +import com.alipay.sofa.koupleless.arklet.core.common.model.InstallRequest; +import com.alipay.sofa.koupleless.arklet.core.ops.BatchInstallHelper; +import com.alipay.sofa.koupleless.common.util.OSUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import static com.alipay.sofa.koupleless.arklet.core.common.model.Constants.STRATEGY_INSTALL_ONLY_STRATEGY; + +/** + * @author lianglipeng.llp@alibaba-inc.com + * @version $Id: BatchInstallBizInDirStrategy.java, v 0.1 2024年12月18日 16:00 立蓬 Exp $ + */ +public class BatchInstallBizInDirAbsolutePathStrategy implements BatchInstallStrategy { + private final BatchInstallHelper batchInstallHelper = new BatchInstallHelper(); + + private static final String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; + + @Override + public Map> convertToInstallInput(BatchInstallRequest request) throws Throwable { + Map> result = new TreeMap<>(); + + Map> bizUrls = batchInstallHelper + .getBizUrlsFromLocalFileSystem(request.getBizDirAbsolutePath()); + for (Map.Entry> entry : bizUrls.entrySet()){ + Integer order = entry.getKey(); + for (String bizUrl : entry.getValue()) { + result.putIfAbsent(order, new ArrayList<>()); + result.get(order).add(buildInstallRequest(bizUrl)); + } + } + return result; + } + + private InstallRequest buildInstallRequest(String bizAbsolutePath){ + String bizUrl = OSUtils.getLocalFileProtocolPrefix() + bizAbsolutePath; + Map mainAttributes = batchInstallHelper + .getMainAttributes(bizAbsolutePath); + String bizName = (String) mainAttributes.get(Constants.ARK_BIZ_NAME); + String bizVersion = (String) mainAttributes.get(Constants.ARK_BIZ_VERSION); + + return InstallRequest.builder().bizUrl(bizUrl).bizName(bizName) + .bizVersion(bizVersion).installStrategy(installStrategy).build(); + } +} \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java new file mode 100644 index 000000000..cc5377d3b --- /dev/null +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java @@ -0,0 +1,53 @@ +/** + * Alipay.com Inc. + * Copyright (c) 2004-2024 All Rights Reserved. + */ +package com.alipay.sofa.koupleless.arklet.core.ops.strategy; + +import com.alipay.sofa.ark.api.ArkClient; +import com.alipay.sofa.ark.common.util.FileUtils; +import com.alipay.sofa.ark.spi.service.PriorityOrdered; +import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallRequest; +import com.alipay.sofa.koupleless.arklet.core.common.model.InstallRequest; +import com.alipay.sofa.koupleless.arklet.core.ops.BatchInstallHelper; +import lombok.SneakyThrows; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * @author lianglipeng.llp@alibaba-inc.com + * @version $Id: BatchInstallBizInRequestStrategy.java, v 0.1 2024年12月18日 16:54 立蓬 Exp $ + */ +public class BatchInstallBizInRequestStrategy implements BatchInstallStrategy { + + private final BatchInstallHelper batchInstallHelper = new BatchInstallHelper(); + @Override + public Map> convertToInstallInput(BatchInstallRequest request) throws Throwable { + Map> result = new TreeMap<>(); + for (InstallRequest installRequest : request.getInstallRequests()){ + Integer order = parsePriority(installRequest); + result.putIfAbsent(order, new ArrayList<>()); + result.get(order).add(installRequest); + } + return result; + } + + @SneakyThrows + private Integer parsePriority(InstallRequest installRequest){ + URL url = new URL(installRequest.getBizUrl()); + File bizFile = ArkClient.createBizSaveFile(installRequest.getBizName(), installRequest.getBizVersion()); + FileUtils.copyInputStreamToFile(url.openStream(), bizFile); + + Map mainAttributes = batchInstallHelper + .getMainAttributes(bizFile.getAbsolutePath()); + org.apache.commons.io.FileUtils.deleteQuietly(bizFile); + return Integer.valueOf( + mainAttributes.getOrDefault("priority", PriorityOrdered.DEFAULT_PRECEDENCE) + .toString()); + } +} \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java new file mode 100644 index 000000000..eaa666aa4 --- /dev/null +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java @@ -0,0 +1,19 @@ +/** + * Alipay.com Inc. + * Copyright (c) 2004-2024 All Rights Reserved. + */ +package com.alipay.sofa.koupleless.arklet.core.ops.strategy; + +import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallRequest; +import com.alipay.sofa.koupleless.arklet.core.common.model.InstallRequest; + +import java.util.List; +import java.util.Map; + +/** + * @author lianglipeng.llp@alibaba-inc.com + * @version $Id: BatchInstallStrategy.java, v 0.1 2024年12月18日 16:00 立蓬 Exp $ + */ +public interface BatchInstallStrategy { + Map> convertToInstallInput(BatchInstallRequest request) throws Throwable; +} \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java new file mode 100644 index 000000000..b11b367b1 --- /dev/null +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java @@ -0,0 +1,24 @@ +/** + * Alipay.com Inc. + * Copyright (c) 2004-2024 All Rights Reserved. + */ +package com.alipay.sofa.koupleless.arklet.core.util; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; +import java.util.List; + +/** + * @author lianglipeng.llp@alibaba-inc.com + * @version $Id: ResourceUtils.java, v 0.1 2024年12月18日 15:32 立蓬 Exp $ + */ +public class ResourceUtils { + public static MemoryPoolMXBean getMetaSpaceMXBean() { + MemoryPoolMXBean metaSpaceMXBean = null; + List memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); + for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeans) + if (memoryPoolMXBean.getName().equals("Metaspace")) + metaSpaceMXBean = memoryPoolMXBean; + return metaSpaceMXBean; + } +} \ No newline at end of file diff --git a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java index b2bf52d77..5debfa700 100644 --- a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java +++ b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java @@ -26,6 +26,7 @@ import com.alipay.sofa.koupleless.arklet.core.command.meta.Output; import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletInitException; import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletRuntimeException; +import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse; import com.alipay.sofa.koupleless.common.log.ArkletLoggerFactory; import com.alipay.sofa.koupleless.arklet.core.common.model.BaseMetadata; import com.alipay.sofa.koupleless.arklet.core.hook.base.BaseMetadataHook; @@ -234,24 +235,28 @@ private void handleBizOperation(String cmd, MqttMessage msg) throws ArkletRuntim private void handlePlaybackBaseline(String cmd, MqttMessage msg) throws ArkletRuntimeException { List> cmdContents = JSONObject.parseObject(msg.toString(), List.class); + Map cmdContent = new HashMap<>(); + cmdContent.put("bizList", cmdContents); ArkletLoggerFactory.getDefaultLogger() - .info("start to playback baseline with content: " + cmdContents); - // TODO: parallel process - List> failedContents = new ArrayList<>(); - for (Map cmdContent : cmdContents) { - try { - commandService.process(BuiltinCommand.INSTALL_BIZ.getId(), cmdContent); - } catch (Throwable e) { - failedContents.add(cmdContent); - } - } - if (!failedContents.isEmpty()) { + .info("start to playback baseline with content: " + cmdContent); + + Output output = null; + try { + output = commandService.process(BuiltinCommand.BATCH_INSTALL_BIZ.getId(), cmdContent); + } catch (Throwable e) { ArkletLoggerFactory.getDefaultLogger().error( - String.format("fail to handle command %s with content: %s", cmd, failedContents)); - } else { + String.format("fail to handle command %s with content: %s", cmd, e.getMessage())); + return; + } + + if (!output.failed()) { ArkletLoggerFactory.getDefaultLogger() - .info("install biz success when playback baseline"); + .info("install biz success when playback baseline"); + } else { + Map bizUrlToResponse = null == output.getData()?null:output.getData().getBizUrlToResponse(); + ArkletLoggerFactory.getDefaultLogger().error( + String.format("fail to handle command %s with content: %s", cmd, bizUrlToResponse)); } } From 0fbbdb43de399d9e7a28a84ed7e814f7b99b8937 Mon Sep 17 00:00:00 2001 From: gaosaroma Date: Wed, 18 Dec 2024 17:59:03 +0800 Subject: [PATCH 2/6] update version to 1.4.1-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 123cacec4..8ee4f4cf4 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ pom - 1.4.0 + 1.4.1-SNAPSHOT 2.2.16 ${revision} 2.7.15 From f5390a83f9c90f35dd3a97f5b2aaaf7b14c991bf Mon Sep 17 00:00:00 2001 From: gaosaroma Date: Wed, 18 Dec 2024 20:05:28 +0800 Subject: [PATCH 3/6] feat: add batch install biz handler for arklet --- .../core/command/builtin/BuiltinCommand.java | 3 +- .../handler/BatchInstallBizHandler.java | 49 ++++++++++++------- .../builtin/handler/InstallBizHandler.java | 10 ++-- .../common/model/BatchInstallRequest.java | 4 +- .../core/ops/UnifiedOperationServiceImpl.java | 13 ++--- ...chInstallBizInDirAbsolutePathStrategy.java | 37 +++++++++----- .../BatchInstallBizInRequestStrategy.java | 33 +++++++++---- .../ops/strategy/BatchInstallStrategy.java | 20 ++++++-- .../arklet/core/util/ResourceUtils.java | 18 +++++-- .../tunnel/mqtt/paho/MqttMessageHandler.java | 11 ++--- 10 files changed, 129 insertions(+), 69 deletions(-) diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java index 671faf29e..e3a198fb1 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java @@ -31,7 +31,8 @@ public enum BuiltinCommand implements Command { INSTALL_BIZ("installBiz", "install one ark biz"), - BATCH_INSTALL_BIZ("batchInstallBiz", "install one ark biz"), + BATCH_INSTALL_BIZ("batchInstallBiz", + "install one ark biz"), UNINSTALL_BIZ("uninstallBiz", "uninstall one ark biz"), diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java index 8063bbd0f..b7195e3bd 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java @@ -1,6 +1,18 @@ -/** - * Alipay.com Inc. - * Copyright (c) 2004-2024 All Rights Reserved. +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alipay.sofa.koupleless.arklet.core.command.builtin.handler; @@ -30,13 +42,15 @@ * @author lianglipeng.llp@alibaba-inc.com * @version $Id: BatchInstallBizHandler.java, v 0.1 2024年12月18日 15:04 立蓬 Exp $ */ -public class BatchInstallBizHandler extends AbstractCommandHandler implements ArkBizOps { +public class BatchInstallBizHandler extends + AbstractCommandHandler + implements ArkBizOps { @Override public void validate(BatchInstallInput batchInstallInput) throws CommandValidationException { notNull(batchInstallInput.getBizList(), "bizList is null"); - for(Input bizInput: batchInstallInput.bizList){ + for (Input bizInput : batchInstallInput.bizList) { bizInput.setAsync(false); InstallBizHandler.validateInput(bizInput); } @@ -48,9 +62,8 @@ public Output handle(BatchInstallInput batchInstallInput) long startSpace = metaSpaceMXBean.getUsage().getUsed(); try { BatchInstallResponse response = convertClientResponse( - getOperationService().batchInstall(convertBatchInstallRequest(batchInstallInput))); - response - .setElapsedSpace(metaSpaceMXBean.getUsage().getUsed() - startSpace); + getOperationService().batchInstall(convertBatchInstallRequest(batchInstallInput))); + response.setElapsedSpace(metaSpaceMXBean.getUsage().getUsed() - startSpace); if (ResponseCode.SUCCESS.equals(response.getCode())) { return Output.ofSuccess(response); } else { @@ -69,17 +82,14 @@ public Command command() { private BatchInstallRequest convertBatchInstallRequest(BatchInstallInput input) { ArrayList installRequestList = new ArrayList<>(); - for(Input bizInput: input.getBizList()){ - installRequestList.add(InstallRequest.builder() - .bizName(bizInput.getBizName()) - .bizVersion(bizInput.getBizVersion()) - .bizUrl(bizInput.getBizUrl()) - .args(bizInput.getArgs()) - .envs(bizInput.getEnvs()) - .installStrategy(bizInput.getInstallStrategy()) - .build()); + for (Input bizInput : input.getBizList()) { + installRequestList.add(InstallRequest.builder().bizName(bizInput.getBizName()) + .bizVersion(bizInput.getBizVersion()).bizUrl(bizInput.getBizUrl()) + .args(bizInput.getArgs()).envs(bizInput.getEnvs()) + .installStrategy(bizInput.getInstallStrategy()).build()); } - return BatchInstallRequest.builder().installRequests(installRequestList.toArray(new InstallRequest[0])).build(); + return BatchInstallRequest.builder() + .installRequests(installRequestList.toArray(new InstallRequest[0])).build(); } private BatchInstallResponse convertClientResponse(com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse res) { @@ -98,7 +108,8 @@ public static class BatchInstallInput extends InputMeta { @Getter @Setter - public static class BatchInstallResponse extends com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse { + public static class BatchInstallResponse extends + com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse { private long elapsedSpace; } } \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java index 888bf8622..0419e3917 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/InstallBizHandler.java @@ -106,12 +106,12 @@ public void validate(Input input) throws CommandValidationException { public static void validateInput(Input input) throws CommandValidationException { isTrue(!input.isAsync() || !StringUtils.isEmpty(input.getRequestId()), - "requestId should not be blank when async is true"); + "requestId should not be blank when async is true"); notBlank(input.getBizUrl(), "bizUrl should not be blank"); if (StringUtils.isEmpty(input.getBizName()) || StringUtils.isEmpty(input.getBizVersion())) { LOGGER.warn( - "biz name and version should not be empty, or it will reduce the performance."); + "biz name and version should not be empty, or it will reduce the performance."); } if (StringUtils.isEmpty(input.getBizName()) && StringUtils.isEmpty(input.getBizVersion())) { @@ -120,16 +120,16 @@ public static void validateInput(Input input) throws CommandValidationException refreshBizInfoFromJar(input); } catch (IOException e) { throw new CommandValidationException( - String.format("refresh biz info from jar failed: %s", e.getMessage())); + String.format("refresh biz info from jar failed: %s", e.getMessage())); } } else if (!StringUtils.isEmpty(input.getBizName()) - && !StringUtils.isEmpty(input.getBizVersion())) { + && !StringUtils.isEmpty(input.getBizVersion())) { // if bizName and bizVersion is not blank, it means that we should install the biz with the given bizName and bizVersion. // do nothing. } else { // if bizName or bizVersion is blank, it is invalid, throw exception. throw new CommandValidationException( - "bizName and bizVersion should be both blank or both not blank."); + "bizName and bizVersion should be both blank or both not blank."); } } diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java index cd40f2552..356226d71 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/common/model/BatchInstallRequest.java @@ -37,12 +37,12 @@ public class BatchInstallRequest { /** * 本地文件系统目录。 */ - private String bizDirAbsolutePath; + private String bizDirAbsolutePath; /** * 静态合并部署,默认没有老版本模块,可以直接使用普通安装策略。 */ @Builder.Default - private String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; + private String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; /** * 模块批量发布请求。 diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java index 22fcd7da1..50ae87d42 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java @@ -54,7 +54,7 @@ public class UnifiedOperationServiceImpl implements UnifiedOperationService { private final BatchInstallStrategy batchInstallBizInDirAbsolutePathStrategy = new BatchInstallBizInDirAbsolutePathStrategy(); - private final BatchInstallStrategy batchInstallBizInRequestStrategy = new BatchInstallBizInRequestStrategy(); + private final BatchInstallStrategy batchInstallBizInRequestStrategy = new BatchInstallBizInRequestStrategy(); /** {@inheritDoc} */ @Override @@ -103,17 +103,18 @@ public BatchInstallResponse batchInstall(BatchInstallRequest request) throws Thr long startTimestamp = System.currentTimeMillis(); BatchInstallStrategy batchInstallStrategy = getBatchInstallStrategy(request); - Map> installRequestsWithOrder = batchInstallStrategy.convertToInstallInput(request); + Map> installRequestsWithOrder = batchInstallStrategy + .convertToInstallInput(request); ThreadPoolExecutor executorService = ExecutorServiceManager.getArkBizOpsExecutor(); Map bizUrlToInstallResult = new HashMap<>(); boolean hasFailed = false; - for (Entry> entry : installRequestsWithOrder.entrySet()) { + for (Entry> entry : installRequestsWithOrder.entrySet()) { List bizRequestInSameOrder = entry.getValue(); List> futures = new ArrayList<>(); for (InstallRequest bizRequest : bizRequestInSameOrder) { - futures.add(CompletableFuture.supplyAsync( - () -> safeBatchInstall(bizRequest), executorService)); + futures.add(CompletableFuture.supplyAsync(() -> safeBatchInstall(bizRequest), + executorService)); } // wait for all install futures done @@ -139,7 +140,7 @@ public BatchInstallResponse batchInstall(BatchInstallRequest request) throws Thr } private BatchInstallStrategy getBatchInstallStrategy(BatchInstallRequest request) { - if(StringUtil.isNotEmpty(request.getBizDirAbsolutePath())){ + if (StringUtil.isNotEmpty(request.getBizDirAbsolutePath())) { return batchInstallBizInRequestStrategy; } return batchInstallBizInRequestStrategy; diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java index 1dce2a944..dc3214f52 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java @@ -1,6 +1,18 @@ -/** - * Alipay.com Inc. - * Copyright (c) 2004-2024 All Rights Reserved. +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alipay.sofa.koupleless.arklet.core.ops.strategy; @@ -24,15 +36,15 @@ public class BatchInstallBizInDirAbsolutePathStrategy implements BatchInstallStrategy { private final BatchInstallHelper batchInstallHelper = new BatchInstallHelper(); - private static final String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; + private static final String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; @Override - public Map> convertToInstallInput(BatchInstallRequest request) throws Throwable { - Map> result = new TreeMap<>(); + public Map> convertToInstallInput(BatchInstallRequest request) throws Throwable { + Map> result = new TreeMap<>(); Map> bizUrls = batchInstallHelper - .getBizUrlsFromLocalFileSystem(request.getBizDirAbsolutePath()); - for (Map.Entry> entry : bizUrls.entrySet()){ + .getBizUrlsFromLocalFileSystem(request.getBizDirAbsolutePath()); + for (Map.Entry> entry : bizUrls.entrySet()) { Integer order = entry.getKey(); for (String bizUrl : entry.getValue()) { result.putIfAbsent(order, new ArrayList<>()); @@ -42,14 +54,13 @@ public Map> convertToInstallInput(BatchInstallReque return result; } - private InstallRequest buildInstallRequest(String bizAbsolutePath){ + private InstallRequest buildInstallRequest(String bizAbsolutePath) { String bizUrl = OSUtils.getLocalFileProtocolPrefix() + bizAbsolutePath; - Map mainAttributes = batchInstallHelper - .getMainAttributes(bizAbsolutePath); + Map mainAttributes = batchInstallHelper.getMainAttributes(bizAbsolutePath); String bizName = (String) mainAttributes.get(Constants.ARK_BIZ_NAME); String bizVersion = (String) mainAttributes.get(Constants.ARK_BIZ_VERSION); - return InstallRequest.builder().bizUrl(bizUrl).bizName(bizName) - .bizVersion(bizVersion).installStrategy(installStrategy).build(); + return InstallRequest.builder().bizUrl(bizUrl).bizName(bizName).bizVersion(bizVersion) + .installStrategy(installStrategy).build(); } } \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java index cc5377d3b..893d78b0e 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java @@ -1,6 +1,18 @@ -/** - * Alipay.com Inc. - * Copyright (c) 2004-2024 All Rights Reserved. +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alipay.sofa.koupleless.arklet.core.ops.strategy; @@ -26,10 +38,11 @@ public class BatchInstallBizInRequestStrategy implements BatchInstallStrategy { private final BatchInstallHelper batchInstallHelper = new BatchInstallHelper(); + @Override public Map> convertToInstallInput(BatchInstallRequest request) throws Throwable { - Map> result = new TreeMap<>(); - for (InstallRequest installRequest : request.getInstallRequests()){ + Map> result = new TreeMap<>(); + for (InstallRequest installRequest : request.getInstallRequests()) { Integer order = parsePriority(installRequest); result.putIfAbsent(order, new ArrayList<>()); result.get(order).add(installRequest); @@ -38,16 +51,16 @@ public Map> convertToInstallInput(BatchInstallRequ } @SneakyThrows - private Integer parsePriority(InstallRequest installRequest){ + private Integer parsePriority(InstallRequest installRequest) { URL url = new URL(installRequest.getBizUrl()); - File bizFile = ArkClient.createBizSaveFile(installRequest.getBizName(), installRequest.getBizVersion()); + File bizFile = ArkClient.createBizSaveFile(installRequest.getBizName(), + installRequest.getBizVersion()); FileUtils.copyInputStreamToFile(url.openStream(), bizFile); Map mainAttributes = batchInstallHelper - .getMainAttributes(bizFile.getAbsolutePath()); + .getMainAttributes(bizFile.getAbsolutePath()); org.apache.commons.io.FileUtils.deleteQuietly(bizFile); return Integer.valueOf( - mainAttributes.getOrDefault("priority", PriorityOrdered.DEFAULT_PRECEDENCE) - .toString()); + mainAttributes.getOrDefault("priority", PriorityOrdered.DEFAULT_PRECEDENCE).toString()); } } \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java index eaa666aa4..312ccbd25 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java @@ -1,6 +1,18 @@ -/** - * Alipay.com Inc. - * Copyright (c) 2004-2024 All Rights Reserved. +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alipay.sofa.koupleless.arklet.core.ops.strategy; @@ -15,5 +27,5 @@ * @version $Id: BatchInstallStrategy.java, v 0.1 2024年12月18日 16:00 立蓬 Exp $ */ public interface BatchInstallStrategy { - Map> convertToInstallInput(BatchInstallRequest request) throws Throwable; + Map> convertToInstallInput(BatchInstallRequest request) throws Throwable; } \ No newline at end of file diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java index b11b367b1..2bee531ca 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java @@ -1,6 +1,18 @@ -/** - * Alipay.com Inc. - * Copyright (c) 2004-2024 All Rights Reserved. +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.alipay.sofa.koupleless.arklet.core.util; diff --git a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java index 5debfa700..5aec81e4c 100644 --- a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java +++ b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java @@ -241,22 +241,21 @@ private void handlePlaybackBaseline(String cmd, MqttMessage msg) throws ArkletRu ArkletLoggerFactory.getDefaultLogger() .info("start to playback baseline with content: " + cmdContent); - Output output = null; + Output output = null; try { output = commandService.process(BuiltinCommand.BATCH_INSTALL_BIZ.getId(), cmdContent); } catch (Throwable e) { ArkletLoggerFactory.getDefaultLogger().error( - String.format("fail to handle command %s with content: %s", cmd, e.getMessage())); + String.format("fail to handle command %s with content: %s", cmd, e.getMessage())); return; } if (!output.failed()) { ArkletLoggerFactory.getDefaultLogger() - .info("install biz success when playback baseline"); + .info("install biz success when playback baseline"); } else { - Map bizUrlToResponse = null == output.getData()?null:output.getData().getBizUrlToResponse(); - ArkletLoggerFactory.getDefaultLogger().error( - String.format("fail to handle command %s with content: %s", cmd, bizUrlToResponse)); + ArkletLoggerFactory.getDefaultLogger() + .error("fail to handle command {} with content: {}", cmd, output); } } From fc6cd490311cef224a1bf1e1d1784537eb00622c Mon Sep 17 00:00:00 2001 From: gaosaroma Date: Mon, 6 Jan 2025 21:35:52 +0800 Subject: [PATCH 4/6] fix batch install handler --- .../core/command/CommandServiceImpl.java | 2 + .../handler/BatchInstallBizHandler.java | 4 +- .../tunnel/mqtt/paho/MqttMessageHandler.java | 54 +++---- .../tunnel/mqtt/paho/handler/MsgHandler.java | 69 +++++++++ .../paho/handler/PlaybackBaselineHandler.java | 132 ++++++++++++++++++ 5 files changed, 224 insertions(+), 37 deletions(-) create mode 100644 arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/MsgHandler.java create mode 100644 arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/PlaybackBaselineHandler.java diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/CommandServiceImpl.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/CommandServiceImpl.java index 770e8d684..cfac8eb24 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/CommandServiceImpl.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/CommandServiceImpl.java @@ -26,6 +26,7 @@ import com.alipay.sofa.ark.common.util.BizIdentityUtils; import com.alipay.sofa.common.utils.StringUtil; import com.alipay.sofa.koupleless.arklet.core.api.model.ResponseCode; +import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.BatchInstallBizHandler; import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.HelpHandler; import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.InstallBizHandler; import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.QueryAllBizHandler; @@ -98,6 +99,7 @@ private void registerBuiltInCommands() { registerCommandHandler(new SwitchBizHandler()); registerCommandHandler(new HealthHandler()); registerCommandHandler(new QueryBizOpsHandler()); + registerCommandHandler(new BatchInstallBizHandler()); } /** {@inheritDoc} */ diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java index b7195e3bd..352930204 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java @@ -22,8 +22,8 @@ import com.alipay.sofa.koupleless.arklet.core.command.builtin.handler.InstallBizHandler.Input; import com.alipay.sofa.koupleless.arklet.core.command.meta.AbstractCommandHandler; import com.alipay.sofa.koupleless.arklet.core.command.meta.Command; -import com.alipay.sofa.koupleless.arklet.core.command.meta.InputMeta; import com.alipay.sofa.koupleless.arklet.core.command.meta.Output; +import com.alipay.sofa.koupleless.arklet.core.command.meta.bizops.ArkBizMeta; import com.alipay.sofa.koupleless.arklet.core.command.meta.bizops.ArkBizOps; import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletRuntimeException; import com.alipay.sofa.koupleless.arklet.core.common.exception.CommandValidationException; @@ -102,7 +102,7 @@ private BatchInstallResponse convertClientResponse(com.alipay.sofa.koupleless.ar @Getter @Setter - public static class BatchInstallInput extends InputMeta { + public static class BatchInstallInput extends ArkBizMeta { private Input[] bizList; } diff --git a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java index 5aec81e4c..47cd4cba5 100644 --- a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java +++ b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/MqttMessageHandler.java @@ -26,7 +26,8 @@ import com.alipay.sofa.koupleless.arklet.core.command.meta.Output; import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletInitException; import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletRuntimeException; -import com.alipay.sofa.koupleless.arklet.core.common.model.BatchInstallResponse; +import com.alipay.sofa.koupleless.arklet.tunnel.mqtt.paho.handler.MsgHandler; +import com.alipay.sofa.koupleless.arklet.tunnel.mqtt.paho.handler.PlaybackBaselineHandler; import com.alipay.sofa.koupleless.common.log.ArkletLoggerFactory; import com.alipay.sofa.koupleless.arklet.core.common.model.BaseMetadata; import com.alipay.sofa.koupleless.arklet.core.hook.base.BaseMetadataHook; @@ -53,12 +54,14 @@ */ public class MqttMessageHandler { - public static boolean baselineQueryComplete = false; - private final CommandService commandService; - private final BaseMetadataHook baseMetadataHook; - private final MqttClient mqttClient; - private String baseEnv; - private final AtomicBoolean run = new AtomicBoolean(false); + public static boolean baselineQueryComplete = false; + private final CommandService commandService; + private final BaseMetadataHook baseMetadataHook; + private final MqttClient mqttClient; + private String baseEnv; + private final AtomicBoolean run = new AtomicBoolean(false); + + private final Map msgHandlers = new HashMap<>(); public MqttMessageHandler(CommandService commandService, BaseMetadataHook baseMetadataHook, MqttClient mqttClient, String baseEnv) { @@ -71,6 +74,13 @@ public MqttMessageHandler(CommandService commandService, BaseMetadataHook baseMe } else { this.baseEnv = this.baseEnv.toLowerCase(); } + + initMsgHandlers(); + } + + private void initMsgHandlers() { + msgHandlers.put(PlaybackBaselineHandler.Mqtt_CMD, + new PlaybackBaselineHandler(commandService, baseMetadataHook, mqttClient, baseEnv)); } /** @@ -188,8 +198,8 @@ public void handleCommand(String cmd, MqttMessage msg) throws ArkletRuntimeExcep if (cmd.equals(BuiltinCommand.INSTALL_BIZ.getId()) || cmd.equals(BuiltinCommand.UNINSTALL_BIZ.getId())) { handleBizOperation(cmd, msg); - } else if (cmd.equals("baseline")) { - handlePlaybackBaseline(cmd, msg); + } else if (PlaybackBaselineHandler.Mqtt_CMD.equals(cmd)) { + msgHandlers.get(PlaybackBaselineHandler.Mqtt_CMD).handle(msg); } else if (cmd.equals(BuiltinCommand.HEALTH.getId())) { handleHealthCommand(cmd, msg); } else if (cmd.equals(BuiltinCommand.QUERY_ALL_BIZ.getId())) { @@ -233,32 +243,6 @@ private void handleBizOperation(String cmd, MqttMessage msg) throws ArkletRuntim } } - private void handlePlaybackBaseline(String cmd, MqttMessage msg) throws ArkletRuntimeException { - List> cmdContents = JSONObject.parseObject(msg.toString(), List.class); - Map cmdContent = new HashMap<>(); - cmdContent.put("bizList", cmdContents); - - ArkletLoggerFactory.getDefaultLogger() - .info("start to playback baseline with content: " + cmdContent); - - Output output = null; - try { - output = commandService.process(BuiltinCommand.BATCH_INSTALL_BIZ.getId(), cmdContent); - } catch (Throwable e) { - ArkletLoggerFactory.getDefaultLogger().error( - String.format("fail to handle command %s with content: %s", cmd, e.getMessage())); - return; - } - - if (!output.failed()) { - ArkletLoggerFactory.getDefaultLogger() - .info("install biz success when playback baseline"); - } else { - ArkletLoggerFactory.getDefaultLogger() - .error("fail to handle command {} with content: {}", cmd, output); - } - } - private void handleHealthCommand(String cmd, MqttMessage msg) throws ArkletRuntimeException { Map cmdContent = JSONObject.parseObject(msg.toString(), HashMap.class); try { diff --git a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/MsgHandler.java b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/MsgHandler.java new file mode 100644 index 000000000..edfd205b5 --- /dev/null +++ b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/MsgHandler.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.arklet.tunnel.mqtt.paho.handler; + +import com.alipay.sofa.koupleless.arklet.core.command.CommandService; +import com.alipay.sofa.koupleless.arklet.core.command.builtin.BuiltinCommand; +import com.alipay.sofa.koupleless.arklet.core.command.meta.Output; +import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletRuntimeException; +import com.alipay.sofa.koupleless.common.log.ArkletLoggerFactory; +import org.eclipse.paho.client.mqttv3.MqttMessage; + +import java.util.Map; + +/** + * @author lianglipeng.llp@alibaba-inc.com + * @version $Id: MsgHandler.java, v 0.1 2024年12月30日 14:22 立蓬 Exp $ + */ +public abstract class MsgHandler { + + protected final CommandService commandService; + + public MsgHandler(CommandService commandService) { + this.commandService = commandService; + } + + public void handle(MqttMessage msg) { + Map cmdContent = toRequest(msg); + ArkletLoggerFactory.getDefaultLogger().info("start to handle mqtt cmd {} with content: {}", + getMqttCMD(), cmdContent); + + Output output = null; + try { + output = commandService.process(getArkletCommand().getId(), cmdContent); + pubSuccessMsg(output); + } catch (Throwable e) { + ArkletLoggerFactory.getDefaultLogger().error(String.format( + "fail to handle mqtt cmd %s with content: %s", getMqttCMD(), e.getMessage())); + pubThrowableMsg(e); + throw new ArkletRuntimeException(e); + } + + ArkletLoggerFactory.getDefaultLogger() + .info("finished to handle mqtt cmd {} when with output: {}", getMqttCMD(), output); + } + + abstract Map toRequest(MqttMessage msg); + + abstract String getMqttCMD(); + + abstract BuiltinCommand getArkletCommand(); + + abstract void pubSuccessMsg(Output output) throws Exception; + + abstract void pubThrowableMsg(Throwable e); +} \ No newline at end of file diff --git a/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/PlaybackBaselineHandler.java b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/PlaybackBaselineHandler.java new file mode 100644 index 000000000..9f762e92b --- /dev/null +++ b/arklet-tunnel-mqtt/src/main/java/com/alipay/sofa/koupleless/arklet/tunnel/mqtt/paho/handler/PlaybackBaselineHandler.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.koupleless.arklet.tunnel.mqtt.paho.handler; + +import com.alibaba.fastjson.JSONObject; +import com.alipay.sofa.ark.api.ClientResponse; +import com.alipay.sofa.ark.api.ResponseCode; +import com.alipay.sofa.koupleless.arklet.core.command.CommandService; +import com.alipay.sofa.koupleless.arklet.core.command.builtin.BuiltinCommand; +import com.alipay.sofa.koupleless.arklet.core.command.meta.Output; +import com.alipay.sofa.koupleless.arklet.core.common.exception.ArkletRuntimeException; +import com.alipay.sofa.koupleless.arklet.core.hook.base.BaseMetadataHook; +import com.alipay.sofa.koupleless.arklet.core.util.ExceptionUtils; +import com.alipay.sofa.koupleless.arklet.tunnel.mqtt.model.Constants; +import com.alipay.sofa.koupleless.arklet.tunnel.mqtt.model.MqttResponse; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author lianglipeng.llp@alibaba-inc.com + * @version $Id: PlaybackBaselineHandler.java, v 0.1 2024年12月30日 14:21 立蓬 Exp $ + */ +public class PlaybackBaselineHandler extends MsgHandler { + public static final String Mqtt_CMD = "baseline"; + + private final MqttClient mqttClient; + + private final BaseMetadataHook baseMetadataHook; + + private final String baseEnv; + + public PlaybackBaselineHandler(CommandService commandService, BaseMetadataHook baseMetadataHook, + MqttClient mqttClient, String baseEnv) { + super(commandService); + this.mqttClient = mqttClient; + this.baseMetadataHook = baseMetadataHook; + this.baseEnv = baseEnv; + } + + @Override + protected String getMqttCMD() { + return Mqtt_CMD; + } + + @Override + protected BuiltinCommand getArkletCommand() { + return BuiltinCommand.BATCH_INSTALL_BIZ; + } + + @Override + protected void pubThrowableMsg(Throwable e) { + Map bizOperationResponse = failOfResponse(e); + try { + mqttClient.publish(getPubTopic(), + JSONObject.toJSONString(MqttResponse.withData(bizOperationResponse)).getBytes(), 1, + false); + } catch (MqttException ex) { + throw new ArkletRuntimeException(ex); + } + } + + @Override + protected void pubSuccessMsg(Output output) throws MqttException { + Map bizOperationResponse = successOfResponse(output); + mqttClient.publish(getPubTopic(), + JSONObject.toJSONString(MqttResponse.withData(bizOperationResponse)).getBytes(), 1, + false); + } + + private String getPubTopic() { + return String.format("koupleless_%s/%s/base/batchInstallBizResponse", baseEnv, + baseMetadataHook.getIdentity()); + } + + @Override + public Map toRequest(MqttMessage msg) { + List> cmdContents = JSONObject.parseObject(msg.toString(), List.class); + Map cmdContent = new HashMap<>(); + cmdContent.put("bizList", cmdContents); + return cmdContent; + } + + /** + * success mqtt response like: + * { "command" -> "batchInstallBiz" } + * { "response" -> output } + * @return java.util.Map + */ + private Map successOfResponse(Output output) { + Map bizOperationResponse = new HashMap<>(); + bizOperationResponse.put(Constants.COMMAND, getArkletCommand().getId()); + bizOperationResponse.put(Constants.COMMAND_RESPONSE, output); + return bizOperationResponse; + } + + /** + * failed mqtt response like: + * { "command" -> "batchInstallBiz" } + * { "response" -> output } + * @return java.util.Map + */ + private Map failOfResponse(Throwable e) { + ClientResponse data = new ClientResponse(); + data.setMessage(ExceptionUtils.getStackTraceAsString(e)); + data.setCode(ResponseCode.FAILED); + Output output = Output.ofFailed(data, e.getMessage()); + + Map bizOperationResponse = new HashMap<>(); + bizOperationResponse.put(Constants.COMMAND, getArkletCommand().getId()); + bizOperationResponse.put(Constants.COMMAND_RESPONSE, output); + return bizOperationResponse; + } +} \ No newline at end of file From 7ad883c904ab638befdb5685b8ed4626873a4b9d Mon Sep 17 00:00:00 2001 From: gaosaroma Date: Tue, 7 Jan 2025 00:06:16 +0800 Subject: [PATCH 5/6] fix ut --- arklet-core/pom.xml | 1 + .../arklet/core/ops/BatchInstallHelper.java | 4 +- .../core/ops/UnifiedOperationServiceImpl.java | 2 +- ...chInstallBizInDirAbsolutePathStrategy.java | 8 +-- .../BatchInstallBizInRequestStrategy.java | 4 +- .../UnifiedOperationServiceImplTests.java | 60 +++++++++---------- 6 files changed, 37 insertions(+), 42 deletions(-) diff --git a/arklet-core/pom.xml b/arklet-core/pom.xml index 20f766cdd..e8d0deb8f 100644 --- a/arklet-core/pom.xml +++ b/arklet-core/pom.xml @@ -16,6 +16,7 @@ com.alipay.sofa sofa-ark-api + ${sofa.ark.version} com.alipay.sofa.koupleless diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/BatchInstallHelper.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/BatchInstallHelper.java index 1e78348ad..0cd282d22 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/BatchInstallHelper.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/BatchInstallHelper.java @@ -47,7 +47,7 @@ public class BatchInstallHelper { * @return a {@link java.util.List} object */ @SneakyThrows - public Map> getBizUrlsFromLocalFileSystem(String absoluteBizDirPath) { + public static Map> getBizUrlsFromLocalFileSystem(String absoluteBizDirPath) { Map> bizUrlsWithPriority = new HashMap<>(); Files.walkFileTree(new File(absoluteBizDirPath).toPath(), new SimpleFileVisitor() { @Override @@ -89,7 +89,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { * @return 主属性。 */ @SneakyThrows - public Map getMainAttributes(String bizUrl) { + public static Map getMainAttributes(String bizUrl) { try (JarFile jarFile = new JarFile(bizUrl)) { Manifest manifest = jarFile.getManifest(); Preconditions.checkState(manifest != null, "Manifest file not found in the JAR."); diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java index 50ae87d42..5602e4183 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/UnifiedOperationServiceImpl.java @@ -141,7 +141,7 @@ public BatchInstallResponse batchInstall(BatchInstallRequest request) throws Thr private BatchInstallStrategy getBatchInstallStrategy(BatchInstallRequest request) { if (StringUtil.isNotEmpty(request.getBizDirAbsolutePath())) { - return batchInstallBizInRequestStrategy; + return batchInstallBizInDirAbsolutePathStrategy; } return batchInstallBizInRequestStrategy; } diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java index dc3214f52..820210b17 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java @@ -34,15 +34,13 @@ * @version $Id: BatchInstallBizInDirStrategy.java, v 0.1 2024年12月18日 16:00 立蓬 Exp $ */ public class BatchInstallBizInDirAbsolutePathStrategy implements BatchInstallStrategy { - private final BatchInstallHelper batchInstallHelper = new BatchInstallHelper(); - - private static final String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; + private static final String installStrategy = STRATEGY_INSTALL_ONLY_STRATEGY; @Override public Map> convertToInstallInput(BatchInstallRequest request) throws Throwable { Map> result = new TreeMap<>(); - Map> bizUrls = batchInstallHelper + Map> bizUrls = BatchInstallHelper .getBizUrlsFromLocalFileSystem(request.getBizDirAbsolutePath()); for (Map.Entry> entry : bizUrls.entrySet()) { Integer order = entry.getKey(); @@ -56,7 +54,7 @@ public Map> convertToInstallInput(BatchInstallRequ private InstallRequest buildInstallRequest(String bizAbsolutePath) { String bizUrl = OSUtils.getLocalFileProtocolPrefix() + bizAbsolutePath; - Map mainAttributes = batchInstallHelper.getMainAttributes(bizAbsolutePath); + Map mainAttributes = BatchInstallHelper.getMainAttributes(bizAbsolutePath); String bizName = (String) mainAttributes.get(Constants.ARK_BIZ_NAME); String bizVersion = (String) mainAttributes.get(Constants.ARK_BIZ_VERSION); diff --git a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java index 893d78b0e..652f10255 100644 --- a/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java +++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java @@ -37,8 +37,6 @@ */ public class BatchInstallBizInRequestStrategy implements BatchInstallStrategy { - private final BatchInstallHelper batchInstallHelper = new BatchInstallHelper(); - @Override public Map> convertToInstallInput(BatchInstallRequest request) throws Throwable { Map> result = new TreeMap<>(); @@ -57,7 +55,7 @@ private Integer parsePriority(InstallRequest installRequest) { installRequest.getBizVersion()); FileUtils.copyInputStreamToFile(url.openStream(), bizFile); - Map mainAttributes = batchInstallHelper + Map mainAttributes = BatchInstallHelper .getMainAttributes(bizFile.getAbsolutePath()); org.apache.commons.io.FileUtils.deleteQuietly(bizFile); return Integer.valueOf( diff --git a/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java b/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java index 055344991..ddb112ade 100644 --- a/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java +++ b/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java @@ -25,6 +25,7 @@ import com.alipay.sofa.koupleless.arklet.core.health.custom.MockBizManagerService; import com.alipay.sofa.koupleless.arklet.core.ops.BatchInstallHelper; import com.alipay.sofa.koupleless.arklet.core.ops.UnifiedOperationServiceImpl; +import com.alipay.sofa.koupleless.common.BizRuntimeContextRegistry; import lombok.SneakyThrows; import org.junit.Assert; import org.junit.Before; @@ -52,20 +53,9 @@ * @since 2023/10/26 */ -@RunWith(MockitoJUnitRunner.class) public class UnifiedOperationServiceImplTests { - @InjectMocks - private UnifiedOperationServiceImpl unifiedOperationService; - - @Spy - private BatchInstallHelper batchInstallHelper; - - @Before - public void setUp() { - if (unifiedOperationService == null) { - unifiedOperationService = new UnifiedOperationServiceImpl(); - } - } + private final UnifiedOperationServiceImpl unifiedOperationService = Mockito + .spy(new UnifiedOperationServiceImpl()); /** * 测试初始化方法 @@ -169,25 +159,33 @@ public void testSwitchBizWithValidBizNameAndVersion() throws Throwable { @SneakyThrows @Test public void testBatchInstall() { - { - List paths = new ArrayList<>(); - paths.add("/file/a-biz.jar"); - paths.add("/file/b-biz.jar"); - paths.add("/file/notbiz.jar"); - Map> pathsInOrder = new HashMap<>(); - pathsInOrder.put(100, paths); - - doReturn(pathsInOrder).when(batchInstallHelper).getBizUrlsFromLocalFileSystem(any()); + try (MockedStatic batchInstallHelperMockedStatic = Mockito + .mockStatic(BatchInstallHelper.class)) { + { + List paths = new ArrayList<>(); + paths.add("/file/a-biz.jar"); + paths.add("/file/b-biz.jar"); + paths.add("/file/notbiz.jar"); + Map> pathsInOrder = new HashMap<>(); + pathsInOrder.put(100, paths); + batchInstallHelperMockedStatic + .when(() -> BatchInstallHelper.getBizUrlsFromLocalFileSystem(any())) + .thenReturn(pathsInOrder); + batchInstallHelperMockedStatic + .when(() -> BatchInstallHelper.getMainAttributes(anyString())) + .thenReturn(new HashMap<>()); + + doReturn(Mockito.mock(ClientResponse.class)).when(unifiedOperationService) + .safeBatchInstall(any()); + } + + BatchInstallResponse response = unifiedOperationService.batchInstall( + BatchInstallRequest.builder().bizDirAbsolutePath("/path/to/biz").build()); + + Assert.assertTrue(response.getBizUrlToResponse().containsKey("file:///file/a-biz.jar")); + + Assert.assertTrue(response.getBizUrlToResponse().containsKey("file:///file/b-biz.jar")); - doReturn(new HashMap<>()).when(batchInstallHelper).getMainAttributes(anyString()); } - - BatchInstallResponse response = unifiedOperationService - .batchInstall(BatchInstallRequest.builder().bizDirAbsolutePath("/path/to/biz").build()); - - Assert.assertTrue(response.getBizUrlToResponse().containsKey("/file/a-biz.jar")); - - Assert.assertTrue(response.getBizUrlToResponse().containsKey("/file/b-biz.jar")); - } } From 742ed444e315b6a6ae4e07ca98c26ff77988bbdc Mon Sep 17 00:00:00 2001 From: gaosaroma Date: Tue, 7 Jan 2025 00:18:00 +0800 Subject: [PATCH 6/6] fix ut --- .../core/component/UnifiedOperationServiceImplTests.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java b/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java index ddb112ade..81f34518a 100644 --- a/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java +++ b/arklet-core/src/test/java/com/alipay/sofa/koupleless/arklet/core/component/UnifiedOperationServiceImplTests.java @@ -41,6 +41,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import static com.alipay.sofa.koupleless.arklet.core.common.model.Constants.STRATEGY_INSTALL_ONLY_STRATEGY; import static com.alipay.sofa.koupleless.arklet.core.common.model.Constants.STRATEGY_UNINSTALL_THEN_INSTALL; @@ -182,10 +183,9 @@ public void testBatchInstall() { BatchInstallResponse response = unifiedOperationService.batchInstall( BatchInstallRequest.builder().bizDirAbsolutePath("/path/to/biz").build()); - Assert.assertTrue(response.getBizUrlToResponse().containsKey("file:///file/a-biz.jar")); - - Assert.assertTrue(response.getBizUrlToResponse().containsKey("file:///file/b-biz.jar")); - + Set bizUrls = response.getBizUrlToResponse().keySet(); + Assert.assertTrue(bizUrls.stream().anyMatch(url -> url.endsWith("a-biz.jar"))); + Assert.assertTrue(bizUrls.stream().anyMatch(url -> url.endsWith("b-biz.jar"))); } } }