Showing
10 changed files
with
185 additions
and
33 deletions
@@ -125,7 +125,7 @@ class DefaultTbContext implements TbContext { | @@ -125,7 +125,7 @@ class DefaultTbContext implements TbContext { | ||
125 | 125 | ||
126 | @Override | 126 | @Override |
127 | public TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) { | 127 | public TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) { |
128 | - return new TbMsg(origMsg.getId(), type, originator, metaData.copy(), data, origMsg.getRuleChainId(), origMsg.getRuleNodeId(), mainCtx.getQueuePartitionId()); | 128 | + return new TbMsg(origMsg.getId(), type, originator, metaData.copy(), origMsg.getDataType(), data, origMsg.getTransactionData(), origMsg.getRuleChainId(), origMsg.getRuleNodeId(), mainCtx.getQueuePartitionId()); |
129 | } | 129 | } |
130 | 130 | ||
131 | @Override | 131 | @Override |
@@ -279,6 +279,9 @@ public class TelemetryController extends BaseController { | @@ -279,6 +279,9 @@ public class TelemetryController extends BaseController { | ||
279 | deleteFromTs = 0L; | 279 | deleteFromTs = 0L; |
280 | deleteToTs = System.currentTimeMillis(); | 280 | deleteToTs = System.currentTimeMillis(); |
281 | } else { | 281 | } else { |
282 | + if (startTs == null || endTs == null) { | ||
283 | + return getImmediateDeferredResult("StartTs and endTs could not be empty when deleteAllDataForKeys equals [false]", HttpStatus.BAD_REQUEST); | ||
284 | + } | ||
282 | deleteFromTs = startTs; | 285 | deleteFromTs = startTs; |
283 | deleteToTs = endTs; | 286 | deleteToTs = endTs; |
284 | } | 287 | } |
@@ -15,40 +15,92 @@ | @@ -15,40 +15,92 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.service.transaction; | 16 | package org.thingsboard.server.service.transaction; |
17 | 17 | ||
18 | -import com.google.common.util.concurrent.FutureCallback; | ||
19 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
20 | import org.springframework.beans.factory.annotation.Value; | 19 | import org.springframework.beans.factory.annotation.Value; |
21 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
22 | import org.thingsboard.rule.engine.api.RuleChainTransactionService; | 21 | import org.thingsboard.rule.engine.api.RuleChainTransactionService; |
22 | +import org.thingsboard.rule.engine.api.TbContext; | ||
23 | import org.thingsboard.server.common.data.id.EntityId; | 23 | import org.thingsboard.server.common.data.id.EntityId; |
24 | import org.thingsboard.server.common.msg.TbMsg; | 24 | import org.thingsboard.server.common.msg.TbMsg; |
25 | 25 | ||
26 | -import java.util.Queue; | 26 | +import java.util.concurrent.BlockingQueue; |
27 | import java.util.concurrent.ConcurrentHashMap; | 27 | import java.util.concurrent.ConcurrentHashMap; |
28 | import java.util.concurrent.ConcurrentMap; | 28 | import java.util.concurrent.ConcurrentMap; |
29 | import java.util.concurrent.LinkedBlockingQueue; | 29 | import java.util.concurrent.LinkedBlockingQueue; |
30 | +import java.util.concurrent.locks.Lock; | ||
31 | +import java.util.concurrent.locks.ReentrantLock; | ||
32 | +import java.util.function.Consumer; | ||
30 | 33 | ||
31 | @Service | 34 | @Service |
32 | @Slf4j | 35 | @Slf4j |
33 | public class BaseRuleChainTransactionService implements RuleChainTransactionService { | 36 | public class BaseRuleChainTransactionService implements RuleChainTransactionService { |
34 | 37 | ||
35 | @Value("${actors.rule.transaction.queue_size}") | 38 | @Value("${actors.rule.transaction.queue_size}") |
36 | - private int queueSize; | 39 | + private int finalQueueSize; |
37 | 40 | ||
38 | - private final ConcurrentMap<EntityId, Queue<TbMsg>> transactionMap = new ConcurrentHashMap<>(); | 41 | + private final Lock transactionLock = new ReentrantLock(); |
42 | + private final ConcurrentMap<EntityId, BlockingQueue<TbTransactionTask>> transactionMap = new ConcurrentHashMap<>(); | ||
39 | 43 | ||
40 | - @Override | ||
41 | - public void beginTransaction(EntityId entityId, FutureCallback<Void> callback) { | ||
42 | - | ||
43 | - | ||
44 | - transactionMap.computeIfAbsent(entityId, id -> new LinkedBlockingQueue<>(queueSize)); | 44 | + //TODO: add delete on timeout from queue -> onFailure accept |
45 | 45 | ||
46 | - log.info("[{}]", queueSize); | 46 | + @Override |
47 | + public void beginTransaction(TbContext ctx, TbMsg msg, Consumer<TbMsg> onStart, Consumer<TbMsg> onEnd, Consumer<Throwable> onFailure) { | ||
48 | + BlockingQueue<TbTransactionTask> queue = transactionMap.computeIfAbsent(msg.getTransactionData().getOriginatorId(), id -> | ||
49 | + new LinkedBlockingQueue<>(finalQueueSize)); | ||
50 | + transactionLock.lock(); | ||
51 | + try { | ||
52 | + TbTransactionTask task = new TbTransactionTask(msg, onStart, onEnd, onFailure); | ||
53 | + int queueSize = queue.size(); | ||
54 | + if (queueSize >= finalQueueSize) { | ||
55 | + onFailure.accept(new RuntimeException("Queue has no space!")); | ||
56 | + } else { | ||
57 | + addMsgToQueue(queue, task, onFailure); | ||
58 | + if (queueSize == 0) { | ||
59 | + onStart.accept(msg); | ||
60 | + } else { | ||
61 | + log.info("Msg [{}] [{}] is waiting to start transaction!", msg.getId(), msg.getType()); | ||
62 | + } | ||
63 | + } | ||
64 | + } finally { | ||
65 | + transactionLock.unlock(); | ||
66 | + } | ||
67 | + } | ||
47 | 68 | ||
69 | + private void addMsgToQueue(BlockingQueue<TbTransactionTask> queue, TbTransactionTask task, Consumer<Throwable> onFailure) { | ||
70 | + try { | ||
71 | + queue.add(task); | ||
72 | + log.info("Added msg to queue, size: [{}]", queue.size()); | ||
73 | + } catch (Exception e) { | ||
74 | + log.error("Error when trying to add msg [{}] to the queue", task.getMsg(), e); | ||
75 | + onFailure.accept(e); | ||
76 | + } | ||
48 | } | 77 | } |
49 | 78 | ||
50 | @Override | 79 | @Override |
51 | - public void endTransaction() { | 80 | + public boolean endTransaction(TbContext ctx, TbMsg msg, Consumer<Throwable> onFailure) { |
81 | + transactionLock.lock(); | ||
82 | + try { | ||
83 | + BlockingQueue<TbTransactionTask> queue = transactionMap.get(msg.getTransactionData().getOriginatorId()); | ||
84 | + try { | ||
85 | + TbTransactionTask currentTask = queue.element(); | ||
86 | + if (currentTask.getMsg().getTransactionData().getTransactionId().equals(msg.getTransactionData().getTransactionId())) { | ||
87 | + queue.remove(); | ||
88 | + log.info("Removed msg from queue, size [{}]", queue.size()); | ||
89 | + currentTask.getOnEnd().accept(currentTask.getMsg()); | ||
52 | 90 | ||
91 | + TbTransactionTask nextTask = queue.peek(); | ||
92 | + if (nextTask != null) { | ||
93 | + nextTask.getOnStart().accept(nextTask.getMsg()); | ||
94 | + } | ||
95 | + } | ||
96 | + } catch (Exception e) { | ||
97 | + log.error("Queue is empty!", queue); | ||
98 | + onFailure.accept(e); | ||
99 | + return true; | ||
100 | + } | ||
101 | + } finally { | ||
102 | + transactionLock.unlock(); | ||
103 | + } | ||
104 | + return false; | ||
53 | } | 105 | } |
54 | } | 106 | } |
application/src/main/java/org/thingsboard/server/service/transaction/TbTransactionTask.java
0 → 100644
1 | +package org.thingsboard.server.service.transaction; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | +import org.thingsboard.server.common.msg.TbMsg; | ||
5 | + | ||
6 | +import java.util.function.Consumer; | ||
7 | + | ||
8 | +@Data | ||
9 | +public final class TbTransactionTask { | ||
10 | + | ||
11 | + private final TbMsg msg; | ||
12 | + private final Consumer<TbMsg> onStart; | ||
13 | + private final Consumer<TbMsg> onEnd; | ||
14 | + private final Consumer<Throwable> onFailure; | ||
15 | + | ||
16 | +} |
@@ -41,6 +41,7 @@ public final class TbMsg implements Serializable { | @@ -41,6 +41,7 @@ public final class TbMsg implements Serializable { | ||
41 | private final TbMsgMetaData metaData; | 41 | private final TbMsgMetaData metaData; |
42 | private final TbMsgDataType dataType; | 42 | private final TbMsgDataType dataType; |
43 | private final String data; | 43 | private final String data; |
44 | + private final TbMsgTransactionData transactionData; | ||
44 | 45 | ||
45 | //The following fields are not persisted to DB, because they can always be recovered from the context; | 46 | //The following fields are not persisted to DB, because they can always be recovered from the context; |
46 | private final RuleChainId ruleChainId; | 47 | private final RuleChainId ruleChainId; |
@@ -55,11 +56,17 @@ public final class TbMsg implements Serializable { | @@ -55,11 +56,17 @@ public final class TbMsg implements Serializable { | ||
55 | this.metaData = metaData; | 56 | this.metaData = metaData; |
56 | this.data = data; | 57 | this.data = data; |
57 | this.dataType = TbMsgDataType.JSON; | 58 | this.dataType = TbMsgDataType.JSON; |
59 | + this.transactionData = null; | ||
58 | this.ruleChainId = ruleChainId; | 60 | this.ruleChainId = ruleChainId; |
59 | this.ruleNodeId = ruleNodeId; | 61 | this.ruleNodeId = ruleNodeId; |
60 | this.clusterPartition = clusterPartition; | 62 | this.clusterPartition = clusterPartition; |
61 | } | 63 | } |
62 | 64 | ||
65 | + public TbMsg(UUID id, String type, EntityId originator, TbMsgMetaData metaData, TbMsgDataType dataType, String data, | ||
66 | + RuleChainId ruleChainId, RuleNodeId ruleNodeId, long clusterPartition) { | ||
67 | + this(id, type, originator, metaData, dataType, data, null, ruleChainId, ruleNodeId, clusterPartition); | ||
68 | + } | ||
69 | + | ||
63 | public static ByteBuffer toBytes(TbMsg msg) { | 70 | public static ByteBuffer toBytes(TbMsg msg) { |
64 | MsgProtos.TbMsgProto.Builder builder = MsgProtos.TbMsgProto.newBuilder(); | 71 | MsgProtos.TbMsgProto.Builder builder = MsgProtos.TbMsgProto.newBuilder(); |
65 | builder.setId(msg.getId().toString()); | 72 | builder.setId(msg.getId().toString()); |
@@ -82,6 +89,16 @@ public final class TbMsg implements Serializable { | @@ -82,6 +89,16 @@ public final class TbMsg implements Serializable { | ||
82 | builder.setMetaData(MsgProtos.TbMsgMetaDataProto.newBuilder().putAllData(msg.getMetaData().getData()).build()); | 89 | builder.setMetaData(MsgProtos.TbMsgMetaDataProto.newBuilder().putAllData(msg.getMetaData().getData()).build()); |
83 | } | 90 | } |
84 | 91 | ||
92 | + TbMsgTransactionData transactionData = msg.getTransactionData(); | ||
93 | + if (transactionData != null) { | ||
94 | + MsgProtos.TbMsgTransactionDataProto.Builder transactionBuilder = MsgProtos.TbMsgTransactionDataProto.newBuilder(); | ||
95 | + transactionBuilder.setId(transactionData.getTransactionId().toString()); | ||
96 | + transactionBuilder.setEntityType(transactionData.getOriginatorId().getEntityType().name()); | ||
97 | + transactionBuilder.setEntityIdMSB(transactionData.getOriginatorId().getId().getMostSignificantBits()); | ||
98 | + transactionBuilder.setEntityIdLSB(transactionData.getOriginatorId().getId().getLeastSignificantBits()); | ||
99 | + builder.setTransactionData(transactionBuilder.build()); | ||
100 | + } | ||
101 | + | ||
85 | builder.setDataType(msg.getDataType().ordinal()); | 102 | builder.setDataType(msg.getDataType().ordinal()); |
86 | builder.setData(msg.getData()); | 103 | builder.setData(msg.getData()); |
87 | byte[] bytes = builder.build().toByteArray(); | 104 | byte[] bytes = builder.build().toByteArray(); |
@@ -92,6 +109,9 @@ public final class TbMsg implements Serializable { | @@ -92,6 +109,9 @@ public final class TbMsg implements Serializable { | ||
92 | try { | 109 | try { |
93 | MsgProtos.TbMsgProto proto = MsgProtos.TbMsgProto.parseFrom(buffer.array()); | 110 | MsgProtos.TbMsgProto proto = MsgProtos.TbMsgProto.parseFrom(buffer.array()); |
94 | TbMsgMetaData metaData = new TbMsgMetaData(proto.getMetaData().getDataMap()); | 111 | TbMsgMetaData metaData = new TbMsgMetaData(proto.getMetaData().getDataMap()); |
112 | + EntityId transactionEntityId = EntityIdFactory.getByTypeAndUuid(proto.getTransactionData().getEntityType(), | ||
113 | + new UUID(proto.getTransactionData().getEntityIdMSB(), proto.getTransactionData().getEntityIdLSB())); | ||
114 | + TbMsgTransactionData transactionData = new TbMsgTransactionData(UUID.fromString(proto.getTransactionData().getId()), transactionEntityId); | ||
95 | EntityId entityId = EntityIdFactory.getByTypeAndUuid(proto.getEntityType(), new UUID(proto.getEntityIdMSB(), proto.getEntityIdLSB())); | 115 | EntityId entityId = EntityIdFactory.getByTypeAndUuid(proto.getEntityType(), new UUID(proto.getEntityIdMSB(), proto.getEntityIdLSB())); |
96 | RuleChainId ruleChainId = new RuleChainId(new UUID(proto.getRuleChainIdMSB(), proto.getRuleChainIdLSB())); | 116 | RuleChainId ruleChainId = new RuleChainId(new UUID(proto.getRuleChainIdMSB(), proto.getRuleChainIdLSB())); |
97 | RuleNodeId ruleNodeId = null; | 117 | RuleNodeId ruleNodeId = null; |
@@ -99,7 +119,7 @@ public final class TbMsg implements Serializable { | @@ -99,7 +119,7 @@ public final class TbMsg implements Serializable { | ||
99 | ruleNodeId = new RuleNodeId(new UUID(proto.getRuleNodeIdMSB(), proto.getRuleNodeIdLSB())); | 119 | ruleNodeId = new RuleNodeId(new UUID(proto.getRuleNodeIdMSB(), proto.getRuleNodeIdLSB())); |
100 | } | 120 | } |
101 | TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; | 121 | TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; |
102 | - return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, dataType, proto.getData(), ruleChainId, ruleNodeId, proto.getClusterPartition()); | 122 | + return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, dataType, proto.getData(), transactionData, ruleChainId, ruleNodeId, proto.getClusterPartition()); |
103 | } catch (InvalidProtocolBufferException e) { | 123 | } catch (InvalidProtocolBufferException e) { |
104 | throw new IllegalStateException("Could not parse protobuf for TbMsg", e); | 124 | throw new IllegalStateException("Could not parse protobuf for TbMsg", e); |
105 | } | 125 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2018 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.msg; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.id.EntityId; | ||
20 | + | ||
21 | +import java.io.Serializable; | ||
22 | +import java.util.UUID; | ||
23 | + | ||
24 | +@Data | ||
25 | +public final class TbMsgTransactionData implements Serializable { | ||
26 | + | ||
27 | + private final UUID transactionId; | ||
28 | + private final EntityId originatorId; | ||
29 | + | ||
30 | +} |
@@ -23,6 +23,13 @@ message TbMsgMetaDataProto { | @@ -23,6 +23,13 @@ message TbMsgMetaDataProto { | ||
23 | map<string, string> data = 1; | 23 | map<string, string> data = 1; |
24 | } | 24 | } |
25 | 25 | ||
26 | +message TbMsgTransactionDataProto { | ||
27 | + string id = 1; | ||
28 | + string entityType = 2; | ||
29 | + int64 entityIdMSB = 3; | ||
30 | + int64 entityIdLSB = 4; | ||
31 | +} | ||
32 | + | ||
26 | message TbMsgProto { | 33 | message TbMsgProto { |
27 | string id = 1; | 34 | string id = 1; |
28 | string type = 2; | 35 | string type = 2; |
@@ -39,7 +46,9 @@ message TbMsgProto { | @@ -39,7 +46,9 @@ message TbMsgProto { | ||
39 | 46 | ||
40 | TbMsgMetaDataProto metaData = 11; | 47 | TbMsgMetaDataProto metaData = 11; |
41 | 48 | ||
42 | - int32 dataType = 12; | ||
43 | - string data = 13; | 49 | + TbMsgTransactionDataProto transactionData = 12; |
50 | + | ||
51 | + int32 dataType = 13; | ||
52 | + string data = 14; | ||
44 | 53 | ||
45 | } | 54 | } |
@@ -15,13 +15,15 @@ | @@ -15,13 +15,15 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.rule.engine.api; | 16 | package org.thingsboard.rule.engine.api; |
17 | 17 | ||
18 | -import com.google.common.util.concurrent.FutureCallback; | ||
19 | -import org.thingsboard.server.common.data.id.EntityId; | 18 | +import org.thingsboard.server.common.msg.TbMsg; |
19 | + | ||
20 | +import java.util.concurrent.Callable; | ||
21 | +import java.util.function.Consumer; | ||
20 | 22 | ||
21 | public interface RuleChainTransactionService { | 23 | public interface RuleChainTransactionService { |
22 | 24 | ||
23 | - void beginTransaction(EntityId entityId, FutureCallback<Void> callback); | 25 | + void beginTransaction(TbContext ctx, TbMsg msg, Consumer<TbMsg> onStart, Consumer<TbMsg> onEnd, Consumer<Throwable> onFailure); |
24 | 26 | ||
25 | - void endTransaction(); | 27 | + boolean endTransaction(TbContext ctx, TbMsg msg, Consumer<Throwable> onFailure); |
26 | 28 | ||
27 | } | 29 | } |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.rule.engine.transaction; | 16 | package org.thingsboard.rule.engine.transaction; |
17 | 17 | ||
18 | -import com.google.common.util.concurrent.FutureCallback; | ||
19 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
20 | import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; | 19 | import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; |
21 | import org.thingsboard.rule.engine.api.RuleNode; | 20 | import org.thingsboard.rule.engine.api.RuleNode; |
@@ -26,9 +25,14 @@ import org.thingsboard.rule.engine.api.TbNodeException; | @@ -26,9 +25,14 @@ import org.thingsboard.rule.engine.api.TbNodeException; | ||
26 | import org.thingsboard.rule.engine.api.util.TbNodeUtils; | 25 | import org.thingsboard.rule.engine.api.util.TbNodeUtils; |
27 | import org.thingsboard.server.common.data.plugin.ComponentType; | 26 | import org.thingsboard.server.common.data.plugin.ComponentType; |
28 | import org.thingsboard.server.common.msg.TbMsg; | 27 | import org.thingsboard.server.common.msg.TbMsg; |
28 | +import org.thingsboard.server.common.msg.TbMsgDataType; | ||
29 | +import org.thingsboard.server.common.msg.TbMsgTransactionData; | ||
29 | 30 | ||
31 | +import java.util.UUID; | ||
30 | import java.util.concurrent.ExecutionException; | 32 | import java.util.concurrent.ExecutionException; |
31 | 33 | ||
34 | +import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; | ||
35 | + | ||
32 | @Slf4j | 36 | @Slf4j |
33 | @RuleNode( | 37 | @RuleNode( |
34 | type = ComponentType.ACTION, | 38 | type = ComponentType.ACTION, |
@@ -50,9 +54,21 @@ public class TbTransactionBeginNode implements TbNode { | @@ -50,9 +54,21 @@ public class TbTransactionBeginNode implements TbNode { | ||
50 | 54 | ||
51 | @Override | 55 | @Override |
52 | public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException { | 56 | public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException { |
53 | - FutureCallback<Void> callback = null; | 57 | + log.info("Msg in - [{}] [{}]", msg.getId(), msg.getType()); |
58 | + | ||
59 | + TbMsgTransactionData transactionData = new TbMsgTransactionData(UUID.randomUUID(), msg.getOriginator()); | ||
60 | + | ||
61 | + TbMsg tbMsg = new TbMsg(msg.getId(), msg.getType(), msg.getOriginator(), msg.getMetaData(), TbMsgDataType.JSON, | ||
62 | + msg.getData(), transactionData, msg.getRuleChainId(), msg.getRuleNodeId(), msg.getClusterPartition()); | ||
54 | 63 | ||
55 | - ctx.getRuleChainTransactionService().beginTransaction(msg.getOriginator(), callback); | 64 | + ctx.getRuleChainTransactionService().beginTransaction(ctx, tbMsg, onStart -> { |
65 | + log.info("Transaction starting... [{}] [{}]", tbMsg.getId(), tbMsg.getType()); | ||
66 | + ctx.tellNext(tbMsg, SUCCESS); | ||
67 | + }, onEnd -> log.info("Transaction ended successfully... [{}] [{}]", tbMsg.getId(), tbMsg.getType()), | ||
68 | + throwable -> { | ||
69 | + log.error("Transaction failed due to queue size restriction! [{}] [{}]", tbMsg.getId(), tbMsg.getType(), throwable); | ||
70 | + ctx.tellFailure(tbMsg, throwable); | ||
71 | + }); | ||
56 | } | 72 | } |
57 | 73 | ||
58 | @Override | 74 | @Override |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2018 The Thingsboard Authors | 2 | * Copyright © 2016-2018 The Thingsboard Authors |
3 | - * | 3 | + * <p> |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at | 6 | * You may obtain a copy of the License at |
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | 7 | + * <p> |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * <p> | ||
10 | * Unless required by applicable law or agreed to in writing, software | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
@@ -17,19 +17,19 @@ package org.thingsboard.rule.engine.transaction; | @@ -17,19 +17,19 @@ package org.thingsboard.rule.engine.transaction; | ||
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; | 19 | import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; |
20 | -import org.thingsboard.rule.engine.api.RuleChainTransactionService; | ||
21 | import org.thingsboard.rule.engine.api.RuleNode; | 20 | import org.thingsboard.rule.engine.api.RuleNode; |
22 | import org.thingsboard.rule.engine.api.TbContext; | 21 | import org.thingsboard.rule.engine.api.TbContext; |
23 | import org.thingsboard.rule.engine.api.TbNode; | 22 | import org.thingsboard.rule.engine.api.TbNode; |
24 | import org.thingsboard.rule.engine.api.TbNodeConfiguration; | 23 | import org.thingsboard.rule.engine.api.TbNodeConfiguration; |
25 | import org.thingsboard.rule.engine.api.TbNodeException; | 24 | import org.thingsboard.rule.engine.api.TbNodeException; |
26 | import org.thingsboard.rule.engine.api.util.TbNodeUtils; | 25 | import org.thingsboard.rule.engine.api.util.TbNodeUtils; |
27 | -import org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNodeConfiguration; | ||
28 | import org.thingsboard.server.common.data.plugin.ComponentType; | 26 | import org.thingsboard.server.common.data.plugin.ComponentType; |
29 | import org.thingsboard.server.common.msg.TbMsg; | 27 | import org.thingsboard.server.common.msg.TbMsg; |
30 | 28 | ||
31 | import java.util.concurrent.ExecutionException; | 29 | import java.util.concurrent.ExecutionException; |
32 | 30 | ||
31 | +import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; | ||
32 | + | ||
33 | @Slf4j | 33 | @Slf4j |
34 | @RuleNode( | 34 | @RuleNode( |
35 | type = ComponentType.ACTION, | 35 | type = ComponentType.ACTION, |
@@ -51,7 +51,11 @@ public class TbTransactionEndNode implements TbNode { | @@ -51,7 +51,11 @@ public class TbTransactionEndNode implements TbNode { | ||
51 | 51 | ||
52 | @Override | 52 | @Override |
53 | public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException { | 53 | public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException { |
54 | - | 54 | + boolean isFailed = ctx.getRuleChainTransactionService().endTransaction(ctx, msg, throwable -> ctx.tellFailure(msg, throwable)); |
55 | + if (!isFailed) { | ||
56 | + ctx.tellNext(msg, SUCCESS); | ||
57 | + } | ||
58 | + log.info("Msg out - [{}] [{}]", msg.getId(), msg.getType()); | ||
55 | } | 59 | } |
56 | 60 | ||
57 | @Override | 61 | @Override |