diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/config/SchedulerConfig.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/config/HealthCheckConfig.java similarity index 66% rename from eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/config/SchedulerConfig.java rename to eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/config/HealthCheckConfig.java index aba415a4..8588311c 100644 --- a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/config/SchedulerConfig.java +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/config/HealthCheckConfig.java @@ -17,17 +17,15 @@ package org.apache.eventmesh.dashboard.console.config; -import org.springframework.context.annotation.Bean; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.stereotype.Component; +import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig; -@Component -public class SchedulerConfig { +import java.util.List; - @Bean - public ThreadPoolTaskScheduler taskScheduler() { - ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); - taskScheduler.setPoolSize(5); - return taskScheduler; - } +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class HealthCheckConfig { + private List checkObjectConfigList; } 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 new file mode 100644 index 00000000..540e3832 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/CheckResultCache.java @@ -0,0 +1,90 @@ +/* + * 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.health; + +import org.apache.eventmesh.dashboard.console.enums.health.HealthCheckStatus; +import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +public class CheckResultCache { + + private final HashMap> cacheMap = new HashMap<>(); + + public void update(String type, Long typeId, HealthCheckStatus status, String resultDesc, Long latency) { + HashMap subMap = cacheMap.get(type); + if (Objects.isNull(subMap)) { + subMap = new HashMap<>(); + 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(), + latency, oldResult.getConfig()); + subMap.put(typeId, result); + } + + public void update(String type, Long typeId, HealthCheckStatus status, String resultDesc, Long latency, HealthCheckObjectConfig config) { + HashMap subMap = cacheMap.get(type); + if (Objects.isNull(subMap)) { + subMap = new HashMap<>(); + cacheMap.put(type, subMap); + } + CheckResult resultToUpdate = subMap.get(typeId); + subMap.put(typeId, new CheckResult(status, resultDesc, LocalDateTime.now(), latency, config)); + } + + public Map> getCacheMap() { + return Collections.unmodifiableMap(cacheMap); + } + + @Getter + @AllArgsConstructor + public class CheckResult { + + /** + * the status of a health check. + * + * @see HealthCheckStatus + */ + @Setter + private HealthCheckStatus status; + /** + * if not passed, this field is used to store some description. + */ + private String resultDesc; + /** + * the time this record is inserted into memory map. + */ + private LocalDateTime createTime; + /** + * latency of a health check, for example ping latency. + */ + private Long latencyMilliSeconds; + + private HealthCheckObjectConfig 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 new file mode 100644 index 00000000..765bdab9 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthExecutor.java @@ -0,0 +1,140 @@ +/* + * 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.health; + +import org.apache.eventmesh.dashboard.console.entity.health.HealthCheckResultEntity; +import org.apache.eventmesh.dashboard.console.enums.health.HealthCheckStatus; +import org.apache.eventmesh.dashboard.console.enums.health.HealthCheckType; +import org.apache.eventmesh.dashboard.console.health.CheckResultCache.CheckResult; +import org.apache.eventmesh.dashboard.console.health.callback.HealthCheckCallback; +import org.apache.eventmesh.dashboard.console.health.check.AbstractHealthCheckService; +import org.apache.eventmesh.dashboard.console.service.health.HealthDataService; + +import java.util.ArrayList; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class HealthExecutor { + + @Setter + private HealthDataService dataService; + + /** + * memory cache is used to store real-time health check result. + */ + @Getter + @Setter + private CheckResultCache memoryCache; + + /** + * execute function is where health check services work. + * + * @param service The health check service to be executed. + */ + + public void execute(AbstractHealthCheckService service) { + final long startTime = System.currentTimeMillis(); + //TODO: execute is called by a ScheduledThreadPoolExecutor, + // when called, it should check if current service should doCheck(check service check rate can be dynamically configured). + try { + 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() { + @Override + public void onSuccess() { + //when the health check is successful, the result is updated to the memory cache. + Long latency = System.currentTimeMillis() - startTime; + HealthCheckStatus status = + latency > service.getConfig().getRequestTimeoutMillis() ? HealthCheckStatus.TIMEOUT : HealthCheckStatus.PASSED; + memoryCache.update(service.getConfig().getHealthCheckResourceType(), service.getConfig().getInstanceId(), + status, "health check success", latency + ); + } + + @Override + public void onFail(Exception e) { + //when the health check fails, the result is updated to the memory cache, passing in the exception message. + log.error("Health check failed for reason: {}. Service config is {}", e, service.getConfig()); + memoryCache.update(service.getConfig().getHealthCheckResourceType(), service.getConfig().getInstanceId(), + 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, + e.getMessage(), + System.currentTimeMillis() - startTime); + } + } + + /** + * this function should be called before any actual execute behaviour.
It will check the execution result of the last check cycle in the + * memory cache, set tasks that haven't finished status to time out and update the database. + */ + public void startExecute() { + ArrayList resultList = new ArrayList<>(); + memoryCache.getCacheMap().forEach((type, subMap) -> { + subMap.forEach((instanceId, result) -> { + if (result.getStatus() == HealthCheckStatus.CHECKING) { + result.setStatus(HealthCheckStatus.TIMEOUT); + } + addToResultList(result, resultList); + }); + }); + if (!resultList.isEmpty()) { + dataService.batchUpdateCheckResultByClusterIdAndTypeAndTypeId(resultList); + } + } + + /** + * this function should be called after all actual execute behaviour.
It will insert the result of this check cycle into the database. At this + * point the status of the tasks may be CHECKING, they will be updated on the next startExecute. + */ + public void endExecute() { + ArrayList resultList = new ArrayList<>(); + memoryCache.getCacheMap().forEach((type, subMap) -> { + subMap.forEach((instanceId, result) -> { + addToResultList(result, resultList); + }); + }); + dataService.batchInsertHealthCheckResult(resultList); + } + + /** + * Helper function to add a CheckResult to the resultList. + * + * @param result memory cached result object. + * @param resultList entity list to be inserted into the database. + */ + private void addToResultList(CheckResult result, ArrayList resultList) { + HealthCheckResultEntity newEntity = new HealthCheckResultEntity(); + newEntity.setClusterId(result.getConfig().getClusterId()); + newEntity.setType(HealthCheckType.toNumber(result.getConfig().getHealthCheckResourceType())); + newEntity.setTypeId(result.getConfig().getInstanceId()); + newEntity.setResultDesc(result.getResultDesc()); + newEntity.setStatus(result.getStatus().getNumber()); + + resultList.add(newEntity); + } + +} 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 new file mode 100644 index 00000000..39485e19 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/HealthService.java @@ -0,0 +1,172 @@ +/* + * 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.health; + +import org.apache.eventmesh.dashboard.console.health.CheckResultCache.CheckResult; +import org.apache.eventmesh.dashboard.console.health.annotation.HealthCheckType; +import org.apache.eventmesh.dashboard.console.health.check.AbstractHealthCheckService; +import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig; +import org.apache.eventmesh.dashboard.console.health.check.impl.StorageRedisCheck; +import org.apache.eventmesh.dashboard.console.service.health.HealthDataService; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import lombok.extern.slf4j.Slf4j; + +/** + * HealthService is the manager of all health check services. It is responsible for creating, deleting and executing health check services.
In + * this class there is a {@link HealthExecutor} which is used to execute health check services, and also a map to store all health check services. + * when the function executeAll is called, health check service will be executed by {@link HealthExecutor}. + */ +@Slf4j +public class HealthService { + + private HealthExecutor healthExecutor; + + /** + * class cache used to build healthCheckService instance.
key: HealthCheckObjectConfig.SimpleClassName value: HealthCheckService + * + * @see HealthCheckObjectConfig + */ + private static final Map> HEALTH_CHECK_CLASS_CACHE = new HashMap<>(); + + static { + setClassCache(StorageRedisCheck.class); + } + + private static void setClassCache(Class clazz) { + HEALTH_CHECK_CLASS_CACHE.put(clazz.getSimpleName(), clazz); + } + + /** + * This map is used to store HealthExecutor.
Outside key is Type(runtime, storage etc.), inside key is the id of type instance(runtimeId, + * storageId etc.). + * + * @see AbstractHealthCheckService + */ + private Map> checkServiceMap = new ConcurrentHashMap<>(); + + private ScheduledThreadPoolExecutor scheduledExecutor; + + public Map> getCheckResultCacheMap() { + return healthExecutor.getMemoryCache().getCacheMap(); + } + + public void insertCheckService(List configList) { + configList.forEach(this::insertCheckService); + } + + public void insertCheckService(HealthCheckObjectConfig config) { + AbstractHealthCheckService healthCheckService = null; + + try { + 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 + //healthCheckService is annotated with @HealthCheckType(type = "storage", subType = "redis") + } else if (Objects.isNull(config.getSimpleClassName()) + && Objects.nonNull(config.getHealthCheckResourceType()) && Objects.nonNull( + config.getHealthCheckResourceSubType())) { + for (Entry> entry : HEALTH_CHECK_CLASS_CACHE.entrySet()) { + Class clazz = entry.getValue(); + HealthCheckType annotation = clazz.getAnnotation(HealthCheckType.class); + if (annotation != null && annotation.type().equals(config.getHealthCheckResourceType()) && annotation.subType() + .equals(config.getHealthCheckResourceSubType())) { + healthCheckService = createCheckService(clazz, config); + 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); + } + + // if all above creation method failed + if (Objects.isNull(healthCheckService)) { + throw new RuntimeException("No construct method of Health Check Service is found, config is {}" + config); + } + } + + public void deleteCheckService(String resourceType, Long resourceId) { + Map subMap = checkServiceMap.get(resourceType); + if (Objects.isNull(subMap)) { + return; + } + subMap.remove(resourceId); + if (subMap.isEmpty()) { + checkServiceMap.remove(resourceType); + } + } + + + public void createExecutor(HealthDataService dataService, CheckResultCache cache) { + healthExecutor = new HealthExecutor(); + healthExecutor.setDataService(dataService); + healthExecutor.setMemoryCache(cache); + } + + public void executeAll() { + healthExecutor.startExecute(); + + checkServiceMap.forEach((type, subMap) -> { + subMap.forEach((typeId, healthCheckService) -> { + healthExecutor.execute(healthCheckService); + }); + }); + + healthExecutor.endExecute(); + } + + private AbstractHealthCheckService createCheckService(Class clazz, HealthCheckObjectConfig config) + throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + Constructor constructor = clazz.getConstructor(HealthCheckObjectConfig.class); + return (AbstractHealthCheckService) constructor.newInstance(config); + } + + /** + * start scheduled execution of health check services + * + * @param initialDelay unit is second + * @param period unit is second + */ + public void startScheduledExecution(long initialDelay, long period) { + if (scheduledExecutor == null) { + scheduledExecutor = new ScheduledThreadPoolExecutor(1); + } + scheduledExecutor.scheduleAtFixedRate(this::executeAll, initialDelay, period, TimeUnit.SECONDS); + } + + public void stopScheduledExecution() { + if (scheduledExecutor != null) { + scheduledExecutor.shutdown(); + } + } +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/annotation/HealthCheckType.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/annotation/HealthCheckType.java new file mode 100644 index 00000000..6f396581 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/annotation/HealthCheckType.java @@ -0,0 +1,41 @@ +/* + * 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.health.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used to mark the type of health check service implement. + * @see org.apache.eventmesh.dashboard.console.enums.health.HealthCheckType + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface HealthCheckType { + /** + * type of resource. runtime, topic etc. + */ + String type(); + + /** + * subtype of resource. For resource storage, it can be redis, rocketmq etc. + */ + String subType() default ""; +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/callback/HealthCheckCallback.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/callback/HealthCheckCallback.java new file mode 100644 index 00000000..7f7b3608 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/callback/HealthCheckCallback.java @@ -0,0 +1,30 @@ +/* + * 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.health.callback; + +import org.apache.eventmesh.dashboard.console.health.HealthExecutor; + +/** + * Callback used by HealthService.doCheck to notify the caller of the result of the health check.
+ * @see HealthExecutor + */ +public interface HealthCheckCallback { + public void onSuccess(); + + public void onFail(Exception e); +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/AbstractHealthCheckService.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/AbstractHealthCheckService.java new file mode 100644 index 00000000..6fa7045d --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/AbstractHealthCheckService.java @@ -0,0 +1,37 @@ +/* + * 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.health.check; + +import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig; + +import lombok.Getter; + +/** + * extends + */ +@Getter +public abstract class AbstractHealthCheckService implements HealthCheckService { + + private final HealthCheckObjectConfig config; + + public AbstractHealthCheckService(HealthCheckObjectConfig healthCheckObjectConfig) { + this.config = healthCheckObjectConfig; + this.init(); + } + +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/HealthCheckService.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/HealthCheckService.java new file mode 100644 index 00000000..8f373632 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/HealthCheckService.java @@ -0,0 +1,39 @@ +/* + * 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.health.check; + +import org.apache.eventmesh.dashboard.console.health.HealthExecutor; +import org.apache.eventmesh.dashboard.console.health.callback.HealthCheckCallback; + +/** + * Health check service interface.
+ * To add a new check service, extend the {@link AbstractHealthCheckService}. + * @see AbstractHealthCheckService + */ +public interface HealthCheckService { + + /** + * Do the health check.
+ * To implement a new check service, add the necessary logic to call the success and fail functions of the callback. + * @param callback The behaviour of the callback is defined as a lambda function when used. Please refer to {@link HealthExecutor} for usage. + */ + public void doCheck(HealthCheckCallback callback); + + public void init(); + +} 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 new file mode 100644 index 00000000..c33931b8 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/config/HealthCheckObjectConfig.java @@ -0,0 +1,51 @@ +/* + * 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.health.check.config; + +import lombok.Data; + +@Data +public class HealthCheckObjectConfig { + + private Long instanceId; + + private String healthCheckResourceType; + + private String healthCheckResourceSubType; + + private String simpleClassName; + + private Class checkClass; + + private Long clusterId; + + private String connectUrl; + //mysql, redis + private String host; + + private Integer port; + + private String username; + + private String password; + + //mysql, redis + private String database; + + private Long requestTimeoutMillis = Long.MAX_VALUE; +} \ No newline at end of file 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 new file mode 100644 index 00000000..dcf05827 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheck.java @@ -0,0 +1,82 @@ +/* + * 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.health.check.impl; + +import org.apache.eventmesh.dashboard.console.health.annotation.HealthCheckType; +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; + +import java.time.Duration; +import java.util.Objects; + +import io.lettuce.core.RedisClient; +import io.lettuce.core.RedisURI; +import io.lettuce.core.RedisURI.Builder; +import io.lettuce.core.api.async.RedisAsyncCommands; + + +@HealthCheckType(type = "storage", subType = "redis") +public class StorageRedisCheck extends AbstractHealthCheckService { + + private RedisClient redisClient; + + public StorageRedisCheck(HealthCheckObjectConfig healthCheckObjectConfig) { + super(healthCheckObjectConfig); + } + + @Override + public void doCheck(HealthCheckCallback callback) { + try { + RedisAsyncCommands commands = redisClient.connect().async(); + commands.ping().thenAccept(result -> { + callback.onSuccess(); + }).exceptionally(e -> { + if (e instanceof Exception) { + callback.onFail((Exception) e); + } else { + callback.onFail(new RuntimeException("RedisCheck failed.")); + } + return null; + }); + } catch (Exception e) { + callback.onFail(e); + } + } + + @Override + public void init() { + String redisUrl; + if (Objects.nonNull(getConfig().getConnectUrl()) && !getConfig().getConnectUrl().isEmpty()) { + redisUrl = getConfig().getConnectUrl(); + } else { + Builder builder = RedisURI.Builder.redis(getConfig().getHost(), getConfig().getPort()); + if (Objects.nonNull(getConfig().getUsername()) && Objects.nonNull(getConfig().getPassword())) { + builder.withAuthentication(getConfig().getUsername(), getConfig().getPassword()); + } + if (Objects.nonNull(getConfig().getRequestTimeoutMillis())) { + builder.withTimeout(Duration.ofMillis(getConfig().getRequestTimeoutMillis())); + } + if (Objects.nonNull(getConfig().getDatabase())) { + builder.withDatabase(Integer.parseInt(getConfig().getDatabase())); + } + redisUrl = builder.build().toString(); + } + RedisClient redisClient = RedisClient.create(redisUrl); + } +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRocketmqCheck.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRocketmqCheck.java new file mode 100644 index 00000000..b6f56b8a --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRocketmqCheck.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.health.check.impl; + +public class StorageRocketmqCheck { + +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManager.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManager.java new file mode 100644 index 00000000..50f5efb0 --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManager.java @@ -0,0 +1,48 @@ +/* + * 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.spring.support; + +import org.apache.eventmesh.dashboard.console.health.CheckResultCache; +import org.apache.eventmesh.dashboard.console.health.HealthService; +import org.apache.eventmesh.dashboard.console.service.health.HealthDataService; + +import lombok.Getter; +import lombok.Setter; + +/** + * FunctionManager is in charge of tasks such as scheduled health checks + */ +public class FunctionManager { + + @Setter + private FunctionManagerProperties properties; + + @Getter + private HealthService healthService; + + @Setter + private HealthDataService healthDataService; + + public void initFunctionManager() { + // HealthService Initialization + healthService = new HealthService(); + CheckResultCache checkResultCache = new CheckResultCache(); + healthService.createExecutor(healthDataService, checkResultCache); + healthService.startScheduledExecution(5, 5); + } +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManagerLoader.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManagerLoader.java new file mode 100644 index 00000000..405cedcc --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManagerLoader.java @@ -0,0 +1,51 @@ +/* + * 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.spring.support; + +import org.apache.eventmesh.dashboard.console.health.HealthService; +import org.apache.eventmesh.dashboard.console.service.health.HealthDataService; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +@Component +public class FunctionManagerLoader { + + private FunctionManager functionManager; + + private FunctionManagerProperties properties; + + @Autowired + private HealthDataService healthDataService; + + @Bean + public HealthService getHealthService() { + return functionManager.getHealthService(); + } + + @PostConstruct + void initManager() { + functionManager = new FunctionManager(); + functionManager.setProperties(properties); + functionManager.setHealthDataService(healthDataService); + functionManager.initFunctionManager(); + } +} diff --git a/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManagerProperties.java b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManagerProperties.java new file mode 100644 index 00000000..5709dc1f --- /dev/null +++ b/eventmesh-dashboard-console/src/main/java/org/apache/eventmesh/dashboard/console/spring/support/FunctionManagerProperties.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.spring.support; + +public class FunctionManagerProperties { + +} 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 new file mode 100644 index 00000000..c2bc1780 --- /dev/null +++ b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthExecutorTest.java @@ -0,0 +1,182 @@ +/* + * 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.health; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; + +import java.util.concurrent.CompletableFuture; +import org.apache.eventmesh.dashboard.console.EventMeshDashboardApplication; +import org.apache.eventmesh.dashboard.console.entity.health.HealthCheckResultEntity; +import org.apache.eventmesh.dashboard.console.enums.health.HealthCheckStatus; +import org.apache.eventmesh.dashboard.console.enums.health.HealthCheckType; +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; +import org.apache.eventmesh.dashboard.console.service.health.impl.HealthDataServiceDatabaseImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.stubbing.Answer; +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; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(MockitoExtension.class) +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = EventMeshDashboardApplication.class) +@ActiveProfiles("test") +@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = {"classpath:use-test-schema.sql", "classpath:eventmesh-dashboard.sql"}) +class HealthExecutorTest { + + private HealthExecutor healthExecutor = new HealthExecutor(); + private CheckResultCache memoryCache = new CheckResultCache(); + + @Autowired + HealthDataServiceDatabaseImpl healthDataService; + + @Mock + AbstractHealthCheckService successHealthCheckService; + + @Mock + AbstractHealthCheckService failHealthCheckService; + + @Mock + AbstractHealthCheckService timeoutHealthCheckService; + + @BeforeEach + public void initMock() { + Mockito.lenient().doAnswer((Answer) invocation -> { + HealthCheckCallback callback = invocation.getArgument(0); + callback.onSuccess(); + return null; + }).when(successHealthCheckService).doCheck(any(HealthCheckCallback.class)); + Mockito.lenient().doAnswer((Answer) invocation -> { + HealthCheckCallback callback = invocation.getArgument(0); + callback.onFail(new RuntimeException("TestRuntimeException")); + return null; + }).when(failHealthCheckService).doCheck(any(HealthCheckCallback.class)); + Mockito.lenient().doAnswer((Answer) invocation -> { + HealthCheckCallback callback = invocation.getArgument(0); + CompletableFuture.runAsync(() -> { + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + return; + } + callback.onFail(new RuntimeException("TestRuntimeException")); + }); + return null; + }).when(timeoutHealthCheckService).doCheck(any(HealthCheckCallback.class)); + + healthExecutor.setDataService(healthDataService); + healthExecutor.setMemoryCache(memoryCache); + HealthCheckObjectConfig config1 = new HealthCheckObjectConfig(); + config1.setInstanceId(1L); + config1.setHealthCheckResourceType("storage"); + config1.setHealthCheckResourceSubType("redis"); + config1.setConnectUrl("redis://localhost:6379"); + config1.setSimpleClassName("StorageRedisCheck"); + config1.setClusterId(1L); + Mockito.lenient().when(successHealthCheckService.getConfig()).thenReturn(config1); + Mockito.lenient().when(timeoutHealthCheckService.getConfig()).thenReturn(config1); + HealthCheckObjectConfig config2 = new HealthCheckObjectConfig(); + config2.setInstanceId(2L); + config2.setHealthCheckResourceType("storage"); + config2.setHealthCheckResourceSubType("redis"); + config2.setConnectUrl("redis://localhost:6379"); + config2.setSimpleClassName("StorageRedisCheck"); + config2.setClusterId(1L); + Mockito.lenient().when(failHealthCheckService.getConfig()).thenReturn(config2); + } + + @Test + public void testExecute() { + healthExecutor.execute(successHealthCheckService); + healthExecutor.execute(failHealthCheckService); + assertEquals(2, memoryCache.getCacheMap().get("storage").size()); + assertNotEquals(memoryCache.getCacheMap().get("storage").get(1L).getStatus(), memoryCache.getCacheMap().get("storage").get(2L).getStatus()); + } + + + @Test + public void testEndExecute() { + healthExecutor.execute(successHealthCheckService); + healthExecutor.execute(failHealthCheckService); + healthExecutor.endExecute(); + HealthCheckResultEntity query = new HealthCheckResultEntity(); + query.setClusterId(1L); + query.setType(HealthCheckType.STORAGE.getNumber()); + query.setTypeId(2L); + assertNotNull(healthDataService.queryHealthCheckResultByClusterIdAndTypeAndTypeId(query).get(0).getStatus()); + } + + @Test + public void testStartExecute() { + healthExecutor.execute(successHealthCheckService); + healthExecutor.execute(failHealthCheckService); + //to test startExecute(), we need to call endExecute() first + healthExecutor.endExecute(); + healthExecutor.startExecute(); + HealthCheckResultEntity query = new HealthCheckResultEntity(); + query.setClusterId(1L); + query.setType(HealthCheckType.STORAGE.getNumber()); + query.setTypeId(1L); + assertEquals(1, healthDataService.queryHealthCheckResultByClusterIdAndTypeAndTypeId(query).get(0).getStatus()); + } + + @Test + public void testTimeout() { + healthExecutor.execute(timeoutHealthCheckService); + healthExecutor.endExecute(); + healthExecutor.startExecute(); + + HealthCheckResultEntity query = new HealthCheckResultEntity(); + query.setClusterId(1L); + query.setType(HealthCheckType.STORAGE.getNumber()); + query.setTypeId(1L); + assertEquals(HealthCheckStatus.TIMEOUT.getNumber(), + healthDataService.queryHealthCheckResultByClusterIdAndTypeAndTypeId(query).get(0).getStatus()); + } + + @Test + public void testFull() throws InterruptedException { + healthExecutor.startExecute(); + healthExecutor.execute(successHealthCheckService); + healthExecutor.execute(failHealthCheckService); + healthExecutor.endExecute(); + Thread.sleep(1000); + healthExecutor.startExecute(); + healthExecutor.execute(successHealthCheckService); + healthExecutor.execute(failHealthCheckService); + healthExecutor.endExecute(); + HealthCheckResultEntity query = new HealthCheckResultEntity(); + query.setClusterId(1L); + query.setType(HealthCheckType.STORAGE.getNumber()); + query.setTypeId(1L); + assertEquals(2, healthDataService.queryHealthCheckResultByClusterIdAndTypeAndTypeId(query).size()); + } + +} \ No newline at end of file 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 new file mode 100644 index 00000000..278852fa --- /dev/null +++ b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/HealthServiceTest.java @@ -0,0 +1,116 @@ +/* + * 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.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; +import org.apache.eventmesh.dashboard.console.service.health.HealthDataService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class HealthServiceTest { + + HealthService healthService = new HealthService(); + + @Mock + private HealthDataService healthDataService; + + @Mock + private CheckResultCache checkResultCache; + + @BeforeEach + void init() { + healthService.createExecutor(healthDataService, checkResultCache); + } + + @Test + void testInsertCheckServiceWithAnnotation() { + HealthCheckObjectConfig config = new HealthCheckObjectConfig(); + config.setInstanceId(2L); + config.setHealthCheckResourceType("storage"); + config.setHealthCheckResourceSubType("redis"); + config.setConnectUrl("redis://localhost:6379"); + healthService.insertCheckService(config); + } + + @Test + void testInsertCheckServiceWithSimpleClassName() { + HealthCheckObjectConfig config = new HealthCheckObjectConfig(); + config.setInstanceId(1L); + config.setSimpleClassName("StorageRedisCheck"); + config.setClusterId(1L); + config.setConnectUrl("redis://localhost:6379"); + healthService.insertCheckService(config); + } + + @Test + void testInsertCheckServiceWithClass() { + HealthCheckObjectConfig config = new HealthCheckObjectConfig(); + config.setInstanceId(1L); + config.setClusterId(1L); + config.setCheckClass(TestHealthCheckService.class); + healthService.insertCheckService(config); + } + + @Test + void testDeleteCheckService() { + HealthCheckObjectConfig config = new HealthCheckObjectConfig(); + config.setInstanceId(1L); + config.setHealthCheckResourceType("storage"); + config.setClusterId(1L); + config.setCheckClass(TestHealthCheckService.class); + healthService.insertCheckService(config); + healthService.deleteCheckService("storage", 1L); + } + + @Test + void testExecuteAll(){ + HealthCheckObjectConfig config = new HealthCheckObjectConfig(); + config.setInstanceId(1L); + config.setHealthCheckResourceType("storage"); + config.setClusterId(1L); + config.setCheckClass(TestHealthCheckService.class); + healthService.insertCheckService(config); + healthService.executeAll(); + } + + public static class TestHealthCheckService extends AbstractHealthCheckService { + + + public TestHealthCheckService(HealthCheckObjectConfig healthCheckObjectConfig) { + super(healthCheckObjectConfig); + } + + @Override + public void doCheck(HealthCheckCallback callback) { + callback.onSuccess(); + } + + @Override + public void init() { + + } + } +} \ No newline at end of file diff --git a/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheckTest.java b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheckTest.java new file mode 100644 index 00000000..d7c5a585 --- /dev/null +++ b/eventmesh-dashboard-console/src/test/java/org/apache/eventmesh/dashboard/console/health/check/impl/StorageRedisCheckTest.java @@ -0,0 +1,55 @@ +/* + * 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.health.check.impl; + +import org.apache.eventmesh.dashboard.console.health.check.config.HealthCheckObjectConfig; +import org.apache.eventmesh.dashboard.console.health.callback.HealthCheckCallback; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class StorageRedisCheckTest { + + private StorageRedisCheck storageRedisCheck; + + @BeforeEach + public void init() { + HealthCheckObjectConfig config = new HealthCheckObjectConfig(); + config.setInstanceId(1L); + config.setHealthCheckResourceType("storage"); + config.setHealthCheckResourceSubType("redis"); + config.setSimpleClassName("StorageRedisCheck"); + config.setClusterId(1L); + config.setConnectUrl("redis://localhost:6379"); + storageRedisCheck = new StorageRedisCheck(config); + } + + @Test + public void testDoCheck() { + storageRedisCheck.doCheck(new HealthCheckCallback() { + @Override + public void onSuccess() { + System.out.println("success"); + } + + @Override + public void onFail(Exception e) { + System.out.println("fail"); + } + }); + } +} \ No newline at end of file