js-script-engine-api: executeSwitch replaced with asynchronous executeSwitchAsync

This commit is contained in:
Sergey Matvienko 2021-06-16 12:40:38 +03:00
parent 585f473bda
commit 8915b279a0
5 changed files with 29 additions and 16 deletions

View File

@ -400,7 +400,7 @@ public class RuleChainController extends BaseController {
output = Boolean.toString(result);
break;
case "switch":
Set<String> states = engine.executeSwitch(inMsg);
Set<String> states = engine.executeSwitchAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = objectMapper.writeValueAsString(states);
break;
case "json":

View File

@ -195,9 +195,7 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S
}, MoreExecutors.directExecutor());
}
@Override
public Set<String> executeSwitch(TbMsg msg) throws ScriptException {
JsonNode result = executeScript(msg);
Set<String> executeSwitchPostProcessFunction(JsonNode result) throws ScriptException {
if (result.isTextual()) {
return Collections.singleton(result.asText());
} else if (result.isArray()) {
@ -217,6 +215,14 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S
}
}
@Override
public ListenableFuture<Set<String>> executeSwitchAsync(TbMsg msg) {
log.trace("execute switch async, msg {}", msg);
return Futures.transformAsync(executeScriptAsync(msg),
result -> Futures.immediateFuture(executeSwitchPostProcessFunction(result)),
MoreExecutors.directExecutor()); //usually runs in a callbackExecutor
}
private JsonNode executeScript(TbMsg msg) throws ScriptException {
try {
String[] inArgs = prepareArgs(msg);

View File

@ -35,7 +35,7 @@ public interface ScriptEngine {
ListenableFuture<Boolean> executeFilterAsync(TbMsg msg);
Set<String> executeSwitch(TbMsg msg) throws ScriptException;
ListenableFuture<Set<String>> executeSwitchAsync(TbMsg msg);
JsonNode executeJson(TbMsg msg) throws ScriptException;

View File

@ -15,7 +15,11 @@
*/
package org.thingsboard.rule.engine.filter;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.thingsboard.common.util.ListeningExecutor;
import org.thingsboard.rule.engine.api.RuleNode;
import org.thingsboard.rule.engine.api.ScriptEngine;
@ -58,17 +62,20 @@ public class TbJsSwitchNode implements TbNode {
@Override
public void onMsg(TbContext ctx, TbMsg msg) {
ListeningExecutor jsExecutor = ctx.getJsExecutor();
ctx.logJsEvalRequest();
withCallback(jsExecutor.executeAsync(() -> jsEngine.executeSwitch(msg)),
result -> {
ctx.logJsEvalResponse();
processSwitch(ctx, msg, result);
},
t -> {
ctx.logJsEvalFailure();
ctx.tellFailure(msg, t);
}, ctx.getDbCallbackExecutor());
Futures.addCallback(jsEngine.executeSwitchAsync(msg), new FutureCallback<Set<String>>() {
@Override
public void onSuccess(@Nullable Set<String> result) {
ctx.logJsEvalResponse();
processSwitch(ctx, msg, result);
}
@Override
public void onFailure(Throwable t) {
ctx.logJsEvalFailure();
ctx.tellFailure(msg, t);
}
}, MoreExecutors.directExecutor()); //usually runs in a callbackExecutor
}
private void processSwitch(TbContext ctx, TbMsg msg, Set<String> nextRelations) {

View File

@ -73,7 +73,7 @@ public class TbJsSwitchNodeTest {
TbMsg msg = TbMsg.newMsg( "USER", null, metaData, TbMsgDataType.JSON, rawJson, ruleChainId, ruleNodeId);
mockJsExecutor();
when(scriptEngine.executeSwitch(msg)).thenReturn(Sets.newHashSet("one", "three"));
when(scriptEngine.executeSwitchAsync(msg)).thenReturn(Futures.immediateFuture(Sets.newHashSet("one", "three")));
node.onMsg(ctx, msg);
verify(ctx).getJsExecutor();