[ISSUE #42] fix the problem HealthExcutor don't doCheck asynchronously (#43)
* fix: let HealthExecutor support async doCheck
* chore: move test files out of unit folder
* chore: add HealthConstant
* chore
* style: rewrite description assign in CheckResultCache in if-else
diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/constant/HealthConstant.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/constant/HealthConstant.java
new file mode 100644
index 0000000..979f578
--- /dev/null
+++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/constant/HealthConstant.java
@@ -0,0 +1,22 @@
+/*
+ * 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 org.apache.eventmesh.dashboard.console.constant;
+
+public class HealthConstant {
+ public static final String NEW_LINE_ENDING = "\n";
+}
diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/CheckResultCache.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/CheckResultCache.java
index 540e383..66dcd44 100644
--- a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/CheckResultCache.java
+++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/CheckResultCache.java
@@ -17,6 +17,7 @@
package org.apache.eventmesh.dashboard.console.health;
+import org.apache.eventmesh.dashboard.console.constant.HealthConstant;
import org.apache.eventmesh.dashboard.console.enums.health.HealthCheckStatus;
import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig;
@@ -41,8 +42,12 @@
cacheMap.put(type, subMap);
}
CheckResult oldResult = subMap.get(typeId);
- String oldDesc = Objects.isNull(oldResult.getResultDesc()) ? "" : oldResult.getResultDesc() + "\n";
- CheckResult result = new CheckResult(status, oldDesc + resultDesc, LocalDateTime.now(),
+ String description = resultDesc;
+ if (oldResult.getResultDesc() != null && !oldResult.getResultDesc().isEmpty()) {
+ description = oldResult.getResultDesc() + HealthConstant.NEW_LINE_ENDING + resultDesc;
+ }
+ description += " Latency: " + latency.toString() + "ms";
+ CheckResult result = new CheckResult(status, description, LocalDateTime.now(),
latency, oldResult.getConfig());
subMap.put(typeId, result);
}
@@ -53,7 +58,6 @@
subMap = new HashMap<>();
cacheMap.put(type, subMap);
}
- CheckResult resultToUpdate = subMap.get(typeId);
subMap.put(typeId, new CheckResult(status, resultDesc, LocalDateTime.now(), latency, config));
}
diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthExecutor.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthExecutor.java
index 765bdab..49d76e2 100644
--- a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthExecutor.java
+++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthExecutor.java
@@ -26,6 +26,8 @@
import org.apache.eventmesh.dashboard.console.service.health.HealthDataService;
import java.util.ArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import lombok.Getter;
import lombok.Setter;
@@ -44,6 +46,8 @@
@Setter
private CheckResultCache memoryCache;
+ private final ExecutorService executorService = Executors.newCachedThreadPool();
+
/**
* execute function is where health check services work.
*
@@ -58,7 +62,7 @@
memoryCache.update(service.getConfig().getHealthCheckResourceType(), service.getConfig().getInstanceId(), HealthCheckStatus.CHECKING, "",
null, service.getConfig());
//The callback interface is used to pass the processing methods for checking success and failure.
- service.doCheck(new HealthCheckCallback() {
+ executorService.submit(() -> service.doCheck(new HealthCheckCallback() {
@Override
public void onSuccess() {
//when the health check is successful, the result is updated to the memory cache.
@@ -66,7 +70,7 @@
HealthCheckStatus status =
latency > service.getConfig().getRequestTimeoutMillis() ? HealthCheckStatus.TIMEOUT : HealthCheckStatus.PASSED;
memoryCache.update(service.getConfig().getHealthCheckResourceType(), service.getConfig().getInstanceId(),
- status, "health check success", latency
+ status, "Health check succeed.", latency
);
}
@@ -78,7 +82,8 @@
HealthCheckStatus.FAILED, e.getMessage(),
System.currentTimeMillis() - startTime);
}
- });
+ }));
+
} catch (Exception e) {
log.error("Health check failed for reason: {}. Service config is {}", e, service.getConfig());
memoryCache.update(service.getConfig().getHealthCheckResourceType(), service.getConfig().getInstanceId(), HealthCheckStatus.FAILED,
diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthService.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthService.java
index 39485e1..333fa99 100644
--- a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthService.java
+++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthService.java
@@ -68,7 +68,7 @@
*
* @see AbstractHealthCheckService
*/
- private Map<String, Map<Long, AbstractHealthCheckService>> checkServiceMap = new ConcurrentHashMap<>();
+ private final Map<String, Map<Long, AbstractHealthCheckService>> checkServiceMap = new ConcurrentHashMap<>();
private ScheduledThreadPoolExecutor scheduledExecutor;
@@ -87,10 +87,13 @@
if (Objects.nonNull(config.getSimpleClassName())) {
Class<?> clazz = HEALTH_CHECK_CLASS_CACHE.get(config.getSimpleClassName());
healthCheckService = createCheckService(clazz, config);
- //if simpleClassName is null, use type(storage) and subType(redis) to create healthCheckService
+ // you can pass an object to create a HealthCheckService(not commonly used)
+ } else if (Objects.nonNull(config.getCheckClass())) {
+ healthCheckService = createCheckService(config.getCheckClass(), config);
+ //if simpleClassName and CheckClass are both null, use type(storage) and subType(redis) to create healthCheckService
+ //This is the default create method.
//healthCheckService is annotated with @HealthCheckType(type = "storage", subType = "redis")
- } else if (Objects.isNull(config.getSimpleClassName())
- && Objects.nonNull(config.getHealthCheckResourceType()) && Objects.nonNull(
+ } else if (Objects.nonNull(config.getHealthCheckResourceType()) && Objects.nonNull(
config.getHealthCheckResourceSubType())) {
for (Entry<String, Class<?>> entry : HEALTH_CHECK_CLASS_CACHE.entrySet()) {
Class<?> clazz = entry.getValue();
@@ -101,9 +104,6 @@
break;
}
}
- // you can pass an object to create a HealthCheckService(not commonly used)
- } else if (Objects.nonNull(config.getCheckClass())) {
- healthCheckService = createCheckService(config.getCheckClass(), config);
}
} catch (Exception e) {
log.error("create healthCheckService failed, healthCheckObjectConfig:{}", config, e);
@@ -113,6 +113,13 @@
if (Objects.isNull(healthCheckService)) {
throw new RuntimeException("No construct method of Health Check Service is found, config is {}" + config);
}
+ insertCheckService(healthCheckService);
+ }
+
+ public void insertCheckService(AbstractHealthCheckService checkService) {
+ Map<Long, AbstractHealthCheckService> subMap = checkServiceMap.computeIfAbsent(checkService.getConfig().getHealthCheckResourceType(),
+ k -> new ConcurrentHashMap<>());
+ subMap.put(checkService.getConfig().getInstanceId(), checkService);
}
public void deleteCheckService(String resourceType, Long resourceId) {
diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/config/HealthCheckObjectConfig.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/config/HealthCheckObjectConfig.java
index c33931b..8c350b4 100644
--- a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/config/HealthCheckObjectConfig.java
+++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/config/HealthCheckObjectConfig.java
@@ -17,6 +17,8 @@
package org.apache.eventmesh.dashboard.console.health.check.config;
+import java.util.Properties;
+
import lombok.Data;
@Data
@@ -32,6 +34,8 @@
private Class<?> checkClass;
+ private Properties eventmeshProperties;
+
private Long clusterId;
private String connectUrl;
diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheck.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheck.java
index dcf0582..00cfad8 100644
--- a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheck.java
+++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheck.java
@@ -77,6 +77,6 @@
}
redisUrl = builder.build().toString();
}
- RedisClient redisClient = RedisClient.create(redisUrl);
+ redisClient = RedisClient.create(redisUrl);
}
}
diff --git a/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthExecutorTest.java b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthExecutorTest.java
index c2bc178..2c5e49c 100644
--- a/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthExecutorTest.java
+++ b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthExecutorTest.java
@@ -113,9 +113,10 @@
}
@Test
- public void testExecute() {
+ public void testExecute() throws InterruptedException {
healthExecutor.execute(successHealthCheckService);
healthExecutor.execute(failHealthCheckService);
+ Thread.sleep(1000);
assertEquals(2, memoryCache.getCacheMap().get("storage").size());
assertNotEquals(memoryCache.getCacheMap().get("storage").get(1L).getStatus(), memoryCache.getCacheMap().get("storage").get(2L).getStatus());
}
diff --git a/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthServiceTest.java b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthServiceTest.java
index 278852f..06343fd 100644
--- a/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthServiceTest.java
+++ b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthServiceTest.java
@@ -17,8 +17,6 @@
package org.apache.eventmesh.dashboard.console.health;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
import org.apache.eventmesh.dashboard.console.health.callback.HealthCheckCallback;
import org.apache.eventmesh.dashboard.console.health.check.AbstractHealthCheckService;
import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig;
@@ -60,6 +58,8 @@
HealthCheckObjectConfig config = new HealthCheckObjectConfig();
config.setInstanceId(1L);
config.setSimpleClassName("StorageRedisCheck");
+ config.setHealthCheckResourceType("storage");
+ config.setHealthCheckResourceSubType("redis");
config.setClusterId(1L);
config.setConnectUrl("redis://localhost:6379");
healthService.insertCheckService(config);
@@ -69,6 +69,8 @@
void testInsertCheckServiceWithClass() {
HealthCheckObjectConfig config = new HealthCheckObjectConfig();
config.setInstanceId(1L);
+ config.setHealthCheckResourceType("storage");
+ config.setHealthCheckResourceSubType("redis");
config.setClusterId(1L);
config.setCheckClass(TestHealthCheckService.class);
healthService.insertCheckService(config);
diff --git a/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/integration/health/HealthServiceIntegrateTest.java b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/integration/health/HealthServiceIntegrateTest.java
new file mode 100644
index 0000000..7afb52f
--- /dev/null
+++ b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/integration/health/HealthServiceIntegrateTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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 org.apache.eventmesh.dashboard.console.integration.health;
+
+import java.util.List;
+import org.apache.eventmesh.dashboard.console.entity.health.HealthCheckResultEntity;
+import org.apache.eventmesh.dashboard.console.enums.health.HealthCheckType;
+import org.apache.eventmesh.dashboard.console.health.CheckResultCache;
+import org.apache.eventmesh.dashboard.console.health.HealthService;
+import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig;
+import org.apache.eventmesh.dashboard.console.service.health.HealthDataService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.jdbc.Sql;
+
+@SpringBootTest
+@ActiveProfiles("test")
+@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = {"classpath:use-test-schema.sql", "classpath:eventmesh-dashboard.sql"})
+public class HealthServiceIntegrateTest {
+ HealthService healthService = new HealthService();
+
+ @Autowired
+ private HealthDataService healthDataService;
+
+ private final CheckResultCache checkResultCache = new CheckResultCache();
+ @BeforeEach
+ void init() {
+ healthService.createExecutor(healthDataService, checkResultCache);
+ }
+
+ @Test
+ void testStorageRedis() throws InterruptedException {
+ HealthCheckObjectConfig config = new HealthCheckObjectConfig();
+ config.setClusterId(1L);
+ config.setInstanceId(1L);
+ config.setHealthCheckResourceType("storage");
+ config.setHealthCheckResourceSubType("redis");
+ config.setConnectUrl("redis://localhost:6379");
+ healthService.insertCheckService(config);
+ healthService.executeAll();
+ Thread.sleep(1000);
+ healthService.executeAll();
+
+ HealthCheckResultEntity queryEntity = new HealthCheckResultEntity();
+ queryEntity.setClusterId(1L);
+ queryEntity.setType(HealthCheckType.STORAGE.getNumber());
+ queryEntity.setTypeId(1L);
+ List<HealthCheckResultEntity> results = healthDataService.queryHealthCheckResultByClusterIdAndTypeAndTypeId(queryEntity);
+ Assertions.assertEquals(2,results.size());
+ }
+}
diff --git a/pom.xml b/pom.xml
index 59cb187..68372bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -135,6 +135,17 @@
</execution>
</executions>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>3.2.2</version>
+ <configuration>
+ <excludes>
+ <exclude>**/org/apache/eventmesh/dashboard/console/integration/**/*.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
\ No newline at end of file