This is an automated email from the ASF dual-hosted git repository. huijun pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-heron.git
The following commit(s) were added to refs/heads/master by this push: new 93b2b3f [healthmgr] Enable runtime toggle for AutoRestartBackpressureContainerPolicy (#2923) 93b2b3f is described below commit 93b2b3fdc0d7dac1a9f06eb1b53f75204886e300 Author: bed debug <huiju...@users.noreply.github.com> AuthorDate: Tue Jul 3 11:43:53 2018 -0700 [healthmgr] Enable runtime toggle for AutoRestartBackpressureContainerPolicy (#2923) * enable runtime config for autobackpressure policy * update comment * clean comment * fix neng comment * fix compile * staging * toggle each policy * toggle per policy * fix neng comment * update condition check in toggle policy * update log fine * fix ning comment --- heron/config/src/yaml/conf/local/healthmgr.yaml | 29 +++-- heron/config/src/yaml/conf/sandbox/healthmgr.yaml | 29 +++-- heron/config/src/yaml/conf/yarn/healthmgr.yaml | 24 +++- .../org/apache/heron/healthmgr/HealthManager.java | 9 +- .../apache/heron/healthmgr/HealthPolicyConfig.java | 22 +++- .../heron/healthmgr/HealthPolicyConfigReader.java | 3 +- .../healthmgr/common/PhysicalPlanProvider.java | 6 +- .../AutoRestartBackpressureContainerPolicy.java | 17 +-- .../policy/DynamicResourceAllocationPolicy.java | 4 +- .../heron/healthmgr/policy/ToggleablePolicy.java | 135 +++++++++++++++++++++ 10 files changed, 236 insertions(+), 42 deletions(-) diff --git a/heron/config/src/yaml/conf/local/healthmgr.yaml b/heron/config/src/yaml/conf/local/healthmgr.yaml index aa49572..d5d93d9 100644 --- a/heron/config/src/yaml/conf/local/healthmgr.yaml +++ b/heron/config/src/yaml/conf/local/healthmgr.yaml @@ -18,27 +18,36 @@ # Topology health manager mode: # disabled = do not launch the health manager # cluster = launch the health manager on container-0 -heron.topology.healthmgr.mode: disabled +heron.topology.healthmgr.mode: cluster # Default class and url for providing metrics -heron.healthmgr.metricsource.type: org.apache.heron.healthmgr.sensors.TrackerMetricsProvider +heron.healthmgr.metricsource.type: org.apache.heron.healthmgr.sensors.MetricsCacheMetricsProvider heron.healthmgr.metricsource.url: http://localhost:8888 # Enable MetricsCache if MetricsCache is chosen as metrics provider -#heron.topology.metricscachemgr.mode: cluster +# disabled = do not launch the metricscache manager +# cluster = launch the metricscache manager on container-0 +heron.topology.metricscachemgr.mode: cluster ## list of policies to be executed for self regulation -#heron.class.health.policies: +heron.class.health.policies: # - dynamic-resource-allocation -# - auto-restart-backpressure-container -# + - auto-restart-backpressure-container + ## configuration specific to individual policies listed above + #dynamic-resource-allocation: +# health.policy.mode: deactivated # health.policy.class: org.apache.heron.healthmgr.policy.DynamicResourceAllocationPolicy # health.policy.interval.ms: 120000 # BackPressureDetector.noiseFilterMillis: 20 # GrowingWaitQueueDetector.limit: 5 -#auto-restart-backpressure-container: -# health.policy.class: org.apache.heron.healthmgr.policy.AutoRestartBackpressureContainerPolicy -# health.policy.interval.ms: 120000 -# BackPressureDetector.noiseFilterMillis: 20 + +auto-restart-backpressure-container: + # policy toggle value: + # deactivated = freeze this policy + # activated = turn on this policy + health.policy.mode: deactivated + health.policy.class: org.apache.heron.healthmgr.policy.AutoRestartBackpressureContainerPolicy + health.policy.interval.ms: 20000 + BackPressureDetector.noiseFilterMillis: 20 diff --git a/heron/config/src/yaml/conf/sandbox/healthmgr.yaml b/heron/config/src/yaml/conf/sandbox/healthmgr.yaml index aa49572..d5d93d9 100644 --- a/heron/config/src/yaml/conf/sandbox/healthmgr.yaml +++ b/heron/config/src/yaml/conf/sandbox/healthmgr.yaml @@ -18,27 +18,36 @@ # Topology health manager mode: # disabled = do not launch the health manager # cluster = launch the health manager on container-0 -heron.topology.healthmgr.mode: disabled +heron.topology.healthmgr.mode: cluster # Default class and url for providing metrics -heron.healthmgr.metricsource.type: org.apache.heron.healthmgr.sensors.TrackerMetricsProvider +heron.healthmgr.metricsource.type: org.apache.heron.healthmgr.sensors.MetricsCacheMetricsProvider heron.healthmgr.metricsource.url: http://localhost:8888 # Enable MetricsCache if MetricsCache is chosen as metrics provider -#heron.topology.metricscachemgr.mode: cluster +# disabled = do not launch the metricscache manager +# cluster = launch the metricscache manager on container-0 +heron.topology.metricscachemgr.mode: cluster ## list of policies to be executed for self regulation -#heron.class.health.policies: +heron.class.health.policies: # - dynamic-resource-allocation -# - auto-restart-backpressure-container -# + - auto-restart-backpressure-container + ## configuration specific to individual policies listed above + #dynamic-resource-allocation: +# health.policy.mode: deactivated # health.policy.class: org.apache.heron.healthmgr.policy.DynamicResourceAllocationPolicy # health.policy.interval.ms: 120000 # BackPressureDetector.noiseFilterMillis: 20 # GrowingWaitQueueDetector.limit: 5 -#auto-restart-backpressure-container: -# health.policy.class: org.apache.heron.healthmgr.policy.AutoRestartBackpressureContainerPolicy -# health.policy.interval.ms: 120000 -# BackPressureDetector.noiseFilterMillis: 20 + +auto-restart-backpressure-container: + # policy toggle value: + # deactivated = freeze this policy + # activated = turn on this policy + health.policy.mode: deactivated + health.policy.class: org.apache.heron.healthmgr.policy.AutoRestartBackpressureContainerPolicy + health.policy.interval.ms: 20000 + BackPressureDetector.noiseFilterMillis: 20 diff --git a/heron/config/src/yaml/conf/yarn/healthmgr.yaml b/heron/config/src/yaml/conf/yarn/healthmgr.yaml index c3cf2b2..d5d93d9 100644 --- a/heron/config/src/yaml/conf/yarn/healthmgr.yaml +++ b/heron/config/src/yaml/conf/yarn/healthmgr.yaml @@ -18,22 +18,36 @@ # Topology health manager mode: # disabled = do not launch the health manager # cluster = launch the health manager on container-0 -heron.topology.healthmgr.mode: disabled +heron.topology.healthmgr.mode: cluster # Default class and url for providing metrics -heron.healthmgr.metricsource.type: org.apache.heron.healthmgr.sensors.TrackerMetricsProvider +heron.healthmgr.metricsource.type: org.apache.heron.healthmgr.sensors.MetricsCacheMetricsProvider heron.healthmgr.metricsource.url: http://localhost:8888 # Enable MetricsCache if MetricsCache is chosen as metrics provider -#heron.topology.metricscachemgr.mode: cluster +# disabled = do not launch the metricscache manager +# cluster = launch the metricscache manager on container-0 +heron.topology.metricscachemgr.mode: cluster ## list of policies to be executed for self regulation -#heron.class.health.policies: +heron.class.health.policies: # - dynamic-resource-allocation -# + - auto-restart-backpressure-container + ## configuration specific to individual policies listed above + #dynamic-resource-allocation: +# health.policy.mode: deactivated # health.policy.class: org.apache.heron.healthmgr.policy.DynamicResourceAllocationPolicy # health.policy.interval.ms: 120000 # BackPressureDetector.noiseFilterMillis: 20 # GrowingWaitQueueDetector.limit: 5 + +auto-restart-backpressure-container: + # policy toggle value: + # deactivated = freeze this policy + # activated = turn on this policy + health.policy.mode: deactivated + health.policy.class: org.apache.heron.healthmgr.policy.AutoRestartBackpressureContainerPolicy + health.policy.interval.ms: 20000 + BackPressureDetector.noiseFilterMillis: 20 diff --git a/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthManager.java b/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthManager.java index ddc519e..f41d516 100644 --- a/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthManager.java +++ b/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthManager.java @@ -68,6 +68,7 @@ import org.apache.heron.spi.utils.ReflectionUtils; import static org.apache.heron.healthmgr.HealthPolicyConfig.CONF_METRICS_SOURCE_TYPE; import static org.apache.heron.healthmgr.HealthPolicyConfig.CONF_METRICS_SOURCE_URL; +import static org.apache.heron.healthmgr.HealthPolicyConfig.CONF_POLICY_ID; import static org.apache.heron.healthmgr.HealthPolicyConfig.CONF_TOPOLOGY_NAME; /** @@ -314,7 +315,7 @@ public class HealthManager { Class<IHealthPolicy> policyClass = (Class<IHealthPolicy>) this.getClass().getClassLoader().loadClass(policyClassName); - AbstractModule module = constructPolicySpecificModule(policyConfig); + AbstractModule module = constructPolicySpecificModule(policyId, policyConfig); IHealthPolicy policy = injector.createChildInjector(module).getInstance(policyClass); healthPolicies.add(policy); @@ -378,10 +379,14 @@ public class HealthManager { }; } - private AbstractModule constructPolicySpecificModule(final HealthPolicyConfig policyConfig) { + private AbstractModule constructPolicySpecificModule( + final String policyId, final HealthPolicyConfig policyConfig) { return new AbstractModule() { @Override protected void configure() { + bind(String.class) + .annotatedWith(Names.named(CONF_POLICY_ID)) + .toInstance(policyId); bind(HealthPolicyConfig.class).toInstance(policyConfig); } }; diff --git a/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfig.java b/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfig.java index 1256eb2..0cba8cb 100644 --- a/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfig.java +++ b/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfig.java @@ -24,11 +24,16 @@ import java.util.Map; import java.util.logging.Logger; import org.apache.heron.healthmgr.HealthPolicyConfigReader.PolicyConfigKey; +import org.apache.heron.healthmgr.policy.ToggleablePolicy; public class HealthPolicyConfig { public static final String CONF_TOPOLOGY_NAME = "TOPOLOGY_NAME"; public static final String CONF_METRICS_SOURCE_URL = "METRICS_SOURCE_URL"; public static final String CONF_METRICS_SOURCE_TYPE = "METRICS_SOURCE_TYPE"; + public static final String CONF_POLICY_ID = "POLICY_ID"; + + public static final String CONF_POLICY_MODE_DEACTIVATED = "deactivated"; + public static final String CONF_POLICY_MODE_ACTIVATED = "activated"; private static final Logger LOG = Logger.getLogger(HealthPolicyConfig.class.getName()); private final Map<String, Object> configs; @@ -42,8 +47,23 @@ public class HealthPolicyConfig { return (String) configs.get(PolicyConfigKey.HEALTH_POLICY_CLASS.key()); } + public ToggleablePolicy.PolicyMode getPolicyMode() { + String configKey = PolicyConfigKey.HEALTH_POLICY_MODE.key(); + if (configs.containsKey(configKey)) { + String val = (String) configs.get(PolicyConfigKey.HEALTH_POLICY_MODE.key()); + if (CONF_POLICY_MODE_DEACTIVATED.equals(val)) { + return ToggleablePolicy.PolicyMode.deactivated; + } else if (CONF_POLICY_MODE_ACTIVATED.equals(val)) { + return ToggleablePolicy.PolicyMode.activated; + } else { + LOG.warning("unknown policy mode config " + val); + } + } + return ToggleablePolicy.PolicyMode.activated; + } + public Duration getInterval() { - return Duration.ofMillis((int) configs.get(PolicyConfigKey.HEALTH_POLICY_INTERVAL.key())); + return Duration.ofMillis((int) configs.get(PolicyConfigKey.HEALTH_POLICY_INTERVAL_MS.key())); } public Object getConfig(String configName) { diff --git a/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfigReader.java b/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfigReader.java index ba45209..f421961 100644 --- a/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfigReader.java +++ b/heron/healthmgr/src/java/org/apache/heron/healthmgr/HealthPolicyConfigReader.java @@ -49,8 +49,9 @@ public class HealthPolicyConfigReader { public enum PolicyConfigKey { CONF_FILE_NAME("healthmgr.yaml"), HEALTH_POLICIES("heron.class.health.policies"), + HEALTH_POLICY_MODE("health.policy.mode"), HEALTH_POLICY_CLASS("health.policy.class"), - HEALTH_POLICY_INTERVAL("health.policy.interval.ms"), + HEALTH_POLICY_INTERVAL_MS("health.policy.interval.ms"), CONF_SENSOR_DURATION_SUFFIX(".duration"), METRIC_SOURCE_TYPE("heron.healthmgr.metricsource.type"), METRIC_SOURCE_URL("heron.healthmgr.metricsource.url"); diff --git a/heron/healthmgr/src/java/org/apache/heron/healthmgr/common/PhysicalPlanProvider.java b/heron/healthmgr/src/java/org/apache/heron/healthmgr/common/PhysicalPlanProvider.java index 79990e8..eca7dfb 100644 --- a/heron/healthmgr/src/java/org/apache/heron/healthmgr/common/PhysicalPlanProvider.java +++ b/heron/healthmgr/src/java/org/apache/heron/healthmgr/common/PhysicalPlanProvider.java @@ -78,11 +78,9 @@ public class PhysicalPlanProvider implements Provider<PhysicalPlan> { @Override public synchronized PhysicalPlan get() { + physicalPlan = stateManagerAdaptor.getPhysicalPlan(topologyName); if (physicalPlan == null) { - physicalPlan = stateManagerAdaptor.getPhysicalPlan(topologyName); - if (physicalPlan == null) { - throw new InvalidStateException(topologyName, "Failed to fetch the physical plan"); - } + throw new InvalidStateException(topologyName, "Failed to fetch the physical plan"); } return physicalPlan; } diff --git a/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/AutoRestartBackpressureContainerPolicy.java b/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/AutoRestartBackpressureContainerPolicy.java index f143246..82b7e69 100644 --- a/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/AutoRestartBackpressureContainerPolicy.java +++ b/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/AutoRestartBackpressureContainerPolicy.java @@ -23,18 +23,20 @@ import java.time.Duration; import java.util.logging.Logger; import javax.inject.Inject; +import javax.inject.Named; import com.microsoft.dhalion.events.EventHandler; import com.microsoft.dhalion.events.EventManager; -import com.microsoft.dhalion.policy.HealthPolicyImpl; import org.apache.heron.healthmgr.HealthPolicyConfig; import org.apache.heron.healthmgr.common.HealthManagerEvents.ContainerRestart; +import org.apache.heron.healthmgr.common.PhysicalPlanProvider; import org.apache.heron.healthmgr.detectors.BackPressureDetector; import org.apache.heron.healthmgr.resolvers.RestartContainerResolver; import org.apache.heron.healthmgr.sensors.BackPressureSensor; -import static org.apache.heron.healthmgr.HealthPolicyConfigReader.PolicyConfigKey.HEALTH_POLICY_INTERVAL; +import static org.apache.heron.healthmgr.HealthPolicyConfig.CONF_POLICY_ID; +import static org.apache.heron.healthmgr.HealthPolicyConfigReader.PolicyConfigKey.HEALTH_POLICY_INTERVAL_MS; /** * This Policy class @@ -42,7 +44,7 @@ import static org.apache.heron.healthmgr.HealthPolicyConfigReader.PolicyConfigKe * state for long time, which we believe the container cannot recover. * 2. resolver: try to restart the backpressure container so as to be rescheduled. */ -public class AutoRestartBackpressureContainerPolicy extends HealthPolicyImpl +public class AutoRestartBackpressureContainerPolicy extends ToggleablePolicy implements EventHandler<ContainerRestart> { private static final String CONF_WAIT_INTERVAL_MILLIS = @@ -50,22 +52,23 @@ public class AutoRestartBackpressureContainerPolicy extends HealthPolicyImpl private static final Logger LOG = Logger.getLogger(AutoRestartBackpressureContainerPolicy.class.getName()); - private final HealthPolicyConfig policyConfig; @Inject - AutoRestartBackpressureContainerPolicy(HealthPolicyConfig policyConfig, + AutoRestartBackpressureContainerPolicy(@Named(CONF_POLICY_ID) String policyId, + HealthPolicyConfig policyConfig, + PhysicalPlanProvider physicalPlanProvider, EventManager eventManager, BackPressureSensor backPressureSensor, BackPressureDetector backPressureDetector, RestartContainerResolver restartContainerResolver) { - this.policyConfig = policyConfig; + super(policyId, policyConfig, physicalPlanProvider); registerSensors(backPressureSensor); registerDetectors(backPressureDetector); registerResolvers(restartContainerResolver); setPolicyExecutionInterval( - Duration.ofMillis((int) policyConfig.getConfig(HEALTH_POLICY_INTERVAL.key(), 60000))); + Duration.ofMillis((int) policyConfig.getConfig(HEALTH_POLICY_INTERVAL_MS.key(), 60000))); eventManager.addEventListener(ContainerRestart.class, this); } diff --git a/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/DynamicResourceAllocationPolicy.java b/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/DynamicResourceAllocationPolicy.java index f314330..45293f0 100644 --- a/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/DynamicResourceAllocationPolicy.java +++ b/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/DynamicResourceAllocationPolicy.java @@ -46,7 +46,7 @@ import org.apache.heron.healthmgr.sensors.BackPressureSensor; import org.apache.heron.healthmgr.sensors.BufferSizeSensor; import org.apache.heron.healthmgr.sensors.ExecuteCountSensor; -import static org.apache.heron.healthmgr.HealthPolicyConfigReader.PolicyConfigKey.HEALTH_POLICY_INTERVAL; +import static org.apache.heron.healthmgr.HealthPolicyConfigReader.PolicyConfigKey.HEALTH_POLICY_INTERVAL_MS; import static org.apache.heron.healthmgr.diagnosers.BaseDiagnoser.DiagnosisType.DIAGNOSIS_DATA_SKEW; import static org.apache.heron.healthmgr.diagnosers.BaseDiagnoser.DiagnosisType.DIAGNOSIS_SLOW_INSTANCE; import static org.apache.heron.healthmgr.diagnosers.BaseDiagnoser.DiagnosisType.DIAGNOSIS_UNDER_PROVISIONING; @@ -86,7 +86,7 @@ public class DynamicResourceAllocationPolicy extends HealthPolicyImpl registerResolvers(scaleUpResolver); setPolicyExecutionInterval( - Duration.ofMillis((int) policyConfig.getConfig(HEALTH_POLICY_INTERVAL.key(), 60000))); + Duration.ofMillis((int) policyConfig.getConfig(HEALTH_POLICY_INTERVAL_MS.key(), 60000))); eventManager.addEventListener(TopologyUpdate.class, this); } diff --git a/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/ToggleablePolicy.java b/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/ToggleablePolicy.java new file mode 100644 index 0000000..a55764e --- /dev/null +++ b/heron/healthmgr/src/java/org/apache/heron/healthmgr/policy/ToggleablePolicy.java @@ -0,0 +1,135 @@ +/** + * 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.heron.healthmgr.policy; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.logging.Logger; + +import javax.inject.Inject; +import javax.inject.Named; + +import com.microsoft.dhalion.core.Action; +import com.microsoft.dhalion.core.Diagnosis; +import com.microsoft.dhalion.core.Measurement; +import com.microsoft.dhalion.core.Symptom; +import com.microsoft.dhalion.policy.HealthPolicyImpl; + +import org.apache.heron.api.generated.TopologyAPI; +import org.apache.heron.healthmgr.HealthPolicyConfig; +import org.apache.heron.healthmgr.common.PhysicalPlanProvider; + +import static org.apache.heron.healthmgr.HealthPolicyConfig.CONF_POLICY_ID; + +/** + * This Policy class + * 1. has a toggle switch + * 2. works with runtime config + */ +public class ToggleablePolicy extends HealthPolicyImpl { + private static final Logger LOG = + Logger.getLogger(ToggleablePolicy.class.getName()); + + protected PhysicalPlanProvider physicalPlanProvider; + protected String policyId; + private String policyIdRuntime; + protected HealthPolicyConfig policyConfig; + + protected PolicyMode policyMode; + + public enum PolicyMode { + activated, + deactivated + } + + @Inject + public ToggleablePolicy( + @Named(CONF_POLICY_ID) String policyId, + HealthPolicyConfig policyConfig, + PhysicalPlanProvider physicalPlanProvider) { + this.physicalPlanProvider = physicalPlanProvider; + this.policyId = policyId; + this.policyConfig = policyConfig; + + policyMode = policyConfig.getPolicyMode(); + policyIdRuntime = policyId + ":runtime"; + } + + @Override + public Collection<Measurement> executeSensors() { + for (TopologyAPI.Config.KeyValue kv + : physicalPlanProvider.get().getTopology().getTopologyConfig().getKvsList()) { + LOG.fine("kv " + kv.getKey() + ":" + kv.getValue()); + if (kv.getKey().equals(policyIdRuntime)) { + try { + PolicyMode val = PolicyMode.valueOf(kv.getValue()); + if (!policyMode.equals(val)) { + policyMode = val; + LOG.info("policy " + policyId + " status changed to " + policyMode); + } else { + LOG.fine("policy " + policyId + " status remains same " + policyMode); + } + break; + } catch (IllegalArgumentException e) { + LOG.warning("policy " + policyId + " status does not change " + policyMode + + "; unknown input " + kv.getValue()); + } + } + } + + if (policyMode.equals(PolicyMode.activated)) { + return super.executeSensors(); + } else { + return new ArrayList<Measurement>(); + } + } + + @Override + public Collection<Symptom> executeDetectors(Collection<Measurement> measurements) { + if (policyMode.equals(PolicyMode.activated)) { + return super.executeDetectors(measurements); + } else { + return new ArrayList<Symptom>(); + } + } + + @Override + public Collection<Diagnosis> executeDiagnosers(Collection<Symptom> symptoms) { + if (policyMode.equals(PolicyMode.activated)) { + return super.executeDiagnosers(symptoms); + } else { + return new ArrayList<Diagnosis>(); + } + } + + @Override + public Collection<Action> executeResolvers(Collection<Diagnosis> diagnosis) { + if (policyMode.equals(PolicyMode.activated)) { + return super.executeResolvers(diagnosis); + } else { + /* + * TODO(dhalion): + * If sub-class could access the `lastExecutionTimestamp` + * and `oneTimeDelay`, avoid super method invocation. + */ + return super.executeResolvers(new ArrayList<Diagnosis>()); + } + } +}