listThreadPoolExecutorId() {
+ return new ArrayList<>(HOLDER_MAP.keySet());
+ }
+
+ /**
+ * Get the number of dynamic thread pools.
+ * The data may be inaccurate when the project is initially
+ * launched because registration is done asynchronously.
+ *
+ * @return thread-pool size
+ */
+ public static Integer getThreadPoolExecutorSize() {
+ return listThreadPoolExecutorId().size();
+ }
}
diff --git a/infra/common/src/main/java/cn/hippo4j/common/handler/DynamicThreadPoolAdapterChoose.java b/infra/common/src/main/java/cn/hippo4j/common/handler/DynamicThreadPoolAdapterChoose.java
new file mode 100644
index 00000000..3f2b3d17
--- /dev/null
+++ b/infra/common/src/main/java/cn/hippo4j/common/handler/DynamicThreadPoolAdapterChoose.java
@@ -0,0 +1,96 @@
+/*
+ * 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 cn.hippo4j.common.handler;
+
+import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
+import cn.hippo4j.common.extension.spi.ServiceLoaderRegistry;
+import cn.hippo4j.common.toolkit.CollectionUtil;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Dynamic thread pool adapter choose.
+ */
+public class DynamicThreadPoolAdapterChoose {
+
+ private static final List DYNAMIC_THREAD_POOL_ADAPTERS = new ArrayList<>();
+
+ static {
+ DYNAMIC_THREAD_POOL_ADAPTERS.add(new TransmittableThreadLocalExecutorAdapter());
+ DYNAMIC_THREAD_POOL_ADAPTERS.add(new TransmittableThreadLocalExecutorServiceAdapter());
+ DYNAMIC_THREAD_POOL_ADAPTERS.add(new ZipkinExecutorAdapter());
+ loadCustomerAdapter();
+ }
+
+ /**
+ * Check if the object contains thread pool information.
+ *
+ * @param executor objects where there may be instances
+ * of dynamic thread pools
+ * @return matching results
+ */
+ public static boolean match(Object executor) {
+ return DYNAMIC_THREAD_POOL_ADAPTERS.stream().anyMatch(each -> each.match(executor));
+ }
+
+ /**
+ * Get the dynamic thread pool reference in the object.
+ *
+ * @param executor objects where there may be instances
+ * of dynamic thread pools
+ * @return get the real dynamic thread pool instance
+ */
+ public static ThreadPoolExecutor unwrap(Object executor) {
+ Optional dynamicThreadPoolAdapterOptional = DYNAMIC_THREAD_POOL_ADAPTERS.stream().filter(each -> each.match(executor)).findFirst();
+ return dynamicThreadPoolAdapterOptional.map(each -> each.unwrap(executor)).orElse(null);
+ }
+
+ /**
+ * If the {@link DynamicThreadPoolAdapter#match(Object)} conditions are met,
+ * the thread pool is replaced with a dynamic thread pool.
+ *
+ * @param executor objects where there may be instances
+ * of dynamic thread pools
+ * @param dynamicThreadPoolExecutor dynamic thread-pool executor
+ */
+ public static void replace(Object executor, Executor dynamicThreadPoolExecutor) {
+ Optional dynamicThreadPoolAdapterOptional = DYNAMIC_THREAD_POOL_ADAPTERS.stream().filter(each -> each.match(executor)).findFirst();
+ dynamicThreadPoolAdapterOptional.ifPresent(dynamicThreadPoolAdapter -> dynamicThreadPoolAdapter.replace(executor, dynamicThreadPoolExecutor));
+ }
+
+ /**
+ * Load SPI customer adapter.
+ */
+ private static void loadCustomerAdapter() {
+ ServiceLoaderRegistry.register(DynamicThreadPoolAdapter.class);
+ Collection instances = ServiceLoaderRegistry.getSingletonServiceInstances(DynamicThreadPoolAdapter.class);
+ if (CollectionUtil.isEmpty(instances)) {
+ return;
+ }
+ for (DynamicThreadPoolAdapter instance : instances) {
+ if (instance != null) {
+ DYNAMIC_THREAD_POOL_ADAPTERS.add(instance);
+ }
+ }
+ }
+}
diff --git a/threadpool/core/src/main/java/cn/hippo4j/core/executor/state/ThreadPoolStatusHandler.java b/infra/common/src/main/java/cn/hippo4j/common/handler/ThreadPoolStatusHandler.java
similarity index 98%
rename from threadpool/core/src/main/java/cn/hippo4j/core/executor/state/ThreadPoolStatusHandler.java
rename to infra/common/src/main/java/cn/hippo4j/common/handler/ThreadPoolStatusHandler.java
index 30bad4a2..5cba3676 100644
--- a/threadpool/core/src/main/java/cn/hippo4j/core/executor/state/ThreadPoolStatusHandler.java
+++ b/infra/common/src/main/java/cn/hippo4j/common/handler/ThreadPoolStatusHandler.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package cn.hippo4j.core.executor.state;
+package cn.hippo4j.common.handler;
import cn.hippo4j.common.toolkit.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
diff --git a/infra/common/src/main/java/cn/hippo4j/common/handler/TransmittableThreadLocalExecutorAdapter.java b/infra/common/src/main/java/cn/hippo4j/common/handler/TransmittableThreadLocalExecutorAdapter.java
new file mode 100644
index 00000000..079fc11e
--- /dev/null
+++ b/infra/common/src/main/java/cn/hippo4j/common/handler/TransmittableThreadLocalExecutorAdapter.java
@@ -0,0 +1,50 @@
+/*
+ * 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 cn.hippo4j.common.handler;
+
+import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
+import cn.hippo4j.common.toolkit.ReflectUtil;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Transmittable thread local executor adapter.
+ */
+public class TransmittableThreadLocalExecutorAdapter implements DynamicThreadPoolAdapter {
+
+ private static final String MATCH_CLASS_NAME = "ExecutorTtlWrapper";
+
+ private static final String FIELD_NAME = "executor";
+
+ @Override
+ public boolean match(Object executor) {
+ return Objects.equals(MATCH_CLASS_NAME, executor.getClass().getSimpleName());
+ }
+
+ @Override
+ public ThreadPoolExecutor unwrap(Object executor) {
+ return (ThreadPoolExecutor) ReflectUtil.getFieldValue(executor, FIELD_NAME);
+ }
+
+ @Override
+ public void replace(Object executor, Executor dynamicThreadPoolExecutor) {
+ ReflectUtil.setFieldValue(executor, FIELD_NAME, dynamicThreadPoolExecutor);
+ }
+}
diff --git a/infra/common/src/main/java/cn/hippo4j/common/handler/TransmittableThreadLocalExecutorServiceAdapter.java b/infra/common/src/main/java/cn/hippo4j/common/handler/TransmittableThreadLocalExecutorServiceAdapter.java
new file mode 100644
index 00000000..5dd27df9
--- /dev/null
+++ b/infra/common/src/main/java/cn/hippo4j/common/handler/TransmittableThreadLocalExecutorServiceAdapter.java
@@ -0,0 +1,50 @@
+/*
+ * 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 cn.hippo4j.common.handler;
+
+import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
+import cn.hippo4j.common.toolkit.ReflectUtil;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Transmittable thread local executor service adapter.
+ */
+public class TransmittableThreadLocalExecutorServiceAdapter implements DynamicThreadPoolAdapter {
+
+ private static final String MATCH_CLASS_NAME = "ExecutorServiceTtlWrapper";
+
+ private static final String FIELD_NAME = "executorService";
+
+ @Override
+ public boolean match(Object executor) {
+ return Objects.equals(MATCH_CLASS_NAME, executor.getClass().getSimpleName());
+ }
+
+ @Override
+ public ThreadPoolExecutor unwrap(Object executor) {
+ return (ThreadPoolExecutor) ReflectUtil.getFieldValue(executor, FIELD_NAME);
+ }
+
+ @Override
+ public void replace(Object executor, Executor dynamicThreadPoolExecutor) {
+ ReflectUtil.setFieldValue(executor, FIELD_NAME, dynamicThreadPoolExecutor);
+ }
+}
diff --git a/infra/common/src/main/java/cn/hippo4j/common/handler/ZipkinExecutorAdapter.java b/infra/common/src/main/java/cn/hippo4j/common/handler/ZipkinExecutorAdapter.java
new file mode 100644
index 00000000..7177c070
--- /dev/null
+++ b/infra/common/src/main/java/cn/hippo4j/common/handler/ZipkinExecutorAdapter.java
@@ -0,0 +1,76 @@
+/*
+ * 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 cn.hippo4j.common.handler;
+
+import cn.hippo4j.common.api.DynamicThreadPoolAdapter;
+import cn.hippo4j.common.toolkit.ReflectUtil;
+
+import java.lang.reflect.Field;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Zipkin thread local executor adapter.
+ */
+public class ZipkinExecutorAdapter implements DynamicThreadPoolAdapter {
+
+ private static final String MATCH_CLASS_NAME = "brave.internal.WrappingExecutorService";
+ private static final String FIELD_NAME = "delegate";
+ private static final String TYPE_NAME = "java.util.concurrent.ExecutorService";
+
+ @Override
+ public boolean match(Object executor) {
+ return matchSuper(executor);
+ }
+
+ public boolean matchSuper(Object executor) {
+ if (Objects.equals(MATCH_CLASS_NAME, Optional.ofNullable(executor).map(Object::getClass).map(Class::getName).orElse(null))) {
+ return true;
+ } else {
+ return Objects.equals(MATCH_CLASS_NAME, Optional.ofNullable(executor).map(Object::getClass).map(Class::getSuperclass).map(Class::getName).orElse(null));
+ }
+ }
+
+ @Override
+ public ThreadPoolExecutor unwrap(Object executor) {
+ Object unwrap = doUnwrap(executor);
+ if (unwrap == null) {
+ return null;
+ }
+ return (ThreadPoolExecutor) unwrap;
+ }
+
+ @Override
+ public void replace(Object executor, Executor dynamicThreadPoolExecutor) {
+ Field field = ReflectUtil.findField(executor, FIELD_NAME, TYPE_NAME);
+ ReflectUtil.setFieldValue(executor, field, dynamicThreadPoolExecutor);
+ }
+
+ private Object doUnwrap(Object executor) {
+ Object unwrap = ReflectUtil.getFieldValue(executor, FIELD_NAME);
+ if (unwrap == null) {
+ Field field = ReflectUtil.findField(executor, FIELD_NAME, TYPE_NAME);
+ if (field != null) {
+ return ReflectUtil.getFieldValue(executor, field);
+ }
+ }
+ return null;
+ }
+}
diff --git a/threadpool/adapter/base/src/main/java/cn/hippo4j/adapter/base/ThreadPoolAdapterState.java b/infra/common/src/main/java/cn/hippo4j/common/model/ThreadPoolAdapterState.java
similarity index 97%
rename from threadpool/adapter/base/src/main/java/cn/hippo4j/adapter/base/ThreadPoolAdapterState.java
rename to infra/common/src/main/java/cn/hippo4j/common/model/ThreadPoolAdapterState.java
index b46c6c26..ad7322d9 100644
--- a/threadpool/adapter/base/src/main/java/cn/hippo4j/adapter/base/ThreadPoolAdapterState.java
+++ b/infra/common/src/main/java/cn/hippo4j/common/model/ThreadPoolAdapterState.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package cn.hippo4j.adapter.base;
+package cn.hippo4j.common.model;
import lombok.Data;
diff --git a/infra/common/src/main/java/cn/hippo4j/common/propertie/EnvironmentProperties.java b/infra/common/src/main/java/cn/hippo4j/common/propertie/EnvironmentProperties.java
new file mode 100644
index 00000000..c874df49
--- /dev/null
+++ b/infra/common/src/main/java/cn/hippo4j/common/propertie/EnvironmentProperties.java
@@ -0,0 +1,44 @@
+/*
+ * 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 cn.hippo4j.common.propertie;
+
+/**
+ * Configurable environment properties.
+ */
+public final class EnvironmentProperties {
+
+ /**
+ * spring.profiles.active
+ */
+ public static String active = "UNKNOWN";
+
+ /**
+ * spring.dynamic.thread-pool.item-id
+ */
+ public static String itemId;
+
+ /**
+ * spring.application.name
+ */
+ public static String applicationName;
+
+ /**
+ * spring.dynamic.thread-pool.check-state-interval
+ */
+ public static Long checkStateInterval;
+}
diff --git a/infra/common/src/main/java/cn/hippo4j/common/propertie/IdentifyProperties.java b/infra/common/src/main/java/cn/hippo4j/common/propertie/IdentifyProperties.java
new file mode 100644
index 00000000..0382e6b7
--- /dev/null
+++ b/infra/common/src/main/java/cn/hippo4j/common/propertie/IdentifyProperties.java
@@ -0,0 +1,32 @@
+/*
+ * 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 cn.hippo4j.common.propertie;
+
+import lombok.Setter;
+
+/**
+ * Identify properties.
+ */
+public class IdentifyProperties {
+
+ /**
+ * The unique identifier of the client, initialized when the project starts
+ */
+ @Setter
+ public static String IDENTIFY;
+}
diff --git a/threadpool/core/src/main/java/cn/hippo4j/core/executor/state/AbstractThreadPoolRuntime.java b/infra/common/src/main/java/cn/hippo4j/common/support/AbstractThreadPoolRuntime.java
similarity index 82%
rename from threadpool/core/src/main/java/cn/hippo4j/core/executor/state/AbstractThreadPoolRuntime.java
rename to infra/common/src/main/java/cn/hippo4j/common/support/AbstractThreadPoolRuntime.java
index 90b5f547..f227137e 100644
--- a/threadpool/core/src/main/java/cn/hippo4j/core/executor/state/AbstractThreadPoolRuntime.java
+++ b/infra/common/src/main/java/cn/hippo4j/common/support/AbstractThreadPoolRuntime.java
@@ -15,16 +15,17 @@
* limitations under the License.
*/
-package cn.hippo4j.core.executor.state;
+package cn.hippo4j.common.support;
+import cn.hippo4j.common.executor.ThreadPoolExecutorHolder;
+import cn.hippo4j.common.executor.ThreadPoolExecutorRegistry;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
-import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
-import cn.hippo4j.core.executor.DynamicThreadPoolWrapper;
-import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
import cn.hippo4j.common.toolkit.CalculateUtil;
+import cn.hippo4j.common.toolkit.ReflectUtil;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
+import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@@ -51,8 +52,8 @@ public abstract class AbstractThreadPoolRuntime {
* @return thread-pool run state info
*/
public ThreadPoolRunStateInfo getPoolRunState(String threadPoolId) {
- DynamicThreadPoolWrapper executorService = GlobalThreadPoolManage.getExecutorService(threadPoolId);
- ThreadPoolExecutor pool = executorService.getExecutor();
+ ThreadPoolExecutorHolder executorHolder = ThreadPoolExecutorRegistry.getHolder(threadPoolId);
+ ThreadPoolExecutor pool = executorHolder.getExecutor();
return getPoolRunState(threadPoolId, pool);
}
@@ -68,7 +69,13 @@ public abstract class AbstractThreadPoolRuntime {
int activeCount = actualExecutor.getActiveCount();
int largestPoolSize = actualExecutor.getLargestPoolSize();
BlockingQueue blockingQueue = actualExecutor.getQueue();
- long rejectCount = actualExecutor instanceof DynamicThreadPoolExecutor ? ((DynamicThreadPoolExecutor) actualExecutor).getRejectCountNum() : NO_REJECT_COUNT_NUM;
+ long rejectCount = NO_REJECT_COUNT_NUM;
+ if (Objects.equals(actualExecutor.getClass().getName(), "cn.hippo4j.core.executor.DynamicThreadPoolExecutor")) {
+ Object actualRejectCountNum = ReflectUtil.invoke(actualExecutor, "getRejectCountNum");
+ if (actualRejectCountNum != null) {
+ rejectCount = (long) actualRejectCountNum;
+ }
+ }
ThreadPoolRunStateInfo stateInfo = ThreadPoolRunStateInfo.builder()
.tpId(threadPoolId)
.activeSize(activeCount)
diff --git a/infra/common/src/main/java/cn/hippo4j/common/toolkit/CalculateUtil.java b/infra/common/src/main/java/cn/hippo4j/common/toolkit/CalculateUtil.java
index 1f80b8ef..cbb7c52d 100644
--- a/infra/common/src/main/java/cn/hippo4j/common/toolkit/CalculateUtil.java
+++ b/infra/common/src/main/java/cn/hippo4j/common/toolkit/CalculateUtil.java
@@ -19,9 +19,6 @@ package cn.hippo4j.common.toolkit;
/**
* Calculate util.
- *
- * @author chen.ma
- * @date 2021/8/15 14:29
*/
public class CalculateUtil {
diff --git a/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java b/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java
index 3be85745..fe8f0d3c 100644
--- a/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java
+++ b/infra/common/src/main/java/cn/hippo4j/common/toolkit/MessageConvert.java
@@ -24,18 +24,18 @@ import java.util.Map;
import cn.hippo4j.common.monitor.AbstractMessage;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.common.monitor.MessageWrapper;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
/**
* Message convert.
*/
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MessageConvert {
/**
* {@link Message} to {@link MessageWrapper}.
- *
- * @param message
- * @return
*/
public static MessageWrapper convert(Message message) {
MessageWrapper wrapper = new MessageWrapper();
@@ -54,9 +54,6 @@ public class MessageConvert {
/**
* {@link MessageWrapper} to {@link Message}.
- *
- * @param messageWrapper
- * @return
*/
@SneakyThrows
public static Message convert(MessageWrapper messageWrapper) {
diff --git a/infra/common/src/test/java/cn/hippo4j/common/executor/ThreadPoolExecutorUtilTest b/infra/common/src/test/java/cn/hippo4j/common/executor/ThreadPoolExecutorUtilTest
new file mode 100644
index 00000000..c3459d03
--- /dev/null
+++ b/infra/common/src/test/java/cn/hippo4j/common/executor/ThreadPoolExecutorUtilTest
@@ -0,0 +1,89 @@
+/*
+ * 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 cn.hippo4j.common.executor;
+
+import cn.hippo4j.common.toolkit.ThreadPoolExecutorUtil;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class ThreadPoolExecutorUtilTest {
+
+ private ThreadPoolExecutor executor;
+ private int corePoolSize;
+ private int maxPoolSize;
+
+ @Before
+ public void testSafeSetPoolSize() {
+ corePoolSize = 2;
+ maxPoolSize = 4;
+ executor = new ThreadPoolExecutor(
+ corePoolSize,
+ maxPoolSize,
+ 1L,
+ TimeUnit.SECONDS,
+ new ArrayBlockingQueue<>(10)
+ );
+ }
+
+ @Test
+ public void testEquals(){
+ // Test when the new core pool size equals the original maximum pool size.
+ int newCorePoolSize1 = maxPoolSize;
+ int newMaxPoolSize1 = 6;
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize1, newMaxPoolSize1);
+ Assert.assertEquals(newCorePoolSize1, executor.getCorePoolSize());
+ Assert.assertEquals(newMaxPoolSize1, executor.getMaximumPoolSize());
+ }
+
+ @Test
+ public void testGreater(){
+ // Test when the new core pool size is greater than the original maximum pool size.
+ int newCorePoolSize2 = 8;
+ int newMaxPoolSize2 = 10;
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize2, newMaxPoolSize2);
+ Assert.assertEquals(newCorePoolSize2, executor.getCorePoolSize());
+ Assert.assertEquals(newMaxPoolSize2, executor.getMaximumPoolSize());
+ }
+
+ @Test
+ public void testLess(){
+ // Test when the new core pool size is less than the original maximum pool size.
+ int newCorePoolSize3 = 3;
+ int newMaxPoolSize3 = 5;
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize3, newMaxPoolSize3);
+ Assert.assertEquals(newCorePoolSize3, executor.getCorePoolSize());
+ Assert.assertEquals(newMaxPoolSize3, executor.getMaximumPoolSize());
+ }
+
+ @Test
+ public void testException(){
+ // Test when the new core pool size is greater than the new maximum pool size, which should throw an IllegalArgumentException.
+ int newCorePoolSize4 = 6;
+ int newMaxPoolSize4 = 4;
+ try {
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize4, newMaxPoolSize4);
+ } catch (IllegalArgumentException e) {
+ // Expected to throw an exception.
+ Assert.assertEquals("newCorePoolSize must be smaller than newMaximumPoolSize", e.getMessage());
+ }
+ }
+}
diff --git a/infra/common/src/test/java/cn/hippo4j/common/executor/support/ThreadPoolExecutorUtilTest.java b/infra/common/src/test/java/cn/hippo4j/common/executor/support/ThreadPoolExecutorUtilTest.java
new file mode 100644
index 00000000..88f523bb
--- /dev/null
+++ b/infra/common/src/test/java/cn/hippo4j/common/executor/support/ThreadPoolExecutorUtilTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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 cn.hippo4j.common.executor.support;
+
+import cn.hippo4j.common.toolkit.ThreadPoolExecutorUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Thread pool executor util test
+ */
+@Slf4j
+public class ThreadPoolExecutorUtilTest {
+
+ private ThreadPoolExecutor executor;
+ private int corePoolSize;
+ private int maxPoolSize;
+
+ @Before
+ public void testSafeSetPoolSize() {
+ corePoolSize = 2;
+ maxPoolSize = 4;
+ executor = new ThreadPoolExecutor(
+ corePoolSize,
+ maxPoolSize,
+ 1L,
+ TimeUnit.SECONDS,
+ new ArrayBlockingQueue<>(10));
+ }
+
+ @Test
+ public void testEquals() {
+ // Test when the new core pool size equals the original maximum pool size.
+ int newCorePoolSize1 = maxPoolSize;
+ int newMaxPoolSize1 = 6;
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize1, newMaxPoolSize1);
+ Assert.assertEquals(newCorePoolSize1, executor.getCorePoolSize());
+ Assert.assertEquals(newMaxPoolSize1, executor.getMaximumPoolSize());
+ }
+
+ @Test
+ public void testGreater() {
+ // Test when the new core pool size is greater than the original maximum pool size.
+ int newCorePoolSize2 = 8;
+ int newMaxPoolSize2 = 10;
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize2, newMaxPoolSize2);
+ Assert.assertEquals(newCorePoolSize2, executor.getCorePoolSize());
+ Assert.assertEquals(newMaxPoolSize2, executor.getMaximumPoolSize());
+ }
+
+ @Test
+ public void testLess() {
+ // Test when the new core pool size is less than the original maximum pool size.
+ int newCorePoolSize3 = 3;
+ int newMaxPoolSize3 = 5;
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize3, newMaxPoolSize3);
+ Assert.assertEquals(newCorePoolSize3, executor.getCorePoolSize());
+ Assert.assertEquals(newMaxPoolSize3, executor.getMaximumPoolSize());
+ }
+
+ @Test
+ public void testException() {
+ // Test when the new core pool size is greater than the new maximum pool size, which should throw an IllegalArgumentException.
+ int newCorePoolSize4 = 6;
+ int newMaxPoolSize4 = 4;
+ try {
+ ThreadPoolExecutorUtil.safeSetPoolSize(executor, newCorePoolSize4, newMaxPoolSize4);
+ } catch (IllegalArgumentException e) {
+ // Expected to throw an exception.
+ Assert.assertEquals("newCorePoolSize must be smaller than newMaximumPoolSize", e.getMessage());
+ log.error("newCorePoolSize must be smaller than newMaximumPoolSize;{}", e.getMessage());
+ }
+ }
+}
diff --git a/infra/common/src/test/java/cn/hippo4j/common/toolkit/IoUtilTest.java b/infra/common/src/test/java/cn/hippo4j/common/toolkit/IoUtilTest.java
index 0f48c046..c9091285 100644
--- a/infra/common/src/test/java/cn/hippo4j/common/toolkit/IoUtilTest.java
+++ b/infra/common/src/test/java/cn/hippo4j/common/toolkit/IoUtilTest.java
@@ -49,6 +49,7 @@ import java.util.zip.GZIPOutputStream;
* test for {@link IoUtil}
*/
public class IoUtilTest {
+
private Path tempDir;
private File sourceFile;
diff --git a/infra/common/src/test/java/cn/hippo4j/common/toolkit/JacksonHandlerTest.java b/infra/common/src/test/java/cn/hippo4j/common/toolkit/JacksonHandlerTest.java
index 907a459c..3acec9fa 100644
--- a/infra/common/src/test/java/cn/hippo4j/common/toolkit/JacksonHandlerTest.java
+++ b/infra/common/src/test/java/cn/hippo4j/common/toolkit/JacksonHandlerTest.java
@@ -87,8 +87,7 @@ public class JacksonHandlerTest {
Assertions.assertEquals(
EXPECTED_ENTITY,
JACKSON_HANDLER.parseObject(EXPECTED_ENTITY_JSON, new TypeReference() {
- })
- );
+ }));
// illegal json
Assertions.assertThrows(MismatchedInputException.class,
() -> JACKSON_HANDLER.parseObject(" ", Entity.class));
diff --git a/infra/common/src/test/java/cn/hippo4j/common/toolkit/MessageConvertTest.java b/infra/common/src/test/java/cn/hippo4j/common/toolkit/MessageConvertTest.java
new file mode 100644
index 00000000..52470aad
--- /dev/null
+++ b/infra/common/src/test/java/cn/hippo4j/common/toolkit/MessageConvertTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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 cn.hippo4j.common.toolkit;
+
+import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
+import cn.hippo4j.common.monitor.*;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+/***
+ * @description : Todo
+ * @author : DDDreame
+ * @date : 2023/5/27 23:24
+ */
+public class MessageConvertTest {
+
+ @Test
+ public void testConvert() {
+ AbstractMessage message = new RuntimeMessage();
+ List runtimeMessages = new ArrayList<>();
+ ThreadPoolRunStateInfo poolRunState = ThreadPoolRunStateInfo.builder()
+ .tpId("testTPid")
+ .activeSize(4)
+ .poolSize(12)
+ .completedTaskCount(8L)
+ .largestPoolSize(12)
+ .currentLoad("6")
+ .clientLastRefreshTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
+ .peakLoad("20")
+ .queueSize(0)
+ .queueRemainingCapacity(512)
+ .rejectCount(0L)
+ .timestamp(System.currentTimeMillis())
+ .build();
+ RuntimeMessage runtimeMessage = BeanUtil.convert(poolRunState, RuntimeMessage.class);
+ runtimeMessage.setGroupKey("test-groupKeys");
+ runtimeMessages.add(runtimeMessage);
+
+ message.setMessageType(MessageTypeEnum.RUNTIME);
+ message.setMessages(runtimeMessages);
+ MessageWrapper messageWrapper = MessageConvert.convert(message);
+ Assertions.assertNotNull(messageWrapper);
+ }
+
+ @Test
+ public void testMessageWrapperConvert() {
+ AbstractMessage message = new RuntimeMessage();
+ List runtimeMessages = new ArrayList<>();
+ ThreadPoolRunStateInfo poolRunState = ThreadPoolRunStateInfo.builder()
+ .tpId("testTPid")
+ .activeSize(4)
+ .poolSize(12)
+ .completedTaskCount(8L)
+ .largestPoolSize(12)
+ .currentLoad("6")
+ .clientLastRefreshTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
+ .peakLoad("20")
+ .queueSize(0)
+ .queueRemainingCapacity(512)
+ .rejectCount(0L)
+ .timestamp(System.currentTimeMillis())
+ .build();
+ RuntimeMessage runtimeMessage = BeanUtil.convert(poolRunState, RuntimeMessage.class);
+ runtimeMessage.setGroupKey("test-groupKeys");
+ runtimeMessages.add(runtimeMessage);
+
+ message.setMessageType(MessageTypeEnum.RUNTIME);
+ message.setMessages(runtimeMessages);
+ MessageWrapper messageWrapper = MessageConvert.convert(message);
+ Message messageResult = MessageConvert.convert(messageWrapper);
+ Assertions.assertNotNull(messageResult);
+ Assertions.assertEquals(message, messageResult);
+ }
+
+ @Test
+ public void testMessageWrapperConvertException() {
+ Assertions.assertThrows(Exception.class, () -> {
+ Map data1 = new HashMap<>();
+ data1.put("key1", "value1");
+ data1.put("key2", 123);
+ Map data2 = new HashMap<>();
+ data2.put("key3", true);
+ data2.put("key4", 3.14);
+ List