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/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/BuiltinCommand.java b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/BuiltinCommand.java
index b6c64ac27..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,6 +31,9 @@ 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..352930204
--- /dev/null
+++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/command/builtin/handler/BatchInstallBizHandler.java
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+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.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;
+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 ArkBizMeta {
+ 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..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
@@ -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,6 +101,10 @@ 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");
notBlank(input.getBizUrl(), "bizUrl should not be blank");
@@ -139,7 +133,7 @@ public void validate(Input input) throws CommandValidationException {
}
}
- 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..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,10 +37,15 @@ 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;
+
+ /**
+ * 模块批量发布请求。
+ */
+ private InstallRequest[] installRequests = new InstallRequest[0];
}
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 be0addf20..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
@@ -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,20 @@ 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) {
- futures.add(CompletableFuture.supplyAsync(
- () -> safeBatchInstall(bizUrl, request.getInstallStrategy()), executorService));
+ for (InstallRequest bizRequest : bizRequestInSameOrder) {
+ futures.add(CompletableFuture.supplyAsync(() -> safeBatchInstall(bizRequest),
+ executorService));
}
// wait for all install futures done
@@ -122,8 +122,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 +139,13 @@ public BatchInstallResponse batchInstall(BatchInstallRequest request) throws Thr
.bizUrlToResponse(bizUrlToInstallResult).build();
}
+ private BatchInstallStrategy getBatchInstallStrategy(BatchInstallRequest request) {
+ if (StringUtil.isNotEmpty(request.getBizDirAbsolutePath())) {
+ return batchInstallBizInDirAbsolutePathStrategy;
+ }
+ 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..820210b17
--- /dev/null
+++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInDirAbsolutePathStrategy.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+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 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..652f10255
--- /dev/null
+++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallBizInRequestStrategy.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+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 {
+
+ @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..312ccbd25
--- /dev/null
+++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/ops/strategy/BatchInstallStrategy.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+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..2bee531ca
--- /dev/null
+++ b/arklet-core/src/main/java/com/alipay/sofa/koupleless/arklet/core/util/ResourceUtils.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+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-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..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
@@ -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;
@@ -40,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;
@@ -52,20 +54,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 +160,32 @@ 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());
-
- doReturn(new HashMap<>()).when(batchInstallHelper).getMainAttributes(anyString());
+ 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());
+
+ 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")));
}
-
- 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"));
-
}
}
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..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,6 +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.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;
@@ -52,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) {
@@ -70,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));
}
/**
@@ -187,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())) {
@@ -232,29 +243,6 @@ private void handleBizOperation(String cmd, MqttMessage msg) throws ArkletRuntim
}
}
- private void handlePlaybackBaseline(String cmd, MqttMessage msg) throws ArkletRuntimeException {
- List