Commit 1bf196bfdf2e3aa3ce5c3a7e5cdfbcfe47a6afc0

Authored by Andrew Shvayka
1 parent fa27fd42

ThingsBoard Rule Nodes improvements

... ... @@ -182,12 +182,14 @@ public class BaseRuleChainTransactionService implements RuleChainTransactionServ
182 182 while (true) {
183 183 TbTransactionTask transactionTask = timeoutQueue.peek();
184 184 if (transactionTask != null) {
  185 + long sleepDuration = 0L;
185 186 transactionLock.lock();
186 187 try {
187 188 if (transactionTask.isCompleted()) {
188 189 timeoutQueue.poll();
189 190 } else {
190   - if (System.currentTimeMillis() > transactionTask.getExpirationTime()) {
  191 + long expIn = transactionTask.getExpirationTime() - System.currentTimeMillis();
  192 + if (expIn < 0) {
191 193 log.trace("Task has expired! Deleting it...[{}][{}]", transactionTask.getMsg().getId(), transactionTask.getMsg().getType());
192 194 timeoutQueue.poll();
193 195 executeOnFailure(transactionTask.getOnFailure(), "Task has expired!");
... ... @@ -201,17 +203,20 @@ public class BaseRuleChainTransactionService implements RuleChainTransactionServ
201 203 }
202 204 }
203 205 } else {
204   - try {
205   - log.trace("Task has not expired! Continue executing...[{}][{}]", transactionTask.getMsg().getId(), transactionTask.getMsg().getType());
206   - TimeUnit.MILLISECONDS.sleep(duration);
207   - } catch (InterruptedException e) {
208   - throw new IllegalStateException("Thread interrupted", e);
209   - }
  206 + sleepDuration = Math.min(expIn, duration);
210 207 }
211 208 }
212 209 } finally {
213 210 transactionLock.unlock();
214 211 }
  212 + if (sleepDuration > 0L) {
  213 + try {
  214 + log.trace("Task has not expired! Continue executing...[{}][{}]", transactionTask.getMsg().getId(), transactionTask.getMsg().getType());
  215 + TimeUnit.MILLISECONDS.sleep(sleepDuration);
  216 + } catch (InterruptedException e) {
  217 + throw new IllegalStateException("Thread interrupted", e);
  218 + }
  219 + }
215 220 } else {
216 221 try {
217 222 log.trace("Queue is empty, waiting for tasks!");
... ...
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbTransactionBeginNode.java
... ... @@ -35,13 +35,15 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
35 35 @Slf4j
36 36 @RuleNode(
37 37 type = ComponentType.ACTION,
38   - name = "transaction start",
  38 + name = "synchronization start",
39 39 configClazz = EmptyNodeConfiguration.class,
40   - nodeDescription = "",
41   - nodeDetails = "",
  40 + nodeDescription = "Starts synchronization of message processing based on message originator",
  41 + nodeDetails = "This node should be used together with \"synchronization end\" node. \n This node will put messages into queue based on message originator id. \n" +
  42 + "Subsequent messages will not be processed until the previous message processing is completed or timeout event occurs.\n" +
  43 + "Size of the queue per originator and timeout values are configurable on a system level",
42 44 uiResources = {"static/rulenode/rulenode-core-config.js"},
43 45 configDirective = "tbNodeEmptyConfig")
44   -public class TbTransactionBeginNode implements TbNode {
  46 +public class TbSynchronizationBeginNode implements TbNode {
45 47
46 48 private EmptyNodeConfiguration config;
47 49
... ... @@ -51,7 +53,7 @@ public class TbTransactionBeginNode implements TbNode {
51 53 }
52 54
53 55 @Override
54   - public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException {
  56 + public void onMsg(TbContext ctx, TbMsg msg) {
55 57 log.trace("Msg enters transaction - [{}][{}]", msg.getId(), msg.getType());
56 58
57 59 TbMsgTransactionData transactionData = new TbMsgTransactionData(msg.getId(), msg.getOriginator());
... ... @@ -63,7 +65,7 @@ public class TbTransactionBeginNode implements TbNode {
63 65 ctx.tellNext(startMsg, SUCCESS);
64 66 }, endMsg -> log.trace("Transaction ended successfully...[{}][{}]", endMsg.getId(), endMsg.getType()),
65 67 throwable -> {
66   - log.error("Transaction failed! [{}][{}]", tbMsg.getId(), tbMsg.getType(), throwable);
  68 + log.trace("Transaction failed! [{}][{}]", tbMsg.getId(), tbMsg.getType(), throwable);
67 69 ctx.tellFailure(tbMsg, throwable);
68 70 });
69 71 }
... ...
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java renamed from rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbTransactionEndNode.java
... ... @@ -33,14 +33,14 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
33 33 @Slf4j
34 34 @RuleNode(
35 35 type = ComponentType.ACTION,
36   - name = "transaction end",
  36 + name = "synchronization end",
37 37 configClazz = EmptyNodeConfiguration.class,
38   - nodeDescription = "",
  38 + nodeDescription = "Stops synchronization of message processing based on message originator",
39 39 nodeDetails = "",
40 40 uiResources = {"static/rulenode/rulenode-core-config.js"},
41 41 configDirective = ("tbNodeEmptyConfig")
42 42 )
43   -public class TbTransactionEndNode implements TbNode {
  43 +public class TbSynchronizationEndNode implements TbNode {
44 44
45 45 private EmptyNodeConfiguration config;
46 46
... ... @@ -50,7 +50,7 @@ public class TbTransactionEndNode implements TbNode {
50 50 }
51 51
52 52 @Override
53   - public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException {
  53 + public void onMsg(TbContext ctx, TbMsg msg) {
54 54 ctx.getRuleChainTransactionService().endTransaction(msg,
55 55 successMsg -> ctx.tellNext(successMsg, SUCCESS),
56 56 throwable -> ctx.tellFailure(msg, throwable));
... ...