Skip to content

Commit

Permalink
Allow to run rules using scheduler to avoid "Failed to execute rule ‘…
Browse files Browse the repository at this point in the history
…{}' with status '{}'" error path (#4072)

Signed-off-by: Oleg Kleshchev <[email protected]>
  • Loading branch information
OlegAndreych committed Jan 28, 2024
1 parent fb7e030 commit e34018a
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
* See the NOTICE file(s) distributed with this work for additional information.

Check failure on line 4 in bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/RuleManager.java

View workflow job for this annotation

GitHub Actions / Build (Java 17, ubuntu-22.04)

Header line doesn't match pattern ^ \* See the NOTICE file\(s\) distributed with this work for additional$
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
* This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
* which is available at http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.automation;

import java.time.ZonedDateTime;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
Expand Down Expand Up @@ -99,6 +98,33 @@ public interface RuleManager {
*/
Map<String, Object> runNow(String uid, boolean considerConditions, @Nullable Map<String, Object> context);

/**
* The method skips the triggers and the conditions and schedules execution of the actions of the rule by respective
* scheduler. This should always be possible unless an action has a mandatory input that is linked to a trigger. In
* that case the action is skipped and the rule engine continues execution of rest actions.
* <p>
* This method allows simultaneous calls from different threads without triggering "Failed to execute rule ‘{}' with
* status '{}'" error execution path.
*
* @param uid id of the rule whose actions have to be executed.
* @return a future with a copy of the rule context, including possible return values
*/
Future<Map<String, Object>> scheduleRun(String uid);

/**
* Same as {@link #scheduleRun(String)} with the additional option to enable/disable evaluation of conditions
* defined in the target rule. The context can be set here, too, but also might be {@code null}.
* <p>
* This method allows simultaneous calls from different threads without triggering "Failed to execute rule ‘{}' with
* status '{}'" error execution path.
*
* @param uid id of the rule whose actions have to be executed.
* @param considerConditions if {@code true} the conditions of the rule will be checked.
* @param context the context that is passed to the conditions and the actions of the rule.
* @return a future with a copy of the rule context, including possible return values
*/
Future<Map<String, Object>> scheduleRun(String uid, boolean considerConditions, Map<String, Object> context);

/**
* Simulates the execution of all rules with tag 'Schedule' for the given time interval.
* The result is sorted ascending by execution time.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,76 +1,33 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
* See the NOTICE file(s) distributed with this work for additional information.

Check failure on line 4 in bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/RuleEngineImpl.java

View workflow job for this annotation

GitHub Actions / Build (Java 17, ubuntu-22.04)

Header line doesn't match pattern ^ \* See the NOTICE file\(s\) distributed with this work for additional$
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
* This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
* which is available at http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.automation.internal;

import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.*;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.Action;
import org.openhab.core.automation.Condition;
import org.openhab.core.automation.*;
import org.openhab.core.automation.Module;
import org.openhab.core.automation.ModuleHandlerCallback;
import org.openhab.core.automation.Rule;
import org.openhab.core.automation.RuleExecution;
import org.openhab.core.automation.RuleManager;
import org.openhab.core.automation.RuleRegistry;
import org.openhab.core.automation.RuleStatus;
import org.openhab.core.automation.RuleStatusDetail;
import org.openhab.core.automation.RuleStatusInfo;
import org.openhab.core.automation.Trigger;
import org.openhab.core.automation.events.RuleStatusInfoEvent;
import org.openhab.core.automation.handler.ActionHandler;
import org.openhab.core.automation.handler.ConditionHandler;
import org.openhab.core.automation.handler.ModuleHandler;
import org.openhab.core.automation.handler.ModuleHandlerFactory;
import org.openhab.core.automation.handler.TriggerHandler;
import org.openhab.core.automation.handler.TriggerHandlerCallback;
import org.openhab.core.automation.handler.*;
import org.openhab.core.automation.internal.TriggerHandlerCallbackImpl.TriggerData;
import org.openhab.core.automation.internal.composite.CompositeModuleHandlerFactory;
import org.openhab.core.automation.internal.module.handler.SystemTriggerHandler;
import org.openhab.core.automation.internal.ruleengine.WrappedAction;
import org.openhab.core.automation.internal.ruleengine.WrappedCondition;
import org.openhab.core.automation.internal.ruleengine.WrappedModule;
import org.openhab.core.automation.internal.ruleengine.WrappedRule;
import org.openhab.core.automation.internal.ruleengine.WrappedTrigger;
import org.openhab.core.automation.type.ActionType;
import org.openhab.core.automation.type.CompositeActionType;
import org.openhab.core.automation.type.CompositeConditionType;
import org.openhab.core.automation.type.CompositeTriggerType;
import org.openhab.core.automation.type.ConditionType;
import org.openhab.core.automation.type.Input;
import org.openhab.core.automation.type.ModuleType;
import org.openhab.core.automation.type.ModuleTypeRegistry;
import org.openhab.core.automation.type.Output;
import org.openhab.core.automation.type.TriggerType;
import org.openhab.core.automation.internal.ruleengine.*;
import org.openhab.core.automation.type.*;
import org.openhab.core.automation.util.ReferenceResolver;
import org.openhab.core.common.NamedThreadFactory;
import org.openhab.core.common.registry.RegistryChangeListener;
Expand All @@ -83,12 +40,7 @@
import org.openhab.core.service.StartLevelService;
import org.openhab.core.storage.Storage;
import org.openhab.core.storage.StorageService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -1051,6 +1003,13 @@ public Map<String, Object> runNow(String ruleUID, boolean considerConditions,
return returnContext;
}

@Override
public Future<Map<String, Object>> scheduleRun(String uid) {
TriggerHandlerCallback triggerHandlerCallback = getTriggerHandlerCallback(uid);
ScheduledExecutorService scheduler = triggerHandlerCallback.getScheduler();
return scheduler.submit(() -> runNow(uid));
}

@Override
public Map<String, Object> runNow(String ruleUID) {
return runNow(ruleUID, false, null);
Expand Down Expand Up @@ -1479,4 +1438,12 @@ public boolean isStarted() {
public Stream<RuleExecution> simulateRuleExecutions(ZonedDateTime from, ZonedDateTime until) {
return new RuleExecutionSimulator(this.ruleRegistry, this).simulateRuleExecutions(from, until);
}

@Override
public Future<Map<String, Object>> scheduleRun(String uid, boolean considerConditions,
Map<String, Object> context) {
TriggerHandlerCallback triggerHandlerCallback = getTriggerHandlerCallback(uid);
ScheduledExecutorService scheduler = triggerHandlerCallback.getScheduler();
return scheduler.submit(() -> runNow(uid, considerConditions, context));
}
}

0 comments on commit e34018a

Please sign in to comment.