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); output = Boolean.toString(result);
break; break;
case "switch": case "switch":
Set<String> states = engine.executeSwitch(inMsg); Set<String> states = engine.executeSwitchAsync(inMsg).get(TIMEOUT, TimeUnit.SECONDS);
output = objectMapper.writeValueAsString(states); output = objectMapper.writeValueAsString(states);
break; break;
case "json": case "json":

View File

@ -195,9 +195,7 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S
}, MoreExecutors.directExecutor()); }, MoreExecutors.directExecutor());
} }
@Override Set<String> executeSwitchPostProcessFunction(JsonNode result) throws ScriptException {
public Set<String> executeSwitch(TbMsg msg) throws ScriptException {
JsonNode result = executeScript(msg);
if (result.isTextual()) { if (result.isTextual()) {
return Collections.singleton(result.asText()); return Collections.singleton(result.asText());
} else if (result.isArray()) { } 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 { private JsonNode executeScript(TbMsg msg) throws ScriptException {
try { try {
String[] inArgs = prepareArgs(msg); String[] inArgs = prepareArgs(msg);

View File

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

View File

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