[automation] Add support for synchronized execution of compiled scripts (#4402)

* [automation] Synchronize execution of compiled scripts if ScriptEngine implements Lock interface

Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
This commit is contained in:
Florian Hotze 2024-10-06 19:20:30 +02:00 committed by GitHub
parent 9eef587c89
commit d012d36bba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -17,6 +17,8 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import javax.script.Compilable; import javax.script.Compilable;
import javax.script.CompiledScript; import javax.script.CompiledScript;
@ -210,15 +212,29 @@ public abstract class AbstractScriptModuleHandler<T extends Module> extends Base
protected @Nullable Object eval(ScriptEngine engine, String script) { protected @Nullable Object eval(ScriptEngine engine, String script) {
try { try {
if (compiledScript.isPresent()) { if (compiledScript.isPresent()) {
if (engine instanceof Lock lock && !lock.tryLock(1, TimeUnit.MINUTES)) {
logger.error("Failed to acquire lock within one minute for script module of rule with UID '{}'",
ruleUID);
return null;
}
logger.debug("Executing pre-compiled script of rule with UID '{}'", ruleUID); logger.debug("Executing pre-compiled script of rule with UID '{}'", ruleUID);
return compiledScript.get().eval(engine.getContext()); try {
return compiledScript.get().eval(engine.getContext());
} finally { // Make sure that Lock is unlocked regardless of an exception being thrown or not to avoid
// deadlocks
if (engine instanceof Lock lock) {
lock.unlock();
}
}
} }
logger.debug("Executing script of rule with UID '{}'", ruleUID); logger.debug("Executing script of rule with UID '{}'", ruleUID);
return engine.eval(script); return engine.eval(script);
} catch (ScriptException e) { } catch (ScriptException e) {
logger.error("Script execution of rule with UID '{}' failed: {}", ruleUID, e.getMessage(), logger.error("Script execution of rule with UID '{}' failed: {}", ruleUID, e.getMessage(),
logger.isDebugEnabled() ? e : null); logger.isDebugEnabled() ? e : null);
return null; } catch (InterruptedException e) {
throw new RuntimeException(e);
} }
return null;
} }
} }