Commit 28e2c74ce3b5f3beda9bfaac9ba16cf42aea9523

Authored by Andrew Shvayka
1 parent da9b2b49

JS Invoke become async

@@ -19,6 +19,8 @@ import com.fasterxml.jackson.core.type.TypeReference; @@ -19,6 +19,8 @@ import com.fasterxml.jackson.core.type.TypeReference;
19 import com.fasterxml.jackson.databind.JsonNode; 19 import com.fasterxml.jackson.databind.JsonNode;
20 import com.fasterxml.jackson.databind.ObjectMapper; 20 import com.fasterxml.jackson.databind.ObjectMapper;
21 import com.google.common.collect.Sets; 21 import com.google.common.collect.Sets;
  22 +import com.google.common.util.concurrent.Futures;
  23 +import com.google.common.util.concurrent.ListenableFuture;
22 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
23 import org.apache.commons.lang3.StringUtils; 25 import org.apache.commons.lang3.StringUtils;
24 import org.thingsboard.server.common.data.id.EntityId; 26 import org.thingsboard.server.common.data.id.EntityId;
@@ -110,6 +112,19 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S @@ -110,6 +112,19 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S
110 } 112 }
111 113
112 @Override 114 @Override
  115 + public ListenableFuture<TbMsg> executeUpdateAsync(TbMsg msg) {
  116 + ListenableFuture<JsonNode> result = executeScriptAsync(msg);
  117 + return Futures.transformAsync(result, json -> {
  118 + if (!json.isObject()) {
  119 + log.warn("Wrong result type: {}", json.getNodeType());
  120 + return Futures.immediateFailedFuture(new ScriptException("Wrong result type: " + json.getNodeType()));
  121 + } else {
  122 + return Futures.immediateFuture(unbindMsg(json, msg));
  123 + }
  124 + });
  125 + }
  126 +
  127 + @Override
113 public TbMsg executeGenerate(TbMsg prevMsg) throws ScriptException { 128 public TbMsg executeGenerate(TbMsg prevMsg) throws ScriptException {
114 JsonNode result = executeScript(prevMsg); 129 JsonNode result = executeScript(prevMsg);
115 if (!result.isObject()) { 130 if (!result.isObject()) {
@@ -145,6 +160,19 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S @@ -145,6 +160,19 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S
145 } 160 }
146 161
147 @Override 162 @Override
  163 + public ListenableFuture<Boolean> executeFilterAsync(TbMsg msg) {
  164 + ListenableFuture<JsonNode> result = executeScriptAsync(msg);
  165 + return Futures.transformAsync(result, json -> {
  166 + if (!json.isBoolean()) {
  167 + log.warn("Wrong result type: {}", json.getNodeType());
  168 + return Futures.immediateFailedFuture(new ScriptException("Wrong result type: " + json.getNodeType()));
  169 + } else {
  170 + return Futures.immediateFuture(json.asBoolean());
  171 + }
  172 + });
  173 + }
  174 +
  175 + @Override
148 public Set<String> executeSwitch(TbMsg msg) throws ScriptException { 176 public Set<String> executeSwitch(TbMsg msg) throws ScriptException {
149 JsonNode result = executeScript(msg); 177 JsonNode result = executeScript(msg);
150 if (result.isTextual()) { 178 if (result.isTextual()) {
@@ -173,7 +201,7 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S @@ -173,7 +201,7 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S
173 return mapper.readTree(eval); 201 return mapper.readTree(eval);
174 } catch (ExecutionException e) { 202 } catch (ExecutionException e) {
175 if (e.getCause() instanceof ScriptException) { 203 if (e.getCause() instanceof ScriptException) {
176 - throw (ScriptException)e.getCause(); 204 + throw (ScriptException) e.getCause();
177 } else if (e.getCause() instanceof RuntimeException) { 205 } else if (e.getCause() instanceof RuntimeException) {
178 throw new ScriptException(e.getCause().getMessage()); 206 throw new ScriptException(e.getCause().getMessage());
179 } else { 207 } else {
@@ -184,6 +212,24 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S @@ -184,6 +212,24 @@ public class RuleNodeJsScriptEngine implements org.thingsboard.rule.engine.api.S
184 } 212 }
185 } 213 }
186 214
  215 + private ListenableFuture<JsonNode> executeScriptAsync(TbMsg msg) {
  216 + String[] inArgs = prepareArgs(msg);
  217 + return Futures.transformAsync(sandboxService.invokeFunction(this.scriptId, inArgs[0], inArgs[1], inArgs[2]),
  218 + o -> {
  219 + try {
  220 + return Futures.immediateFuture(mapper.readTree(o.toString()));
  221 + } catch (Exception e) {
  222 + if (e.getCause() instanceof ScriptException) {
  223 + return Futures.immediateFailedFuture(e.getCause());
  224 + } else if (e.getCause() instanceof RuntimeException) {
  225 + return Futures.immediateFailedFuture(new ScriptException(e.getCause().getMessage()));
  226 + } else {
  227 + return Futures.immediateFailedFuture(new ScriptException(e));
  228 + }
  229 + }
  230 + });
  231 + }
  232 +
187 public void destroy() { 233 public void destroy() {
188 sandboxService.release(this.scriptId); 234 sandboxService.release(this.scriptId);
189 } 235 }
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.rule.engine.api; 16 package org.thingsboard.rule.engine.api;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
  19 +import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.msg.TbMsg; 20 import org.thingsboard.server.common.msg.TbMsg;
20 21
21 import javax.script.ScriptException; 22 import javax.script.ScriptException;
@@ -25,10 +26,14 @@ public interface ScriptEngine { @@ -25,10 +26,14 @@ public interface ScriptEngine {
25 26
26 TbMsg executeUpdate(TbMsg msg) throws ScriptException; 27 TbMsg executeUpdate(TbMsg msg) throws ScriptException;
27 28
  29 + ListenableFuture<TbMsg> executeUpdateAsync(TbMsg msg);
  30 +
28 TbMsg executeGenerate(TbMsg prevMsg) throws ScriptException; 31 TbMsg executeGenerate(TbMsg prevMsg) throws ScriptException;
29 32
30 boolean executeFilter(TbMsg msg) throws ScriptException; 33 boolean executeFilter(TbMsg msg) throws ScriptException;
31 34
  35 + ListenableFuture<Boolean> executeFilterAsync(TbMsg msg);
  36 +
32 Set<String> executeSwitch(TbMsg msg) throws ScriptException; 37 Set<String> executeSwitch(TbMsg msg) throws ScriptException;
33 38
34 JsonNode executeJson(TbMsg msg) throws ScriptException; 39 JsonNode executeJson(TbMsg msg) throws ScriptException;
@@ -51,9 +51,8 @@ public class TbJsFilterNode implements TbNode { @@ -51,9 +51,8 @@ public class TbJsFilterNode implements TbNode {
51 51
52 @Override 52 @Override
53 public void onMsg(TbContext ctx, TbMsg msg) { 53 public void onMsg(TbContext ctx, TbMsg msg) {
54 - ListeningExecutor jsExecutor = ctx.getJsExecutor();  
55 ctx.logJsEvalRequest(); 54 ctx.logJsEvalRequest();
56 - withCallback(jsExecutor.executeAsync(() -> jsEngine.executeFilter(msg)), 55 + withCallback(jsEngine.executeFilterAsync(msg),
57 filterResult -> { 56 filterResult -> {
58 ctx.logJsEvalResponse(); 57 ctx.logJsEvalResponse();
59 ctx.tellNext(msg, filterResult ? "True" : "False"); 58 ctx.tellNext(msg, filterResult ? "True" : "False");
@@ -53,7 +53,7 @@ public class TbTransformMsgNode extends TbAbstractTransformNode { @@ -53,7 +53,7 @@ public class TbTransformMsgNode extends TbAbstractTransformNode {
53 @Override 53 @Override
54 protected ListenableFuture<TbMsg> transform(TbContext ctx, TbMsg msg) { 54 protected ListenableFuture<TbMsg> transform(TbContext ctx, TbMsg msg) {
55 ctx.logJsEvalRequest(); 55 ctx.logJsEvalRequest();
56 - return ctx.getJsExecutor().executeAsync(() -> jsEngine.executeUpdate(msg)); 56 + return jsEngine.executeUpdateAsync(msg);
57 } 57 }
58 58
59 @Override 59 @Override