Commit 3eaae1ef32cf601ca06001e95a5f5f130c4d74a8

Authored by Andrii Shvaika
1 parent ff3fd89a

Statistics Implementation

Showing 64 changed files with 976 additions and 720 deletions
@@ -24,10 +24,9 @@ import akka.actor.Terminated; @@ -24,10 +24,9 @@ import akka.actor.Terminated;
24 import com.google.common.collect.BiMap; 24 import com.google.common.collect.BiMap;
25 import com.google.common.collect.HashBiMap; 25 import com.google.common.collect.HashBiMap;
26 import org.thingsboard.server.actors.ActorSystemContext; 26 import org.thingsboard.server.actors.ActorSystemContext;
27 -import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; 27 +import org.thingsboard.server.actors.service.ContextAwareActor;
28 import org.thingsboard.server.actors.service.ContextBasedCreator; 28 import org.thingsboard.server.actors.service.ContextBasedCreator;
29 import org.thingsboard.server.actors.service.DefaultActorService; 29 import org.thingsboard.server.actors.service.DefaultActorService;
30 -import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager;  
31 import org.thingsboard.server.actors.tenant.TenantActor; 30 import org.thingsboard.server.actors.tenant.TenantActor;
32 import org.thingsboard.server.common.data.EntityType; 31 import org.thingsboard.server.common.data.EntityType;
33 import org.thingsboard.server.common.data.Tenant; 32 import org.thingsboard.server.common.data.Tenant;
@@ -37,16 +36,14 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; @@ -37,16 +36,14 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
37 import org.thingsboard.server.common.msg.MsgType; 36 import org.thingsboard.server.common.msg.MsgType;
38 import org.thingsboard.server.common.msg.TbActorMsg; 37 import org.thingsboard.server.common.msg.TbActorMsg;
39 import org.thingsboard.server.common.msg.aware.TenantAwareMsg; 38 import org.thingsboard.server.common.msg.aware.TenantAwareMsg;
40 -import org.thingsboard.server.common.msg.cluster.SendToClusterMsg;  
41 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 39 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
42 -import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;  
43 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; 40 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;
44 -import org.thingsboard.server.common.msg.queue.ServiceType; 41 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
45 import org.thingsboard.server.dao.model.ModelConstants; 42 import org.thingsboard.server.dao.model.ModelConstants;
46 import org.thingsboard.server.dao.tenant.TenantService; 43 import org.thingsboard.server.dao.tenant.TenantService;
47 import scala.concurrent.duration.Duration; 44 import scala.concurrent.duration.Duration;
48 45
49 -public class AppActor extends RuleChainManagerActor { 46 +public class AppActor extends ContextAwareActor {
50 47
51 private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); 48 private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID);
52 private final TenantService tenantService; 49 private final TenantService tenantService;
@@ -54,7 +51,7 @@ public class AppActor extends RuleChainManagerActor { @@ -54,7 +51,7 @@ public class AppActor extends RuleChainManagerActor {
54 private boolean ruleChainsInitialized; 51 private boolean ruleChainsInitialized;
55 52
56 private AppActor(ActorSystemContext systemContext) { 53 private AppActor(ActorSystemContext systemContext) {
57 - super(systemContext, new SystemRuleChainManager(systemContext)); 54 + super(systemContext);
58 this.tenantService = systemContext.getTenantService(); 55 this.tenantService = systemContext.getTenantService();
59 this.tenantActors = HashBiMap.create(); 56 this.tenantActors = HashBiMap.create();
60 } 57 }
@@ -80,9 +77,6 @@ public class AppActor extends RuleChainManagerActor { @@ -80,9 +77,6 @@ public class AppActor extends RuleChainManagerActor {
80 switch (msg.getMsgType()) { 77 switch (msg.getMsgType()) {
81 case APP_INIT_MSG: 78 case APP_INIT_MSG:
82 break; 79 break;
83 - case SEND_TO_CLUSTER_MSG:  
84 - onPossibleClusterMsg((SendToClusterMsg) msg);  
85 - break;  
86 case PARTITION_CHANGE_MSG: 80 case PARTITION_CHANGE_MSG:
87 broadcast(msg); 81 broadcast(msg);
88 break; 82 break;
@@ -98,7 +92,6 @@ public class AppActor extends RuleChainManagerActor { @@ -98,7 +92,6 @@ public class AppActor extends RuleChainManagerActor {
98 case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: 92 case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG:
99 case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: 93 case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG:
100 case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: 94 case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG:
101 - case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG:  
102 onToDeviceActorMsg((TenantAwareMsg) msg); 95 onToDeviceActorMsg((TenantAwareMsg) msg);
103 break; 96 break;
104 default: 97 default:
@@ -110,7 +103,6 @@ public class AppActor extends RuleChainManagerActor { @@ -110,7 +103,6 @@ public class AppActor extends RuleChainManagerActor {
110 private void initRuleChainsAndTenantActors() { 103 private void initRuleChainsAndTenantActors() {
111 log.info("Starting main system actor."); 104 log.info("Starting main system actor.");
112 try { 105 try {
113 - initRuleChains();  
114 if (systemContext.isTenantComponentsInitEnabled()) { 106 if (systemContext.isTenantComponentsInitEnabled()) {
115 PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); 107 PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT);
116 for (Tenant tenant : tenantIterator) { 108 for (Tenant tenant : tenantIterator) {
@@ -125,37 +117,22 @@ public class AppActor extends RuleChainManagerActor { @@ -125,37 +117,22 @@ public class AppActor extends RuleChainManagerActor {
125 } 117 }
126 } 118 }
127 119
128 - private void onPossibleClusterMsg(SendToClusterMsg msg) {  
129 - //TODO 2.5  
130 -// Optional<ServerAddress> address = systemContext.getRoutingService().resolveById(msg.getEntityId());  
131 -// if (address.isPresent()) {  
132 -  
133 -// systemContext.getRpcService().tell(  
134 -// systemContext.getEncodingService().convertToProtoDataMessage(address.get(), msg.getMsg()));  
135 -// } else {  
136 - self().tell(msg.getMsg(), ActorRef.noSender());  
137 -// }  
138 - }  
139 -  
140 private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) { 120 private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) {
141 if (SYSTEM_TENANT.equals(msg.getTenantId())) { 121 if (SYSTEM_TENANT.equals(msg.getTenantId())) {
142 -// this may be a notification about system entities created.  
143 -// log.warn("[{}] Invalid service to rule engine msg called. System messages are not supported yet: {}", SYSTEM_TENANT, msg); 122 + msg.getTbMsg().getCallback().onFailure(new RuleEngineException("Message has system tenant id!"));
144 } else { 123 } else {
145 getOrCreateTenantActor(msg.getTenantId()).tell(msg, self()); 124 getOrCreateTenantActor(msg.getTenantId()).tell(msg, self());
146 } 125 }
147 } 126 }
148 127
149 - @Override  
150 protected void broadcast(Object msg) { 128 protected void broadcast(Object msg) {
151 - super.broadcast(msg);  
152 tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); 129 tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender()));
153 } 130 }
154 131
155 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { 132 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) {
156 ActorRef target = null; 133 ActorRef target = null;
157 if (SYSTEM_TENANT.equals(msg.getTenantId())) { 134 if (SYSTEM_TENANT.equals(msg.getTenantId())) {
158 - target = getEntityActorRef(msg.getEntityId()); 135 + log.warn("Message has system tenant id: {}", msg);
159 } else { 136 } else {
160 if (msg.getEntityId().getEntityType() == EntityType.TENANT 137 if (msg.getEntityId().getEntityType() == EntityType.TENANT
161 && msg.getEvent() == ComponentLifecycleEvent.DELETED) { 138 && msg.getEvent() == ComponentLifecycleEvent.DELETED) {
@@ -56,7 +56,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMs @@ -56,7 +56,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMs
56 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; 56 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
57 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; 57 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
58 import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; 58 import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
59 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 59 +import org.thingsboard.server.common.msg.queue.TbCallback;
60 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; 60 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
61 import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; 61 import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg;
62 import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg; 62 import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg;
@@ -213,7 +213,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { @@ -213,7 +213,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
213 213
214 void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) { 214 void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) {
215 TransportToDeviceActorMsg msg = wrapper.getMsg(); 215 TransportToDeviceActorMsg msg = wrapper.getMsg();
216 - TbMsgCallback callback = wrapper.getCallback(); 216 + TbCallback callback = wrapper.getCallback();
217 if (msg.hasSessionEvent()) { 217 if (msg.hasSessionEvent()) {
218 processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent()); 218 processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent());
219 } 219 }
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
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 * 7 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 + * http://www.apache.org/licenses/LICENSE-2.0
9 * 9 *
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,
@@ -110,7 +110,7 @@ class DefaultTbContext implements TbContext { @@ -110,7 +110,7 @@ class DefaultTbContext implements TbContext {
110 if (nodeCtx.getSelf().isDebugMode()) { 110 if (nodeCtx.getSelf().isDebugMode()) {
111 relationTypes.forEach(relationType -> mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, relationType, th)); 111 relationTypes.forEach(relationType -> mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, relationType, th));
112 } 112 }
113 - nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), relationTypes, msg), nodeCtx.getSelfActor()); 113 + nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), relationTypes, msg, th != null ? th.getMessage() : null), nodeCtx.getSelfActor());
114 } 114 }
115 115
116 @Override 116 @Override
@@ -140,52 +140,60 @@ class DefaultTbContext implements TbContext { @@ -140,52 +140,60 @@ class DefaultTbContext implements TbContext {
140 } 140 }
141 141
142 @Override 142 @Override
  143 + public void enqueueForTellFailure(TbMsg tbMsg, String failureMessage) {
  144 + TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator());
  145 + enqueueForTellNext(tpi, tbMsg, Collections.singleton(TbRelationTypes.FAILURE), failureMessage, null, null);
  146 + }
  147 +
  148 + @Override
143 public void enqueueForTellNext(TbMsg tbMsg, String relationType) { 149 public void enqueueForTellNext(TbMsg tbMsg, String relationType) {
144 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); 150 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator());
145 - enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, null); 151 + enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, null, null);
146 } 152 }
147 153
148 @Override 154 @Override
149 public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes) { 155 public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes) {
150 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); 156 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator());
151 - enqueueForTellNext(tpi, tbMsg, relationTypes, null, null); 157 + enqueueForTellNext(tpi, tbMsg, relationTypes, null, null, null);
152 } 158 }
153 159
154 @Override 160 @Override
155 public void enqueueForTellNext(TbMsg tbMsg, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) { 161 public void enqueueForTellNext(TbMsg tbMsg, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) {
156 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); 162 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator());
157 - enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), onSuccess, onFailure); 163 + enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, onSuccess, onFailure);
158 } 164 }
159 165
160 @Override 166 @Override
161 public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) { 167 public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) {
162 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator()); 168 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator());
163 - enqueueForTellNext(tpi, tbMsg, relationTypes, onSuccess, onFailure); 169 + enqueueForTellNext(tpi, tbMsg, relationTypes, null, onSuccess, onFailure);
164 } 170 }
165 171
166 @Override 172 @Override
167 public void enqueueForTellNext(TbMsg tbMsg, String queueName, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) { 173 public void enqueueForTellNext(TbMsg tbMsg, String queueName, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) {
168 - TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, getTenantId(), tbMsg.getOriginator());  
169 - enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), onSuccess, onFailure); 174 + TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, queueName, getTenantId(), tbMsg.getOriginator());
  175 + enqueueForTellNext(tpi, tbMsg, Collections.singleton(relationType), null, onSuccess, onFailure);
170 } 176 }
171 177
172 @Override 178 @Override
173 public void enqueueForTellNext(TbMsg tbMsg, String queueName, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) { 179 public void enqueueForTellNext(TbMsg tbMsg, String queueName, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) {
174 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, queueName, getTenantId(), tbMsg.getOriginator()); 180 TopicPartitionInfo tpi = mainCtx.resolve(ServiceType.TB_RULE_ENGINE, queueName, getTenantId(), tbMsg.getOriginator());
175 - enqueueForTellNext(tpi, tbMsg, relationTypes, onSuccess, onFailure); 181 + enqueueForTellNext(tpi, tbMsg, relationTypes, null, onSuccess, onFailure);
176 } 182 }
177 183
178 - private void enqueueForTellNext(TopicPartitionInfo tpi, TbMsg tbMsg, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) { 184 + private void enqueueForTellNext(TopicPartitionInfo tpi, TbMsg tbMsg, Set<String> relationTypes, String failureMessage, Runnable onSuccess, Consumer<Throwable> onFailure) {
179 RuleChainId ruleChainId = nodeCtx.getSelf().getRuleChainId(); 185 RuleChainId ruleChainId = nodeCtx.getSelf().getRuleChainId();
180 RuleNodeId ruleNodeId = nodeCtx.getSelf().getId(); 186 RuleNodeId ruleNodeId = nodeCtx.getSelf().getId();
181 tbMsg = TbMsg.newMsg(tbMsg, ruleChainId, ruleNodeId); 187 tbMsg = TbMsg.newMsg(tbMsg, ruleChainId, ruleNodeId);
182 - TransportProtos.ToRuleEngineMsg msg = TransportProtos.ToRuleEngineMsg.newBuilder() 188 + TransportProtos.ToRuleEngineMsg.Builder msg = TransportProtos.ToRuleEngineMsg.newBuilder()
183 .setTenantIdMSB(getTenantId().getId().getMostSignificantBits()) 189 .setTenantIdMSB(getTenantId().getId().getMostSignificantBits())
184 .setTenantIdLSB(getTenantId().getId().getLeastSignificantBits()) 190 .setTenantIdLSB(getTenantId().getId().getLeastSignificantBits())
185 .setTbMsg(TbMsg.toByteString(tbMsg)) 191 .setTbMsg(TbMsg.toByteString(tbMsg))
186 - .addAllRelationTypes(relationTypes)  
187 - .build();  
188 - mainCtx.getProducerProvider().getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), new SimpleTbQueueCallback(onSuccess, onFailure)); 192 + .addAllRelationTypes(relationTypes);
  193 + if (failureMessage != null) {
  194 + msg.setFailureMessage(failureMessage);
  195 + }
  196 + mainCtx.getProducerProvider().getRuleEngineMsgProducer().send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg.build()), new SimpleTbQueueCallback(onSuccess, onFailure));
189 } 197 }
190 198
191 @Override 199 @Override
@@ -207,7 +215,8 @@ class DefaultTbContext implements TbContext { @@ -207,7 +215,8 @@ class DefaultTbContext implements TbContext {
207 if (nodeCtx.getSelf().isDebugMode()) { 215 if (nodeCtx.getSelf().isDebugMode()) {
208 mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, TbRelationTypes.FAILURE, th); 216 mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, TbRelationTypes.FAILURE, th);
209 } 217 }
210 - nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), Collections.singleton(TbRelationTypes.FAILURE), msg), nodeCtx.getSelfActor()); 218 + nodeCtx.getChainActor().tell(new RuleNodeToRuleChainTellNextMsg(nodeCtx.getSelf().getId(), Collections.singleton(TbRelationTypes.FAILURE),
  219 + msg, th != null ? th.getMessage() : null), nodeCtx.getSelfActor());
211 } 220 }
212 221
213 public void updateSelf(RuleNode self) { 222 public void updateSelf(RuleNode self) {
1 -/**  
2 - * Copyright © 2016-2020 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.actors.ruleChain;  
17 -  
18 -import lombok.Data;  
19 -import org.thingsboard.server.common.data.id.RuleChainId;  
20 -import org.thingsboard.server.common.data.id.TenantId;  
21 -import org.thingsboard.server.common.msg.MsgType;  
22 -import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg;  
23 -import org.thingsboard.server.common.msg.aware.TenantAwareMsg;  
24 -  
25 -import java.io.Serializable;  
26 -  
27 -/**  
28 - * Created by ashvayka on 19.03.18.  
29 - */  
30 -@Data  
31 -final class RemoteToRuleChainTellNextMsg extends RuleNodeToRuleChainTellNextMsg implements TenantAwareMsg, RuleChainAwareMsg {  
32 -  
33 - private static final long serialVersionUID = 2459605482321657447L;  
34 - private final TenantId tenantId;  
35 - private final RuleChainId ruleChainId;  
36 -  
37 - public RemoteToRuleChainTellNextMsg(RuleNodeToRuleChainTellNextMsg original, TenantId tenantId, RuleChainId ruleChainId) {  
38 - super(original.getOriginator(), original.getRelationTypes(), original.getMsg());  
39 - this.tenantId = tenantId;  
40 - this.ruleChainId = ruleChainId;  
41 - }  
42 -  
43 - @Override  
44 - public MsgType getMsgType() {  
45 - return MsgType.REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG;  
46 - }  
47 -  
48 -}  
@@ -22,6 +22,7 @@ import org.thingsboard.server.actors.service.ComponentActor; @@ -22,6 +22,7 @@ import org.thingsboard.server.actors.service.ComponentActor;
22 import org.thingsboard.server.actors.service.ContextBasedCreator; 22 import org.thingsboard.server.actors.service.ContextBasedCreator;
23 import org.thingsboard.server.common.data.id.RuleChainId; 23 import org.thingsboard.server.common.data.id.RuleChainId;
24 import org.thingsboard.server.common.data.id.TenantId; 24 import org.thingsboard.server.common.data.id.TenantId;
  25 +import org.thingsboard.server.common.data.rule.RuleChain;
25 import org.thingsboard.server.common.msg.TbActorMsg; 26 import org.thingsboard.server.common.msg.TbActorMsg;
26 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 27 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
27 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; 28 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
@@ -30,9 +31,9 @@ import scala.concurrent.duration.Duration; @@ -30,9 +31,9 @@ import scala.concurrent.duration.Duration;
30 31
31 public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMessageProcessor> { 32 public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMessageProcessor> {
32 33
33 - private RuleChainActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId) {  
34 - super(systemContext, tenantId, ruleChainId);  
35 - setProcessor(new RuleChainActorMessageProcessor(tenantId, ruleChainId, systemContext, 34 + private RuleChainActor(ActorSystemContext systemContext, TenantId tenantId, RuleChain ruleChain) {
  35 + super(systemContext, tenantId, ruleChain.getId());
  36 + setProcessor(new RuleChainActorMessageProcessor(tenantId, ruleChain, systemContext,
36 context().parent(), context().self())); 37 context().parent(), context().self()));
37 } 38 }
38 39
@@ -46,7 +47,6 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe @@ -46,7 +47,6 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe
46 processor.onQueueToRuleEngineMsg((QueueToRuleEngineMsg) msg); 47 processor.onQueueToRuleEngineMsg((QueueToRuleEngineMsg) msg);
47 break; 48 break;
48 case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG: 49 case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG:
49 - case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG:  
50 processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg); 50 processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg);
51 break; 51 break;
52 case RULE_CHAIN_TO_RULE_CHAIN_MSG: 52 case RULE_CHAIN_TO_RULE_CHAIN_MSG:
@@ -68,17 +68,17 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe @@ -68,17 +68,17 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe
68 private static final long serialVersionUID = 1L; 68 private static final long serialVersionUID = 1L;
69 69
70 private final TenantId tenantId; 70 private final TenantId tenantId;
71 - private final RuleChainId ruleChainId; 71 + private final RuleChain ruleChain;
72 72
73 - public ActorCreator(ActorSystemContext context, TenantId tenantId, RuleChainId pluginId) { 73 + public ActorCreator(ActorSystemContext context, TenantId tenantId, RuleChain ruleChain) {
74 super(context); 74 super(context);
75 this.tenantId = tenantId; 75 this.tenantId = tenantId;
76 - this.ruleChainId = pluginId; 76 + this.ruleChain = ruleChain;
77 } 77 }
78 78
79 @Override 79 @Override
80 public RuleChainActor create() { 80 public RuleChainActor create() {
81 - return new RuleChainActor(context, tenantId, ruleChainId); 81 + return new RuleChainActor(context, tenantId, ruleChain);
82 } 82 }
83 } 83 }
84 84
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
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 * 7 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 + * http://www.apache.org/licenses/LICENSE-2.0
9 * 9 *
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,
@@ -37,6 +37,8 @@ import org.thingsboard.server.common.msg.TbMsg; @@ -37,6 +37,8 @@ import org.thingsboard.server.common.msg.TbMsg;
37 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 37 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
38 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; 38 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
39 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; 39 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;
  40 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  41 +import org.thingsboard.server.common.msg.queue.RuleNodeException;
40 import org.thingsboard.server.common.msg.queue.ServiceType; 42 import org.thingsboard.server.common.msg.queue.ServiceType;
41 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; 43 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
42 import org.thingsboard.server.dao.rule.RuleChainService; 44 import org.thingsboard.server.dao.rule.RuleChainService;
@@ -67,14 +69,16 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -67,14 +69,16 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
67 private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes; 69 private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes;
68 private final RuleChainService service; 70 private final RuleChainService service;
69 private final TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> producer; 71 private final TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> producer;
  72 + private String ruleChainName;
70 73
71 private RuleNodeId firstId; 74 private RuleNodeId firstId;
72 private RuleNodeCtx firstNode; 75 private RuleNodeCtx firstNode;
73 private boolean started; 76 private boolean started;
74 77
75 - RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext 78 + RuleChainActorMessageProcessor(TenantId tenantId, RuleChain ruleChain, ActorSystemContext systemContext
76 , ActorRef parent, ActorRef self) { 79 , ActorRef parent, ActorRef self) {
77 - super(systemContext, tenantId, ruleChainId); 80 + super(systemContext, tenantId, ruleChain.getId());
  81 + this.ruleChainName = ruleChain.getName();
78 this.parent = parent; 82 this.parent = parent;
79 this.self = self; 83 this.self = self;
80 this.nodeActors = new HashMap<>(); 84 this.nodeActors = new HashMap<>();
@@ -113,6 +117,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -113,6 +117,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
113 public void onUpdate(ActorContext context) { 117 public void onUpdate(ActorContext context) {
114 RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); 118 RuleChain ruleChain = service.findRuleChainById(tenantId, entityId);
115 if (ruleChain != null) { 119 if (ruleChain != null) {
  120 + ruleChainName = ruleChain.getName();
116 List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId); 121 List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId);
117 log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); 122 log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size());
118 for (RuleNode ruleNode : ruleNodeList) { 123 for (RuleNode ruleNode : ruleNodeList) {
@@ -194,7 +199,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -194,7 +199,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
194 void onQueueToRuleEngineMsg(QueueToRuleEngineMsg envelope) { 199 void onQueueToRuleEngineMsg(QueueToRuleEngineMsg envelope) {
195 TbMsg msg = envelope.getTbMsg(); 200 TbMsg msg = envelope.getTbMsg();
196 log.trace("[{}][{}] Processing message [{}]: {}", entityId, firstId, msg.getId(), msg); 201 log.trace("[{}][{}] Processing message [{}]: {}", entityId, firstId, msg.getId(), msg);
197 - if (envelope.getRelationTypes() == null) { 202 + if (envelope.getRelationTypes() == null || envelope.getRelationTypes().isEmpty()) {
198 try { 203 try {
199 checkActive(); 204 checkActive();
200 RuleNodeId targetId = msg.getRuleNodeId(); 205 RuleNodeId targetId = msg.getRuleNodeId();
@@ -213,10 +218,10 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -213,10 +218,10 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
213 msg.getCallback().onSuccess(); 218 msg.getCallback().onSuccess();
214 } 219 }
215 } catch (Exception e) { 220 } catch (Exception e) {
216 - envelope.getTbMsg().getCallback().onFailure(e); 221 + envelope.getTbMsg().getCallback().onFailure(new RuleEngineException(e.getMessage()));
217 } 222 }
218 } else { 223 } else {
219 - onTellNext(envelope.getTbMsg(), envelope.getTbMsg().getRuleNodeId(), envelope.getRelationTypes()); 224 + onTellNext(envelope.getTbMsg(), envelope.getTbMsg().getRuleNodeId(), envelope.getRelationTypes(), envelope.getFailureMessage());
220 } 225 }
221 } 226 }
222 227
@@ -230,10 +235,10 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -230,10 +235,10 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
230 } 235 }
231 236
232 void onTellNext(RuleNodeToRuleChainTellNextMsg envelope) { 237 void onTellNext(RuleNodeToRuleChainTellNextMsg envelope) {
233 - onTellNext(envelope.getMsg(), envelope.getOriginator(), envelope.getRelationTypes()); 238 + onTellNext(envelope.getMsg(), envelope.getOriginator(), envelope.getRelationTypes(), envelope.getFailureMessage());
234 } 239 }
235 240
236 - private void onTellNext(TbMsg msg, RuleNodeId originatorNodeId, Set<String> relationTypes) { 241 + private void onTellNext(TbMsg msg, RuleNodeId originatorNodeId, Set<String> relationTypes, String failureMessage) {
237 try { 242 try {
238 checkActive(); 243 checkActive();
239 EntityId entityId = msg.getOriginator(); 244 EntityId entityId = msg.getOriginator();
@@ -245,9 +250,14 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -245,9 +250,14 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
245 if (relationsCount == 0) { 250 if (relationsCount == 0) {
246 log.trace("[{}][{}][{}] No outbound relations to process", tenantId, entityId, msg.getId()); 251 log.trace("[{}][{}][{}] No outbound relations to process", tenantId, entityId, msg.getId());
247 if (relationTypes.contains(TbRelationTypes.FAILURE)) { 252 if (relationTypes.contains(TbRelationTypes.FAILURE)) {
248 - log.debug("[{}] Failure during message processing by Rule Node [{}]. Enable and see debug events for more info", entityId, originatorNodeId.getId());  
249 - //TODO 2.5: Introduce our own RuleEngineFailureException to track what is wrong  
250 - msg.getCallback().onFailure(new RuntimeException("Failure during message processing by Rule Node [" + originatorNodeId.getId().toString() + "]")); 253 + RuleNodeCtx ruleNodeCtx = nodeActors.get(originatorNodeId);
  254 + if (ruleNodeCtx != null) {
  255 + msg.getCallback().onFailure(new RuleNodeException(failureMessage, ruleChainName, ruleNodeCtx.getSelf()));
  256 + } else {
  257 + log.debug("[{}] Failure during message processing by Rule Node [{}]. Enable and see debug events for more info", entityId, originatorNodeId.getId());
  258 + //TODO 2.5: Introduce our own RuleEngineFailureException to track what is wrong
  259 + msg.getCallback().onFailure(new RuleEngineException("Failure during message processing by Rule Node [" + originatorNodeId.getId().toString() + "]"));
  260 + }
251 } else { 261 } else {
252 msg.getCallback().onSuccess(); 262 msg.getCallback().onSuccess();
253 } 263 }
@@ -265,7 +275,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -265,7 +275,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
265 } 275 }
266 } 276 }
267 } catch (Exception e) { 277 } catch (Exception e) {
268 - msg.getCallback().onFailure(e); 278 + msg.getCallback().onFailure(new RuleEngineException("onTellNext - " + e.getMessage()));
269 } 279 }
270 } 280 }
271 281
@@ -15,43 +15,89 @@ @@ -15,43 +15,89 @@
15 */ 15 */
16 package org.thingsboard.server.actors.ruleChain; 16 package org.thingsboard.server.actors.ruleChain;
17 17
  18 +import akka.actor.ActorContext;
18 import akka.actor.ActorRef; 19 import akka.actor.ActorRef;
  20 +import akka.actor.Props;
  21 +import com.google.common.collect.BiMap;
  22 +import com.google.common.collect.HashBiMap;
  23 +import lombok.Getter;
19 import org.thingsboard.server.actors.ActorSystemContext; 24 import org.thingsboard.server.actors.ActorSystemContext;
20 import org.thingsboard.server.actors.service.ContextAwareActor; 25 import org.thingsboard.server.actors.service.ContextAwareActor;
21 -import org.thingsboard.server.actors.shared.rulechain.RuleChainManager; 26 +import org.thingsboard.server.actors.service.DefaultActorService;
  27 +import org.thingsboard.server.common.data.EntityType;
22 import org.thingsboard.server.common.data.id.EntityId; 28 import org.thingsboard.server.common.data.id.EntityId;
23 import org.thingsboard.server.common.data.id.RuleChainId; 29 import org.thingsboard.server.common.data.id.RuleChainId;
  30 +import org.thingsboard.server.common.data.id.TenantId;
  31 +import org.thingsboard.server.common.data.page.PageDataIterable;
  32 +import org.thingsboard.server.common.data.rule.RuleChain;
24 import org.thingsboard.server.dao.rule.RuleChainService; 33 import org.thingsboard.server.dao.rule.RuleChainService;
25 34
  35 +import java.util.function.Function;
  36 +
26 /** 37 /**
27 * Created by ashvayka on 15.03.18. 38 * Created by ashvayka on 15.03.18.
28 */ 39 */
29 public abstract class RuleChainManagerActor extends ContextAwareActor { 40 public abstract class RuleChainManagerActor extends ContextAwareActor {
30 41
31 - protected final RuleChainManager ruleChainManager;  
32 - protected final RuleChainService ruleChainService; 42 + protected final TenantId tenantId;
  43 + private final RuleChainService ruleChainService;
  44 + private final BiMap<RuleChainId, ActorRef> actors;
  45 + @Getter
  46 + protected RuleChain rootChain;
  47 + @Getter
  48 + protected ActorRef rootChainActor;
33 49
34 - public RuleChainManagerActor(ActorSystemContext systemContext, RuleChainManager ruleChainManager) { 50 + public RuleChainManagerActor(ActorSystemContext systemContext, TenantId tenantId) {
35 super(systemContext); 51 super(systemContext);
36 - this.ruleChainManager = ruleChainManager; 52 + this.tenantId = tenantId;
  53 + this.actors = HashBiMap.create();
37 this.ruleChainService = systemContext.getRuleChainService(); 54 this.ruleChainService = systemContext.getRuleChainService();
38 } 55 }
39 56
40 protected void initRuleChains() { 57 protected void initRuleChains() {
41 - ruleChainManager.init(this.context()); 58 + for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChains(tenantId, link), ContextAwareActor.ENTITY_PACK_LIMIT)) {
  59 + RuleChainId ruleChainId = ruleChain.getId();
  60 + log.debug("[{}|{}] Creating rule chain actor", ruleChainId.getEntityType(), ruleChain.getId());
  61 + //TODO: remove this cast making UUIDBased subclass of EntityId an interface and vice versa.
  62 + ActorRef actorRef = getOrCreateActor(this.context(), ruleChainId, id -> ruleChain);
  63 + visit(ruleChain, actorRef);
  64 + log.debug("[{}|{}] Rule Chain actor created.", ruleChainId.getEntityType(), ruleChainId.getId());
  65 + }
  66 + }
  67 +
  68 + protected void visit(RuleChain entity, ActorRef actorRef) {
  69 + if (entity != null && entity.isRoot()) {
  70 + rootChain = entity;
  71 + rootChainActor = actorRef;
  72 + }
  73 + }
  74 +
  75 + public ActorRef getOrCreateActor(ActorContext context, RuleChainId ruleChainId) {
  76 + return getOrCreateActor(context, ruleChainId, eId -> ruleChainService.findRuleChainById(TenantId.SYS_TENANT_ID, eId));
  77 + }
  78 +
  79 + public ActorRef getOrCreateActor(ActorContext context, RuleChainId ruleChainId, Function<RuleChainId, RuleChain> provider) {
  80 + return actors.computeIfAbsent(ruleChainId, eId -> {
  81 + RuleChain ruleChain = provider.apply(eId);
  82 + return context.actorOf(Props.create(new RuleChainActor.ActorCreator(systemContext, tenantId, ruleChain))
  83 + .withDispatcher(DefaultActorService.TENANT_RULE_DISPATCHER_NAME), eId.toString());
  84 + });
42 } 85 }
43 86
44 protected ActorRef getEntityActorRef(EntityId entityId) { 87 protected ActorRef getEntityActorRef(EntityId entityId) {
45 ActorRef target = null; 88 ActorRef target = null;
46 - switch (entityId.getEntityType()) {  
47 - case RULE_CHAIN:  
48 - target = ruleChainManager.getOrCreateActor(this.context(), (RuleChainId) entityId);  
49 - break; 89 + if (entityId.getEntityType() == EntityType.RULE_CHAIN) {
  90 + target = getOrCreateActor(this.context(), (RuleChainId) entityId);
50 } 91 }
51 return target; 92 return target;
52 } 93 }
53 94
54 protected void broadcast(Object msg) { 95 protected void broadcast(Object msg) {
55 - ruleChainManager.broadcast(msg); 96 + actors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender()));
56 } 97 }
  98 +
  99 + public ActorRef get(RuleChainId id) {
  100 + return actors.get(id);
  101 + }
  102 +
57 } 103 }
@@ -34,6 +34,7 @@ class RuleNodeToRuleChainTellNextMsg implements TbActorMsg, Serializable { @@ -34,6 +34,7 @@ class RuleNodeToRuleChainTellNextMsg implements TbActorMsg, Serializable {
34 private final RuleNodeId originator; 34 private final RuleNodeId originator;
35 private final Set<String> relationTypes; 35 private final Set<String> relationTypes;
36 private final TbMsg msg; 36 private final TbMsg msg;
  37 + private final String failureMessage;
37 38
38 @Override 39 @Override
39 public MsgType getMsgType() { 40 public MsgType getMsgType() {
1 -/**  
2 - * Copyright © 2016-2020 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.actors.shared;  
17 -  
18 -import akka.actor.ActorContext;  
19 -import akka.actor.ActorRef;  
20 -import akka.actor.Props;  
21 -import akka.actor.UntypedActor;  
22 -import akka.japi.Creator;  
23 -import com.google.common.collect.BiMap;  
24 -import com.google.common.collect.HashBiMap;  
25 -import lombok.extern.slf4j.Slf4j;  
26 -import org.thingsboard.server.actors.ActorSystemContext;  
27 -import org.thingsboard.server.actors.ruleChain.RuleChainActor;  
28 -import org.thingsboard.server.actors.service.ContextAwareActor;  
29 -import org.thingsboard.server.common.data.SearchTextBased;  
30 -import org.thingsboard.server.common.data.id.EntityId;  
31 -import org.thingsboard.server.common.data.id.RuleChainId;  
32 -import org.thingsboard.server.common.data.id.TenantId;  
33 -import org.thingsboard.server.common.data.id.UUIDBased;  
34 -import org.thingsboard.server.common.data.page.PageDataIterable;  
35 -  
36 -import java.util.HashMap;  
37 -import java.util.Map;  
38 -  
39 -/**  
40 - * Created by ashvayka on 15.03.18.  
41 - */  
42 -@Slf4j  
43 -public abstract class EntityActorsManager<T extends EntityId, A extends UntypedActor, M extends SearchTextBased<? extends UUIDBased>> {  
44 -  
45 - protected final ActorSystemContext systemContext;  
46 - protected final BiMap<T, ActorRef> actors;  
47 -  
48 - public EntityActorsManager(ActorSystemContext systemContext) {  
49 - this.systemContext = systemContext;  
50 - this.actors = HashBiMap.create();  
51 - }  
52 -  
53 - protected abstract TenantId getTenantId();  
54 -  
55 - protected abstract String getDispatcherName();  
56 -  
57 - protected abstract Creator<A> creator(T entityId);  
58 -  
59 - protected abstract PageDataIterable.FetchFunction<M> getFetchEntitiesFunction();  
60 -  
61 - public void init(ActorContext context) {  
62 - for (M entity : new PageDataIterable<>(getFetchEntitiesFunction(), ContextAwareActor.ENTITY_PACK_LIMIT)) {  
63 - T entityId = (T) entity.getId();  
64 - log.debug("[{}|{}] Creating entity actor", entityId.getEntityType(), entityId.getId());  
65 - //TODO: remove this cast making UUIDBased subclass of EntityId an interface and vice versa.  
66 - ActorRef actorRef = getOrCreateActor(context, entityId);  
67 - visit(entity, actorRef);  
68 - log.debug("[{}|{}] Entity actor created.", entityId.getEntityType(), entityId.getId());  
69 - }  
70 - }  
71 -  
72 - public void visit(M entity, ActorRef actorRef) {  
73 - }  
74 -  
75 - public ActorRef getOrCreateActor(ActorContext context, T entityId) {  
76 - return actors.computeIfAbsent(entityId, eId ->  
77 - context.actorOf(Props.create(creator(eId))  
78 - .withDispatcher(getDispatcherName()), eId.toString()));  
79 - }  
80 -  
81 - public void broadcast(Object msg) {  
82 - actors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender()));  
83 - }  
84 -  
85 - public void remove(T id) {  
86 - actors.remove(id);  
87 - }  
88 -  
89 - public ActorRef get(T id) {  
90 - return actors.get(id);  
91 - }  
92 -  
93 -}  
1 -/**  
2 - * Copyright © 2016-2020 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.actors.shared.rulechain;  
17 -  
18 -import akka.actor.ActorRef;  
19 -import akka.japi.Creator;  
20 -import lombok.Getter;  
21 -import lombok.extern.slf4j.Slf4j;  
22 -import org.thingsboard.server.actors.ActorSystemContext;  
23 -import org.thingsboard.server.actors.ruleChain.RuleChainActor;  
24 -import org.thingsboard.server.actors.shared.EntityActorsManager;  
25 -import org.thingsboard.server.common.data.id.RuleChainId;  
26 -import org.thingsboard.server.common.data.rule.RuleChain;  
27 -import org.thingsboard.server.dao.rule.RuleChainService;  
28 -  
29 -/**  
30 - * Created by ashvayka on 15.03.18.  
31 - */  
32 -@Slf4j  
33 -public abstract class RuleChainManager extends EntityActorsManager<RuleChainId, RuleChainActor, RuleChain> {  
34 -  
35 - protected final RuleChainService service;  
36 - @Getter  
37 - protected RuleChain rootChain;  
38 - @Getter  
39 - protected ActorRef rootChainActor;  
40 -  
41 - public RuleChainManager(ActorSystemContext systemContext) {  
42 - super(systemContext);  
43 - this.service = systemContext.getRuleChainService();  
44 - }  
45 -  
46 - @Override  
47 - public Creator<RuleChainActor> creator(RuleChainId entityId) {  
48 - return new RuleChainActor.ActorCreator(systemContext, getTenantId(), entityId);  
49 - }  
50 -  
51 - @Override  
52 - public void visit(RuleChain entity, ActorRef actorRef) {  
53 - if (entity != null && entity.isRoot()) {  
54 - rootChain = entity;  
55 - rootChainActor = actorRef;  
56 - }  
57 - }  
58 -  
59 -}  
1 -/**  
2 - * Copyright © 2016-2020 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.actors.shared.rulechain;  
17 -  
18 -import akka.actor.ActorContext;  
19 -import org.thingsboard.server.actors.ActorSystemContext;  
20 -import org.thingsboard.server.actors.service.DefaultActorService;  
21 -import org.thingsboard.server.common.data.id.TenantId;  
22 -import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction;  
23 -import org.thingsboard.server.common.data.rule.RuleChain;  
24 -  
25 -public class TenantRuleChainManager extends RuleChainManager {  
26 -  
27 - private final TenantId tenantId;  
28 -  
29 - public TenantRuleChainManager(ActorSystemContext systemContext, TenantId tenantId) {  
30 - super(systemContext);  
31 - this.tenantId = tenantId;  
32 - }  
33 -  
34 - @Override  
35 - public void init(ActorContext context) {  
36 - super.init(context);  
37 - }  
38 -  
39 - @Override  
40 - protected TenantId getTenantId() {  
41 - return tenantId;  
42 - }  
43 -  
44 - @Override  
45 - protected String getDispatcherName() {  
46 - return DefaultActorService.TENANT_RULE_DISPATCHER_NAME;  
47 - }  
48 -  
49 - @Override  
50 - protected FetchFunction<RuleChain> getFetchEntitiesFunction() {  
51 - return link -> service.findTenantRuleChains(tenantId, link);  
52 - }  
53 -}  
@@ -24,7 +24,6 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; @@ -24,7 +24,6 @@ import org.thingsboard.server.actors.service.ContextBasedCreator;
24 import org.thingsboard.server.common.data.DataConstants; 24 import org.thingsboard.server.common.data.DataConstants;
25 import org.thingsboard.server.common.data.Event; 25 import org.thingsboard.server.common.data.Event;
26 import org.thingsboard.server.common.msg.TbActorMsg; 26 import org.thingsboard.server.common.msg.TbActorMsg;
27 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
28 27
29 @Slf4j 28 @Slf4j
30 public class StatsActor extends ContextAwareActor { 29 public class StatsActor extends ContextAwareActor {
@@ -30,7 +30,6 @@ import org.thingsboard.server.actors.device.DeviceActorCreator; @@ -30,7 +30,6 @@ import org.thingsboard.server.actors.device.DeviceActorCreator;
30 import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; 30 import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor;
31 import org.thingsboard.server.actors.service.ContextBasedCreator; 31 import org.thingsboard.server.actors.service.ContextBasedCreator;
32 import org.thingsboard.server.actors.service.DefaultActorService; 32 import org.thingsboard.server.actors.service.DefaultActorService;
33 -import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager;  
34 import org.thingsboard.server.common.data.EntityType; 33 import org.thingsboard.server.common.data.EntityType;
35 import org.thingsboard.server.common.data.id.DeviceId; 34 import org.thingsboard.server.common.data.id.DeviceId;
36 import org.thingsboard.server.common.data.id.RuleChainId; 35 import org.thingsboard.server.common.data.id.RuleChainId;
@@ -43,6 +42,7 @@ import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg; @@ -43,6 +42,7 @@ import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg;
43 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; 42 import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
44 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; 43 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
45 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; 44 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;
  45 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
46 import org.thingsboard.server.common.msg.queue.ServiceType; 46 import org.thingsboard.server.common.msg.queue.ServiceType;
47 import scala.concurrent.duration.Duration; 47 import scala.concurrent.duration.Duration;
48 48
@@ -51,12 +51,12 @@ import java.util.stream.Collectors; @@ -51,12 +51,12 @@ import java.util.stream.Collectors;
51 51
52 public class TenantActor extends RuleChainManagerActor { 52 public class TenantActor extends RuleChainManagerActor {
53 53
54 - private final TenantId tenantId;  
55 private final BiMap<DeviceId, ActorRef> deviceActors; 54 private final BiMap<DeviceId, ActorRef> deviceActors;
  55 + private boolean isRuleEngine;
  56 + private boolean isCore;
56 57
57 private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { 58 private TenantActor(ActorSystemContext systemContext, TenantId tenantId) {
58 - super(systemContext, new TenantRuleChainManager(systemContext, tenantId));  
59 - this.tenantId = tenantId; 59 + super(systemContext, tenantId);
60 this.deviceActors = HashBiMap.create(); 60 this.deviceActors = HashBiMap.create();
61 } 61 }
62 62
@@ -69,7 +69,11 @@ public class TenantActor extends RuleChainManagerActor { @@ -69,7 +69,11 @@ public class TenantActor extends RuleChainManagerActor {
69 public void preStart() { 69 public void preStart() {
70 log.info("[{}] Starting tenant actor.", tenantId); 70 log.info("[{}] Starting tenant actor.", tenantId);
71 try { 71 try {
72 - initRuleChains(); 72 + isRuleEngine = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE);
  73 + isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE);
  74 + if (isRuleEngine) {
  75 + initRuleChains();
  76 + }
73 log.info("[{}] Tenant actor started.", tenantId); 77 log.info("[{}] Tenant actor started.", tenantId);
74 } catch (Exception e) { 78 } catch (Exception e) {
75 log.warn("[{}] Unknown failure", tenantId, e); 79 log.warn("[{}] Unknown failure", tenantId, e);
@@ -115,7 +119,6 @@ public class TenantActor extends RuleChainManagerActor { @@ -115,7 +119,6 @@ public class TenantActor extends RuleChainManagerActor {
115 onToDeviceActorMsg((DeviceAwareMsg) msg); 119 onToDeviceActorMsg((DeviceAwareMsg) msg);
116 break; 120 break;
117 case RULE_CHAIN_TO_RULE_CHAIN_MSG: 121 case RULE_CHAIN_TO_RULE_CHAIN_MSG:
118 - case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG:  
119 onRuleChainMsg((RuleChainAwareMsg) msg); 122 onRuleChainMsg((RuleChainAwareMsg) msg);
120 break; 123 break;
121 default: 124 default:
@@ -129,16 +132,19 @@ public class TenantActor extends RuleChainManagerActor { @@ -129,16 +132,19 @@ public class TenantActor extends RuleChainManagerActor {
129 } 132 }
130 133
131 private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) { 134 private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) {
  135 + if (!isRuleEngine) {
  136 + log.warn("RECEIVED INVALID MESSAGE: {}", msg);
  137 + }
132 TbMsg tbMsg = msg.getTbMsg(); 138 TbMsg tbMsg = msg.getTbMsg();
133 if (tbMsg.getRuleChainId() == null) { 139 if (tbMsg.getRuleChainId() == null) {
134 - if (ruleChainManager.getRootChainActor() != null) {  
135 - ruleChainManager.getRootChainActor().tell(msg, self()); 140 + if (getRootChainActor() != null) {
  141 + getRootChainActor().tell(msg, self());
136 } else { 142 } else {
137 - tbMsg.getCallback().onFailure(new RuntimeException("No Root Rule Chain available!")); 143 + tbMsg.getCallback().onFailure(new RuleEngineException("No Root Rule Chain available!"));
138 log.info("[{}] No Root Chain: {}", tenantId, msg); 144 log.info("[{}] No Root Chain: {}", tenantId, msg);
139 } 145 }
140 } else { 146 } else {
141 - ActorRef ruleChainActor = ruleChainManager.get(tbMsg.getRuleChainId()); 147 + ActorRef ruleChainActor = get(tbMsg.getRuleChainId());
142 if (ruleChainActor != null) { 148 if (ruleChainActor != null) {
143 ruleChainActor.tell(msg, self()); 149 ruleChainActor.tell(msg, self());
144 } else { 150 } else {
@@ -150,24 +156,29 @@ public class TenantActor extends RuleChainManagerActor { @@ -150,24 +156,29 @@ public class TenantActor extends RuleChainManagerActor {
150 } 156 }
151 157
152 private void onRuleChainMsg(RuleChainAwareMsg msg) { 158 private void onRuleChainMsg(RuleChainAwareMsg msg) {
153 - ruleChainManager.getOrCreateActor(context(), msg.getRuleChainId()).tell(msg, self()); 159 + getOrCreateActor(context(), msg.getRuleChainId()).tell(msg, self());
154 } 160 }
155 161
156 private void onToDeviceActorMsg(DeviceAwareMsg msg) { 162 private void onToDeviceActorMsg(DeviceAwareMsg msg) {
  163 + if (!isCore) {
  164 + log.warn("RECEIVED INVALID MESSAGE: {}", msg);
  165 + }
157 getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); 166 getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender());
158 } 167 }
159 168
160 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { 169 private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) {
161 - ActorRef target = getEntityActorRef(msg.getEntityId());  
162 - if (target != null) {  
163 - if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) {  
164 - RuleChain ruleChain = systemContext.getRuleChainService().  
165 - findRuleChainById(tenantId, new RuleChainId(msg.getEntityId().getId()));  
166 - ruleChainManager.visit(ruleChain, target); 170 + if (isRuleEngine) {
  171 + ActorRef target = getEntityActorRef(msg.getEntityId());
  172 + if (target != null) {
  173 + if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) {
  174 + RuleChain ruleChain = systemContext.getRuleChainService().
  175 + findRuleChainById(tenantId, new RuleChainId(msg.getEntityId().getId()));
  176 + visit(ruleChain, target);
  177 + }
  178 + target.tell(msg, ActorRef.noSender());
  179 + } else {
  180 + log.debug("[{}] Invalid component lifecycle msg: {}", tenantId, msg);
167 } 181 }
168 - target.tell(msg, ActorRef.noSender());  
169 - } else {  
170 - log.debug("[{}] Invalid component lifecycle msg: {}", tenantId, msg);  
171 } 182 }
172 } 183 }
173 184
@@ -214,15 +225,12 @@ public class TenantActor extends RuleChainManagerActor { @@ -214,15 +225,12 @@ public class TenantActor extends RuleChainManagerActor {
214 } 225 }
215 } 226 }
216 227
217 - private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), new Function<Throwable, SupervisorStrategy.Directive>() {  
218 - @Override  
219 - public SupervisorStrategy.Directive apply(Throwable t) {  
220 - log.warn("[{}] Unknown failure", tenantId, t);  
221 - if (t instanceof ActorInitializationException) {  
222 - return SupervisorStrategy.stop();  
223 - } else {  
224 - return SupervisorStrategy.resume();  
225 - } 228 + private final SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create("1 minute"), t -> {
  229 + log.warn("[{}] Unknown failure", tenantId, t);
  230 + if (t instanceof ActorInitializationException) {
  231 + return SupervisorStrategy.stop();
  232 + } else {
  233 + return SupervisorStrategy.resume();
226 } 234 }
227 }); 235 });
228 236
@@ -92,10 +92,10 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr @@ -92,10 +92,10 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr
92 try { 92 try {
93 SessionMetaData sessionMd = internalSessionMap.get(session.getId()); 93 SessionMetaData sessionMd = internalSessionMap.get(session.getId());
94 if (sessionMd != null) { 94 if (sessionMd != null) {
95 - log.info("[{}][{}] Processing {}", sessionMd.sessionRef.getSecurityCtx().getTenantId(), session.getId(), message.getPayload()); 95 + log.trace("[{}][{}] Processing {}", sessionMd.sessionRef.getSecurityCtx().getTenantId(), session.getId(), message.getPayload());
96 webSocketService.handleWebSocketMsg(sessionMd.sessionRef, message.getPayload()); 96 webSocketService.handleWebSocketMsg(sessionMd.sessionRef, message.getPayload());
97 } else { 97 } else {
98 - log.warn("[{}] Failed to find session", session.getId()); 98 + log.trace("[{}] Failed to find session", session.getId());
99 session.close(CloseStatus.SERVER_ERROR.withReason("Session not found!")); 99 session.close(CloseStatus.SERVER_ERROR.withReason("Session not found!"));
100 } 100 }
101 } catch (IOException e) { 101 } catch (IOException e) {
@@ -139,7 +139,7 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr @@ -139,7 +139,7 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr
139 if (sessionMd != null) { 139 if (sessionMd != null) {
140 processInWebSocketService(sessionMd.sessionRef, SessionEvent.onError(tError)); 140 processInWebSocketService(sessionMd.sessionRef, SessionEvent.onError(tError));
141 } else { 141 } else {
142 - log.warn("[{}] Failed to find session", session.getId()); 142 + log.trace("[{}] Failed to find session", session.getId());
143 } 143 }
144 log.trace("[{}] Session transport error", session.getId(), tError); 144 log.trace("[{}] Session transport error", session.getId(), tError);
145 } 145 }
@@ -25,7 +25,7 @@ import org.thingsboard.server.actors.ActorSystemContext; @@ -25,7 +25,7 @@ import org.thingsboard.server.actors.ActorSystemContext;
25 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
26 import org.thingsboard.server.common.msg.TbActorMsg; 26 import org.thingsboard.server.common.msg.TbActorMsg;
27 import org.thingsboard.server.common.msg.queue.ServiceType; 27 import org.thingsboard.server.common.msg.queue.ServiceType;
28 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 28 +import org.thingsboard.server.common.msg.queue.TbCallback;
29 import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; 29 import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto;
30 import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto; 30 import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto;
31 import org.thingsboard.server.gen.transport.TransportProtos.LocalSubscriptionServiceMsgProto; 31 import org.thingsboard.server.gen.transport.TransportProtos.LocalSubscriptionServiceMsgProto;
@@ -120,8 +120,8 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -120,8 +120,8 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
120 ConcurrentMap<UUID, TbProtoQueueMsg<ToCoreMsg>> failedMap = new ConcurrentHashMap<>(); 120 ConcurrentMap<UUID, TbProtoQueueMsg<ToCoreMsg>> failedMap = new ConcurrentHashMap<>();
121 CountDownLatch processingTimeoutLatch = new CountDownLatch(1); 121 CountDownLatch processingTimeoutLatch = new CountDownLatch(1);
122 pendingMap.forEach((id, msg) -> { 122 pendingMap.forEach((id, msg) -> {
123 - log.info("[{}] Creating main callback for message: {}", id, msg.getValue());  
124 - TbMsgCallback callback = new MsgPackCallback<>(id, processingTimeoutLatch, pendingMap, new ConcurrentHashMap<>(), failedMap); 123 + log.trace("[{}] Creating main callback for message: {}", id, msg.getValue());
  124 + TbCallback callback = new TbPackCallback<>(id, processingTimeoutLatch, pendingMap, failedMap);
125 try { 125 try {
126 ToCoreMsg toCoreMsg = msg.getValue(); 126 ToCoreMsg toCoreMsg = msg.getValue();
127 if (toCoreMsg.hasToSubscriptionMgrMsg()) { 127 if (toCoreMsg.hasToSubscriptionMgrMsg()) {
@@ -182,7 +182,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -182,7 +182,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
182 } 182 }
183 183
184 @Override 184 @Override
185 - protected void handleNotification(UUID id, TbProtoQueueMsg<ToCoreNotificationMsg> msg, TbMsgCallback callback) { 185 + protected void handleNotification(UUID id, TbProtoQueueMsg<ToCoreNotificationMsg> msg, TbCallback callback) {
186 ToCoreNotificationMsg toCoreMsg = msg.getValue(); 186 ToCoreNotificationMsg toCoreMsg = msg.getValue();
187 if (toCoreMsg.hasToLocalSubscriptionServiceMsg()) { 187 if (toCoreMsg.hasToLocalSubscriptionServiceMsg()) {
188 log.trace("[{}] Forwarding message to local subscription service {}", id, toCoreMsg.getToLocalSubscriptionServiceMsg()); 188 log.trace("[{}] Forwarding message to local subscription service {}", id, toCoreMsg.getToLocalSubscriptionServiceMsg());
@@ -200,7 +200,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -200,7 +200,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
200 } 200 }
201 } 201 }
202 202
203 - private void forwardToCoreRpcService(FromDeviceRPCResponseProto proto, TbMsgCallback callback) { 203 + private void forwardToCoreRpcService(FromDeviceRPCResponseProto proto, TbCallback callback) {
204 RpcError error = proto.getError() > 0 ? RpcError.values()[proto.getError()] : null; 204 RpcError error = proto.getError() > 0 ? RpcError.values()[proto.getError()] : null;
205 FromDeviceRpcResponse response = new FromDeviceRpcResponse(new UUID(proto.getRequestIdMSB(), proto.getRequestIdLSB()) 205 FromDeviceRpcResponse response = new FromDeviceRpcResponse(new UUID(proto.getRequestIdMSB(), proto.getRequestIdLSB())
206 , proto.getResponse(), error); 206 , proto.getResponse(), error);
@@ -215,7 +215,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -215,7 +215,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
215 } 215 }
216 } 216 }
217 217
218 - private void forwardToLocalSubMgrService(LocalSubscriptionServiceMsgProto msg, TbMsgCallback callback) { 218 + private void forwardToLocalSubMgrService(LocalSubscriptionServiceMsgProto msg, TbCallback callback) {
219 if (msg.hasSubUpdate()) { 219 if (msg.hasSubUpdate()) {
220 localSubscriptionService.onSubscriptionUpdate(msg.getSubUpdate().getSessionId(), TbSubscriptionUtils.fromProto(msg.getSubUpdate()), callback); 220 localSubscriptionService.onSubscriptionUpdate(msg.getSubUpdate().getSessionId(), TbSubscriptionUtils.fromProto(msg.getSubUpdate()), callback);
221 } else { 221 } else {
@@ -223,7 +223,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -223,7 +223,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
223 } 223 }
224 } 224 }
225 225
226 - private void forwardToSubMgrService(SubscriptionMgrMsgProto msg, TbMsgCallback callback) { 226 + private void forwardToSubMgrService(SubscriptionMgrMsgProto msg, TbCallback callback) {
227 if (msg.hasAttributeSub()) { 227 if (msg.hasAttributeSub()) {
228 subscriptionManagerService.addSubscription(TbSubscriptionUtils.fromProto(msg.getAttributeSub()), callback); 228 subscriptionManagerService.addSubscription(TbSubscriptionUtils.fromProto(msg.getAttributeSub()), callback);
229 } else if (msg.hasTelemetrySub()) { 229 } else if (msg.hasTelemetrySub()) {
@@ -248,21 +248,21 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -248,21 +248,21 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
248 } 248 }
249 } 249 }
250 250
251 - private void forwardToStateService(DeviceStateServiceMsgProto deviceStateServiceMsg, TbMsgCallback callback) { 251 + private void forwardToStateService(DeviceStateServiceMsgProto deviceStateServiceMsg, TbCallback callback) {
252 if (statsEnabled) { 252 if (statsEnabled) {
253 stats.log(deviceStateServiceMsg); 253 stats.log(deviceStateServiceMsg);
254 } 254 }
255 stateService.onQueueMsg(deviceStateServiceMsg, callback); 255 stateService.onQueueMsg(deviceStateServiceMsg, callback);
256 } 256 }
257 257
258 - private void forwardToDeviceActor(TransportToDeviceActorMsg toDeviceActorMsg, TbMsgCallback callback) { 258 + private void forwardToDeviceActor(TransportToDeviceActorMsg toDeviceActorMsg, TbCallback callback) {
259 if (statsEnabled) { 259 if (statsEnabled) {
260 stats.log(toDeviceActorMsg); 260 stats.log(toDeviceActorMsg);
261 } 261 }
262 actorContext.getAppActor().tell(new TransportToDeviceActorMsgWrapper(toDeviceActorMsg, callback), ActorRef.noSender()); 262 actorContext.getAppActor().tell(new TransportToDeviceActorMsgWrapper(toDeviceActorMsg, callback), ActorRef.noSender());
263 } 263 }
264 264
265 - private void throwNotHandled(Object msg, TbMsgCallback callback) { 265 + private void throwNotHandled(Object msg, TbCallback callback) {
266 log.warn("Message not handled: {}", msg); 266 log.warn("Message not handled: {}", msg);
267 callback.onFailure(new RuntimeException("Message not handled!")); 267 callback.onFailure(new RuntimeException("Message not handled!"));
268 } 268 }
@@ -27,8 +27,11 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -27,8 +27,11 @@ import org.thingsboard.server.common.data.id.TenantId;
27 import org.thingsboard.server.common.msg.TbActorMsg; 27 import org.thingsboard.server.common.msg.TbActorMsg;
28 import org.thingsboard.server.common.msg.TbMsg; 28 import org.thingsboard.server.common.msg.TbMsg;
29 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; 29 import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;
  30 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  31 +import org.thingsboard.server.common.msg.queue.RuleNodeException;
30 import org.thingsboard.server.common.msg.queue.ServiceQueue; 32 import org.thingsboard.server.common.msg.queue.ServiceQueue;
31 import org.thingsboard.server.common.msg.queue.ServiceType; 33 import org.thingsboard.server.common.msg.queue.ServiceType;
  34 +import org.thingsboard.server.common.msg.queue.TbCallback;
32 import org.thingsboard.server.common.msg.queue.TbMsgCallback; 35 import org.thingsboard.server.common.msg.queue.TbMsgCallback;
33 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; 36 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
34 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; 37 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
@@ -45,6 +48,7 @@ import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingDec @@ -45,6 +48,7 @@ import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingDec
45 import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingResult; 48 import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingResult;
46 import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategy; 49 import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategy;
47 import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory; 50 import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory;
  51 +import org.thingsboard.server.service.stats.RuleEngineStatisticsService;
48 52
49 import javax.annotation.PostConstruct; 53 import javax.annotation.PostConstruct;
50 import java.util.Collections; 54 import java.util.Collections;
@@ -69,20 +73,22 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -69,20 +73,22 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
69 private long pollDuration; 73 private long pollDuration;
70 @Value("${queue.rule-engine.pack-processing-timeout}") 74 @Value("${queue.rule-engine.pack-processing-timeout}")
71 private long packProcessingTimeout; 75 private long packProcessingTimeout;
72 - @Value("${queue.rule-engine.stats.enabled:false}") 76 + @Value("${queue.rule-engine.stats.enabled:true}")
73 private boolean statsEnabled; 77 private boolean statsEnabled;
74 78
75 - private final TbCoreConsumerStats stats = new TbCoreConsumerStats();  
76 private final TbRuleEngineProcessingStrategyFactory factory; 79 private final TbRuleEngineProcessingStrategyFactory factory;
77 private final TbRuleEngineQueueFactory tbRuleEngineQueueFactory; 80 private final TbRuleEngineQueueFactory tbRuleEngineQueueFactory;
78 private final TbQueueRuleEngineSettings ruleEngineSettings; 81 private final TbQueueRuleEngineSettings ruleEngineSettings;
  82 + private final RuleEngineStatisticsService statisticsService;
79 private final ConcurrentMap<String, TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>>> consumers = new ConcurrentHashMap<>(); 83 private final ConcurrentMap<String, TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>>> consumers = new ConcurrentHashMap<>();
80 private final ConcurrentMap<String, TbRuleEngineQueueConfiguration> consumerConfigurations = new ConcurrentHashMap<>(); 84 private final ConcurrentMap<String, TbRuleEngineQueueConfiguration> consumerConfigurations = new ConcurrentHashMap<>();
  85 + private final ConcurrentMap<String, TbRuleEngineConsumerStats> consumerStats = new ConcurrentHashMap<>();
81 86
82 public DefaultTbRuleEngineConsumerService(TbRuleEngineProcessingStrategyFactory factory, TbQueueRuleEngineSettings ruleEngineSettings, 87 public DefaultTbRuleEngineConsumerService(TbRuleEngineProcessingStrategyFactory factory, TbQueueRuleEngineSettings ruleEngineSettings,
83 - TbRuleEngineQueueFactory tbRuleEngineQueueFactory, 88 + TbRuleEngineQueueFactory tbRuleEngineQueueFactory, RuleEngineStatisticsService statisticsService,
84 ActorSystemContext actorContext, DataDecodingEncodingService encodingService) { 89 ActorSystemContext actorContext, DataDecodingEncodingService encodingService) {
85 super(actorContext, encodingService, tbRuleEngineQueueFactory.createToRuleEngineNotificationsMsgConsumer()); 90 super(actorContext, encodingService, tbRuleEngineQueueFactory.createToRuleEngineNotificationsMsgConsumer());
  91 + this.statisticsService = statisticsService;
86 this.ruleEngineSettings = ruleEngineSettings; 92 this.ruleEngineSettings = ruleEngineSettings;
87 this.tbRuleEngineQueueFactory = tbRuleEngineQueueFactory; 93 this.tbRuleEngineQueueFactory = tbRuleEngineQueueFactory;
88 this.factory = factory; 94 this.factory = factory;
@@ -92,7 +98,9 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -92,7 +98,9 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
92 public void init() { 98 public void init() {
93 super.init("tb-rule-engine-consumer", "tb-rule-engine-notifications-consumer"); 99 super.init("tb-rule-engine-consumer", "tb-rule-engine-notifications-consumer");
94 for (TbRuleEngineQueueConfiguration configuration : ruleEngineSettings.getQueues()) { 100 for (TbRuleEngineQueueConfiguration configuration : ruleEngineSettings.getQueues()) {
  101 + consumerConfigurations.putIfAbsent(configuration.getName(), configuration);
95 consumers.computeIfAbsent(configuration.getName(), queueName -> tbRuleEngineQueueFactory.createToRuleEngineMsgConsumer(configuration)); 102 consumers.computeIfAbsent(configuration.getName(), queueName -> tbRuleEngineQueueFactory.createToRuleEngineMsgConsumer(configuration));
  103 + consumerStats.put(configuration.getName(), new TbRuleEngineConsumerStats(configuration.getName()));
96 } 104 }
97 } 105 }
98 106
@@ -107,7 +115,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -107,7 +115,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
107 115
108 @Override 116 @Override
109 protected void launchMainConsumers() { 117 protected void launchMainConsumers() {
110 - consumers.forEach((queue, consumer) -> launchConsumer(consumer, consumerConfigurations.get(queue))); 118 + consumers.forEach((queue, consumer) -> launchConsumer(consumer, consumerConfigurations.get(queue), consumerStats.get(queue)));
111 } 119 }
112 120
113 @Override 121 @Override
@@ -115,7 +123,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -115,7 +123,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
115 consumers.values().forEach(TbQueueConsumer::unsubscribe); 123 consumers.values().forEach(TbQueueConsumer::unsubscribe);
116 } 124 }
117 125
118 - private void launchConsumer(TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> consumer, TbRuleEngineQueueConfiguration configuration) { 126 + private void launchConsumer(TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>> consumer, TbRuleEngineQueueConfiguration configuration, TbRuleEngineConsumerStats stats) {
119 consumersExecutor.execute(() -> { 127 consumersExecutor.execute(() -> {
120 while (!stopped) { 128 while (!stopped) {
121 try { 129 try {
@@ -123,7 +131,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -123,7 +131,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
123 if (msgs.isEmpty()) { 131 if (msgs.isEmpty()) {
124 continue; 132 continue;
125 } 133 }
126 - TbRuleEngineProcessingStrategy strategy = factory.newInstance(configuration.getAckStrategy()); 134 + TbRuleEngineProcessingStrategy strategy = factory.newInstance(configuration.getName(), configuration.getAckStrategy());
127 TbRuleEngineProcessingDecision decision = null; 135 TbRuleEngineProcessingDecision decision = null;
128 boolean firstAttempt = true; 136 boolean firstAttempt = true;
129 while (!stopped && (firstAttempt || !decision.isCommit())) { 137 while (!stopped && (firstAttempt || !decision.isCommit())) {
@@ -137,21 +145,21 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -137,21 +145,21 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
137 } 145 }
138 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap = new ConcurrentHashMap<>(); 146 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap = new ConcurrentHashMap<>();
139 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failedMap = new ConcurrentHashMap<>(); 147 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failedMap = new ConcurrentHashMap<>();
140 - 148 + ConcurrentMap<TenantId, RuleEngineException> exceptionsMap = new ConcurrentHashMap<>();
141 CountDownLatch processingTimeoutLatch = new CountDownLatch(1); 149 CountDownLatch processingTimeoutLatch = new CountDownLatch(1);
142 allMap.forEach((id, msg) -> { 150 allMap.forEach((id, msg) -> {
143 - log.info("[{}] Creating main callback for message: {}", id, msg.getValue());  
144 - TbMsgCallback callback = new MsgPackCallback<>(id, processingTimeoutLatch, allMap, successMap, failedMap); 151 + log.trace("[{}] Creating main callback for message: {}", id, msg.getValue());
  152 + ToRuleEngineMsg toRuleEngineMsg = msg.getValue();
  153 + TenantId tenantId = new TenantId(new UUID(toRuleEngineMsg.getTenantIdMSB(), toRuleEngineMsg.getTenantIdLSB()));
  154 + TbMsgCallback callback = new TbMsgPackCallback<>(id, tenantId, processingTimeoutLatch, allMap, successMap, failedMap, exceptionsMap);
145 try { 155 try {
146 - ToRuleEngineMsg toRuleEngineMsg = msg.getValue();  
147 - TenantId tenantId = new TenantId(new UUID(toRuleEngineMsg.getTenantIdMSB(), toRuleEngineMsg.getTenantIdLSB()));  
148 if (toRuleEngineMsg.getTbMsg() != null && !toRuleEngineMsg.getTbMsg().isEmpty()) { 156 if (toRuleEngineMsg.getTbMsg() != null && !toRuleEngineMsg.getTbMsg().isEmpty()) {
149 forwardToRuleEngineActor(tenantId, toRuleEngineMsg, callback); 157 forwardToRuleEngineActor(tenantId, toRuleEngineMsg, callback);
150 } else { 158 } else {
151 callback.onSuccess(); 159 callback.onSuccess();
152 } 160 }
153 - } catch (Throwable e) {  
154 - callback.onFailure(e); 161 + } catch (Exception e) {
  162 + callback.onFailure(new RuleEngineException(e.getMessage()));
155 } 163 }
156 }); 164 });
157 165
@@ -159,7 +167,11 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -159,7 +167,11 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
159 if (!processingTimeoutLatch.await(packProcessingTimeout, TimeUnit.MILLISECONDS)) { 167 if (!processingTimeoutLatch.await(packProcessingTimeout, TimeUnit.MILLISECONDS)) {
160 timeout = true; 168 timeout = true;
161 } 169 }
162 - decision = strategy.analyze(new TbRuleEngineProcessingResult(timeout, allMap, successMap, failedMap)); 170 + TbRuleEngineProcessingResult result = new TbRuleEngineProcessingResult(timeout, allMap, successMap, failedMap, exceptionsMap);
  171 + decision = strategy.analyze(result);
  172 + if (statsEnabled) {
  173 + stats.log(result, decision.isCommit());
  174 + }
163 } 175 }
164 consumer.commit(); 176 consumer.commit();
165 } catch (Exception e) { 177 } catch (Exception e) {
@@ -193,7 +205,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -193,7 +205,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
193 } 205 }
194 206
195 @Override 207 @Override
196 - protected void handleNotification(UUID id, TbProtoQueueMsg<ToRuleEngineNotificationMsg> msg, TbMsgCallback callback) throws Exception { 208 + protected void handleNotification(UUID id, TbProtoQueueMsg<ToRuleEngineNotificationMsg> msg, TbCallback callback) throws Exception {
197 ToRuleEngineNotificationMsg nfMsg = msg.getValue(); 209 ToRuleEngineNotificationMsg nfMsg = msg.getValue();
198 if (nfMsg.getComponentLifecycleMsg() != null && !nfMsg.getComponentLifecycleMsg().isEmpty()) { 210 if (nfMsg.getComponentLifecycleMsg() != null && !nfMsg.getComponentLifecycleMsg().isEmpty()) {
199 Optional<TbActorMsg> actorMsg = encodingService.decode(nfMsg.getComponentLifecycleMsg().toByteArray()); 211 Optional<TbActorMsg> actorMsg = encodingService.decode(nfMsg.getComponentLifecycleMsg().toByteArray());
@@ -219,18 +231,18 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @@ -219,18 +231,18 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
219 relationTypes = new HashSet<>(relationTypesList); 231 relationTypes = new HashSet<>(relationTypesList);
220 } 232 }
221 } 233 }
222 - msg = new QueueToRuleEngineMsg(tenantId, tbMsg, relationTypes); 234 + msg = new QueueToRuleEngineMsg(tenantId, tbMsg, relationTypes, toRuleEngineMsg.getFailureMessage());
223 actorContext.getAppActor().tell(msg, ActorRef.noSender()); 235 actorContext.getAppActor().tell(msg, ActorRef.noSender());
224 - //TODO: 2.5 before release.  
225 -// if (statsEnabled) {  
226 -// stats.log(toDeviceActorMsg);  
227 -// }  
228 } 236 }
229 237
230 @Scheduled(fixedDelayString = "${queue.rule-engine.stats.print-interval-ms}") 238 @Scheduled(fixedDelayString = "${queue.rule-engine.stats.print-interval-ms}")
231 public void printStats() { 239 public void printStats() {
232 if (statsEnabled) { 240 if (statsEnabled) {
233 - stats.printStats(); 241 + long ts = System.currentTimeMillis();
  242 + consumerStats.forEach((queue, stats) -> {
  243 + stats.printStats();
  244 + statisticsService.reportQueueStats(ts, stats);
  245 + });
234 } 246 }
235 } 247 }
236 248
  1 +/**
  2 + * Copyright © 2016-2020 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.service.queue;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.thingsboard.server.common.data.id.TenantId;
  20 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  21 +import org.thingsboard.server.common.msg.queue.RuleNodeException;
  22 +import org.thingsboard.server.common.msg.queue.TbCallback;
  23 +import org.thingsboard.server.common.msg.queue.TbMsgCallback;
  24 +
  25 +import java.util.UUID;
  26 +import java.util.concurrent.ConcurrentMap;
  27 +import java.util.concurrent.CountDownLatch;
  28 +
  29 +@Slf4j
  30 +public class TbMsgPackCallback<T> implements TbMsgCallback {
  31 + private final CountDownLatch processingTimeoutLatch;
  32 + private final ConcurrentMap<UUID, T> ackMap;
  33 + private final ConcurrentMap<UUID, T> successMap;
  34 + private final ConcurrentMap<UUID, T> failedMap;
  35 + private final UUID id;
  36 + private final TenantId tenantId;
  37 + private final ConcurrentMap<TenantId, RuleEngineException> firstExceptions;
  38 +
  39 + public TbMsgPackCallback(UUID id, TenantId tenantId,
  40 + CountDownLatch processingTimeoutLatch,
  41 + ConcurrentMap<UUID, T> ackMap,
  42 + ConcurrentMap<UUID, T> successMap,
  43 + ConcurrentMap<UUID, T> failedMap,
  44 + ConcurrentMap<TenantId, RuleEngineException> firstExceptions) {
  45 + this.id = id;
  46 + this.tenantId = tenantId;
  47 + this.processingTimeoutLatch = processingTimeoutLatch;
  48 + this.ackMap = ackMap;
  49 + this.successMap = successMap;
  50 + this.failedMap = failedMap;
  51 + this.firstExceptions = firstExceptions;
  52 + }
  53 +
  54 + @Override
  55 + public void onSuccess() {
  56 + log.trace("[{}] ON SUCCESS", id);
  57 + T msg = ackMap.remove(id);
  58 + if (msg != null) {
  59 + successMap.put(id, msg);
  60 + }
  61 + if (msg != null && ackMap.isEmpty()) {
  62 + processingTimeoutLatch.countDown();
  63 + }
  64 + }
  65 +
  66 + @Override
  67 + public void onFailure(RuleEngineException e) {
  68 + log.trace("[{}] ON FAILURE", id, e);
  69 + T msg = ackMap.remove(id);
  70 + if (msg != null) {
  71 + failedMap.put(id, msg);
  72 + firstExceptions.putIfAbsent(tenantId, e);
  73 + }
  74 + if (ackMap.isEmpty()) {
  75 + processingTimeoutLatch.countDown();
  76 + }
  77 + }
  78 +}
application/src/main/java/org/thingsboard/server/service/queue/TbPackCallback.java renamed from application/src/main/java/org/thingsboard/server/service/queue/MsgPackCallback.java
@@ -16,30 +16,26 @@ @@ -16,30 +16,26 @@
16 package org.thingsboard.server.service.queue; 16 package org.thingsboard.server.service.queue;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 -import org.thingsboard.server.common.msg.queue.TbMsgCallback;  
20 -import org.thingsboard.server.queue.common.TbProtoQueueMsg; 19 +import org.thingsboard.server.common.msg.queue.TbCallback;
21 20
22 import java.util.UUID; 21 import java.util.UUID;
23 -import java.util.concurrent.ConcurrentHashMap;  
24 import java.util.concurrent.ConcurrentMap; 22 import java.util.concurrent.ConcurrentMap;
25 import java.util.concurrent.CountDownLatch; 23 import java.util.concurrent.CountDownLatch;
26 24
27 @Slf4j 25 @Slf4j
28 -public class MsgPackCallback<T> implements TbMsgCallback { 26 +public class TbPackCallback<T> implements TbCallback {
29 private final CountDownLatch processingTimeoutLatch; 27 private final CountDownLatch processingTimeoutLatch;
30 private final ConcurrentMap<UUID, T> ackMap; 28 private final ConcurrentMap<UUID, T> ackMap;
31 - private final ConcurrentMap<UUID, T> successMap;  
32 private final ConcurrentMap<UUID, T> failedMap; 29 private final ConcurrentMap<UUID, T> failedMap;
33 private final UUID id; 30 private final UUID id;
34 31
35 - public MsgPackCallback(UUID id, CountDownLatch processingTimeoutLatch,  
36 - ConcurrentMap<UUID, T> ackMap,  
37 - ConcurrentMap<UUID, T> successMap,  
38 - ConcurrentMap<UUID, T> failedMap) { 32 + public TbPackCallback(UUID id,
  33 + CountDownLatch processingTimeoutLatch,
  34 + ConcurrentMap<UUID, T> ackMap,
  35 + ConcurrentMap<UUID, T> failedMap) {
39 this.id = id; 36 this.id = id;
40 this.processingTimeoutLatch = processingTimeoutLatch; 37 this.processingTimeoutLatch = processingTimeoutLatch;
41 this.ackMap = ackMap; 38 this.ackMap = ackMap;
42 - this.successMap = successMap;  
43 this.failedMap = failedMap; 39 this.failedMap = failedMap;
44 } 40 }
45 41
@@ -47,9 +43,6 @@ public class MsgPackCallback<T> implements TbMsgCallback { @@ -47,9 +43,6 @@ public class MsgPackCallback<T> implements TbMsgCallback {
47 public void onSuccess() { 43 public void onSuccess() {
48 log.trace("[{}] ON SUCCESS", id); 44 log.trace("[{}] ON SUCCESS", id);
49 T msg = ackMap.remove(id); 45 T msg = ackMap.remove(id);
50 - if (msg != null) {  
51 - successMap.put(id, msg);  
52 - }  
53 if (msg != null && ackMap.isEmpty()) { 46 if (msg != null && ackMap.isEmpty()) {
54 processingTimeoutLatch.countDown(); 47 processingTimeoutLatch.countDown();
55 } 48 }
@@ -57,7 +50,7 @@ public class MsgPackCallback<T> implements TbMsgCallback { @@ -57,7 +50,7 @@ public class MsgPackCallback<T> implements TbMsgCallback {
57 50
58 @Override 51 @Override
59 public void onFailure(Throwable t) { 52 public void onFailure(Throwable t) {
60 - log.trace("[{}] ON FAILURE", id); 53 + log.trace("[{}] ON FAILURE", id, t);
61 T msg = ackMap.remove(id); 54 T msg = ackMap.remove(id);
62 if (msg != null) { 55 if (msg != null) {
63 failedMap.put(id, msg); 56 failedMap.put(id, msg);
@@ -15,38 +15,119 @@ @@ -15,38 +15,119 @@
15 */ 15 */
16 package org.thingsboard.server.service.queue; 16 package org.thingsboard.server.service.queue;
17 17
  18 +import lombok.Data;
18 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
19 -import org.thingsboard.server.gen.transport.TransportProtos; 20 +import org.thingsboard.server.common.data.id.TenantId;
  21 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  22 +import org.thingsboard.server.common.msg.queue.RuleNodeException;
  23 +import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
  24 +import org.thingsboard.server.queue.common.TbProtoQueueMsg;
  25 +import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingResult;
20 26
  27 +import java.util.HashMap;
  28 +import java.util.Map;
  29 +import java.util.UUID;
  30 +import java.util.concurrent.ConcurrentHashMap;
  31 +import java.util.concurrent.ConcurrentMap;
21 import java.util.concurrent.atomic.AtomicInteger; 32 import java.util.concurrent.atomic.AtomicInteger;
22 33
23 @Slf4j 34 @Slf4j
  35 +@Data
24 public class TbRuleEngineConsumerStats { 36 public class TbRuleEngineConsumerStats {
25 37
26 - private final AtomicInteger totalCounter = new AtomicInteger(0);  
27 - private final AtomicInteger postTelemetryCounter = new AtomicInteger(0);  
28 - private final AtomicInteger postAttributesCounter = new AtomicInteger(0);  
29 - private final AtomicInteger toServerRPCCallRequestCounter = new AtomicInteger(0); 38 + public static final String TOTAL_MSGS = "totalMsgs";
  39 + public static final String SUCCESSFUL_MSGS = "successfulMsgs";
  40 + public static final String TMP_TIMEOUT = "tmpTimeout";
  41 + public static final String TMP_FAILED = "tmpFailed";
  42 + public static final String TIMEOUT_MSGS = "timeoutMsgs";
  43 + public static final String FAILED_MSGS = "failedMsgs";
  44 + public static final String SUCCESSFUL_ITERATIONS = "successfulIterations";
  45 + public static final String FAILED_ITERATIONS = "failedIterations";
30 46
31 - public void log(TransportProtos.TransportToRuleEngineMsg msg) {  
32 - totalCounter.incrementAndGet();  
33 - if (msg.hasPostTelemetry()) {  
34 - postTelemetryCounter.incrementAndGet();  
35 - }  
36 - if (msg.hasPostAttributes()) {  
37 - postAttributesCounter.incrementAndGet();  
38 - }  
39 - if (msg.hasToServerRPCCallRequest()) {  
40 - toServerRPCCallRequestCounter.incrementAndGet(); 47 + private final AtomicInteger totalMsgCounter = new AtomicInteger(0);
  48 + private final AtomicInteger successMsgCounter = new AtomicInteger(0);
  49 + private final AtomicInteger tmpTimeoutMsgCounter = new AtomicInteger(0);
  50 + private final AtomicInteger tmpFailedMsgCounter = new AtomicInteger(0);
  51 +
  52 + private final AtomicInteger timeoutMsgCounter = new AtomicInteger(0);
  53 + private final AtomicInteger failedMsgCounter = new AtomicInteger(0);
  54 +
  55 + private final AtomicInteger successIterationsCounter = new AtomicInteger(0);
  56 + private final AtomicInteger failedIterationsCounter = new AtomicInteger(0);
  57 +
  58 + private final Map<String, AtomicInteger> counters = new HashMap<>();
  59 + private final ConcurrentMap<UUID, TbTenantRuleEngineStats> tenantStats = new ConcurrentHashMap<>();
  60 + private final ConcurrentMap<TenantId, RuleEngineException> tenantExceptions = new ConcurrentHashMap<>();
  61 +
  62 + private final String queueName;
  63 +
  64 + public TbRuleEngineConsumerStats(String queueName) {
  65 + this.queueName = queueName;
  66 + counters.put(TOTAL_MSGS, totalMsgCounter);
  67 + counters.put(SUCCESSFUL_MSGS, successMsgCounter);
  68 + counters.put(TIMEOUT_MSGS, timeoutMsgCounter);
  69 + counters.put(FAILED_MSGS, failedMsgCounter);
  70 +
  71 + counters.put(TMP_TIMEOUT, tmpTimeoutMsgCounter);
  72 + counters.put(TMP_FAILED, tmpFailedMsgCounter);
  73 + counters.put(SUCCESSFUL_ITERATIONS, successIterationsCounter);
  74 + counters.put(FAILED_ITERATIONS, failedIterationsCounter);
  75 + }
  76 +
  77 + public void log(TbRuleEngineProcessingResult msg, boolean finalIterationForPack) {
  78 + int success = msg.getSuccessMap().size();
  79 + int pending = msg.getPendingMap().size();
  80 + int failed = msg.getFailureMap().size();
  81 + totalMsgCounter.addAndGet(success + pending + failed);
  82 + successMsgCounter.addAndGet(success);
  83 + msg.getSuccessMap().values().forEach(m -> getTenantStats(m).logSuccess());
  84 + if (finalIterationForPack) {
  85 + if (pending > 0 || failed > 0) {
  86 + timeoutMsgCounter.addAndGet(pending);
  87 + failedMsgCounter.addAndGet(failed);
  88 + if (pending > 0) {
  89 + msg.getPendingMap().values().forEach(m -> getTenantStats(m).logTimeout());
  90 + }
  91 + if (failed > 0) {
  92 + msg.getFailureMap().values().forEach(m -> getTenantStats(m).logFailed());
  93 + }
  94 + failedIterationsCounter.incrementAndGet();
  95 + } else {
  96 + successIterationsCounter.incrementAndGet();
  97 + }
  98 + } else {
  99 + failedIterationsCounter.incrementAndGet();
  100 + tmpTimeoutMsgCounter.addAndGet(pending);
  101 + tmpFailedMsgCounter.addAndGet(failed);
  102 + if (pending > 0) {
  103 + msg.getPendingMap().values().forEach(m -> getTenantStats(m).logTmpTimeout());
  104 + }
  105 + if (failed > 0) {
  106 + msg.getFailureMap().values().forEach(m -> getTenantStats(m).logTmpFailed());
  107 + }
41 } 108 }
  109 + msg.getExceptionsMap().forEach(tenantExceptions::putIfAbsent);
  110 + }
  111 +
  112 + private TbTenantRuleEngineStats getTenantStats(TbProtoQueueMsg<ToRuleEngineMsg> m) {
  113 + ToRuleEngineMsg reMsg = m.getValue();
  114 + return tenantStats.computeIfAbsent(new UUID(reMsg.getTenantIdMSB(), reMsg.getTenantIdLSB()), TbTenantRuleEngineStats::new);
42 } 115 }
43 116
44 public void printStats() { 117 public void printStats() {
45 - int total = totalCounter.getAndSet(0); 118 + int total = totalMsgCounter.get();
46 if (total > 0) { 119 if (total > 0) {
47 - log.info("Transport total [{}] telemetry [{}] attributes [{}] toServerRpc [{}]",  
48 - total, postTelemetryCounter.getAndSet(0),  
49 - postAttributesCounter.getAndSet(0), toServerRPCCallRequestCounter.getAndSet(0)); 120 + StringBuilder stats = new StringBuilder();
  121 + counters.forEach((label, value) -> {
  122 + stats.append(label).append(" = [").append(value.get()).append("] ");
  123 + });
  124 + log.info("[{}] Stats: {}", queueName, stats);
50 } 125 }
51 } 126 }
  127 +
  128 + public void reset() {
  129 + counters.values().forEach(counter -> counter.set(0));
  130 + tenantStats.clear();
  131 + tenantExceptions.clear();
  132 + }
52 } 133 }
  1 +/**
  2 + * Copyright © 2016-2020 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.service.queue;
  17 +
  18 +import lombok.Data;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +
  21 +import java.util.HashMap;
  22 +import java.util.Map;
  23 +import java.util.UUID;
  24 +import java.util.concurrent.atomic.AtomicInteger;
  25 +
  26 +@Slf4j
  27 +@Data
  28 +public class TbTenantRuleEngineStats {
  29 +
  30 + private final UUID tenantId;
  31 +
  32 + private final AtomicInteger totalMsgCounter = new AtomicInteger(0);
  33 + private final AtomicInteger successMsgCounter = new AtomicInteger(0);
  34 + private final AtomicInteger tmpTimeoutMsgCounter = new AtomicInteger(0);
  35 + private final AtomicInteger tmpFailedMsgCounter = new AtomicInteger(0);
  36 +
  37 + private final AtomicInteger timeoutMsgCounter = new AtomicInteger(0);
  38 + private final AtomicInteger failedMsgCounter = new AtomicInteger(0);
  39 +
  40 + private final Map<String, AtomicInteger> counters = new HashMap<>();
  41 +
  42 + public TbTenantRuleEngineStats(UUID tenantId) {
  43 + this.tenantId = tenantId;
  44 + counters.put(TbRuleEngineConsumerStats.TOTAL_MSGS, totalMsgCounter);
  45 + counters.put(TbRuleEngineConsumerStats.SUCCESSFUL_MSGS, successMsgCounter);
  46 + counters.put(TbRuleEngineConsumerStats.TIMEOUT_MSGS, timeoutMsgCounter);
  47 + counters.put(TbRuleEngineConsumerStats.FAILED_MSGS, failedMsgCounter);
  48 +
  49 + counters.put(TbRuleEngineConsumerStats.TMP_TIMEOUT, tmpTimeoutMsgCounter);
  50 + counters.put(TbRuleEngineConsumerStats.TMP_FAILED, tmpFailedMsgCounter);
  51 + }
  52 +
  53 + public void logSuccess() {
  54 + totalMsgCounter.incrementAndGet();
  55 + successMsgCounter.incrementAndGet();
  56 + }
  57 +
  58 + public void logFailed() {
  59 + totalMsgCounter.incrementAndGet();
  60 + failedMsgCounter.incrementAndGet();
  61 + }
  62 +
  63 + public void logTimeout() {
  64 + totalMsgCounter.incrementAndGet();
  65 + timeoutMsgCounter.incrementAndGet();
  66 + }
  67 +
  68 + public void logTmpFailed() {
  69 + totalMsgCounter.incrementAndGet();
  70 + tmpFailedMsgCounter.incrementAndGet();
  71 + }
  72 +
  73 + public void logTmpTimeout() {
  74 + totalMsgCounter.incrementAndGet();
  75 + tmpTimeoutMsgCounter.incrementAndGet();
  76 + }
  77 +
  78 + public void printStats() {
  79 + int total = totalMsgCounter.get();
  80 + if (total > 0) {
  81 + StringBuilder stats = new StringBuilder();
  82 + counters.forEach((label, value) -> {
  83 + stats.append(label).append(" = [").append(value.get()).append("]");
  84 + });
  85 + log.info("[{}] Stats: {}", tenantId, stats);
  86 + }
  87 + }
  88 +
  89 + public void reset() {
  90 + counters.values().forEach(counter -> counter.set(0));
  91 + }
  92 +}
@@ -22,12 +22,12 @@ import org.springframework.context.event.EventListener; @@ -22,12 +22,12 @@ import org.springframework.context.event.EventListener;
22 import org.thingsboard.common.util.ThingsBoardThreadFactory; 22 import org.thingsboard.common.util.ThingsBoardThreadFactory;
23 import org.thingsboard.server.actors.ActorSystemContext; 23 import org.thingsboard.server.actors.ActorSystemContext;
24 import org.thingsboard.server.common.msg.queue.ServiceType; 24 import org.thingsboard.server.common.msg.queue.ServiceType;
25 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 25 +import org.thingsboard.server.common.msg.queue.TbCallback;
26 import org.thingsboard.server.queue.TbQueueConsumer; 26 import org.thingsboard.server.queue.TbQueueConsumer;
27 import org.thingsboard.server.queue.common.TbProtoQueueMsg; 27 import org.thingsboard.server.queue.common.TbProtoQueueMsg;
28 import org.thingsboard.server.queue.discovery.PartitionChangeEvent; 28 import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
29 import org.thingsboard.server.service.encoding.DataDecodingEncodingService; 29 import org.thingsboard.server.service.encoding.DataDecodingEncodingService;
30 -import org.thingsboard.server.service.queue.MsgPackCallback; 30 +import org.thingsboard.server.service.queue.TbPackCallback;
31 31
32 import javax.annotation.PreDestroy; 32 import javax.annotation.PreDestroy;
33 import java.util.List; 33 import java.util.List;
@@ -95,8 +95,8 @@ public abstract class AbstractConsumerService<N extends com.google.protobuf.Gene @@ -95,8 +95,8 @@ public abstract class AbstractConsumerService<N extends com.google.protobuf.Gene
95 ConcurrentMap<UUID, TbProtoQueueMsg<N>> failedMap = new ConcurrentHashMap<>(); 95 ConcurrentMap<UUID, TbProtoQueueMsg<N>> failedMap = new ConcurrentHashMap<>();
96 CountDownLatch processingTimeoutLatch = new CountDownLatch(1); 96 CountDownLatch processingTimeoutLatch = new CountDownLatch(1);
97 pendingMap.forEach((id, msg) -> { 97 pendingMap.forEach((id, msg) -> {
98 - log.info("[{}] Creating notification callback for message: {}", id, msg.getValue());  
99 - TbMsgCallback callback = new MsgPackCallback<>(id, processingTimeoutLatch, pendingMap, new ConcurrentHashMap<>(), failedMap); 98 + log.trace("[{}] Creating notification callback for message: {}", id, msg.getValue());
  99 + TbCallback callback = new TbPackCallback<>(id, processingTimeoutLatch, pendingMap, failedMap);
100 try { 100 try {
101 handleNotification(id, msg, callback); 101 handleNotification(id, msg, callback);
102 } catch (Throwable e) { 102 } catch (Throwable e) {
@@ -124,7 +124,7 @@ public abstract class AbstractConsumerService<N extends com.google.protobuf.Gene @@ -124,7 +124,7 @@ public abstract class AbstractConsumerService<N extends com.google.protobuf.Gene
124 }); 124 });
125 } 125 }
126 126
127 - protected abstract void handleNotification(UUID id, TbProtoQueueMsg<N> msg, TbMsgCallback callback) throws Exception; 127 + protected abstract void handleNotification(UUID id, TbProtoQueueMsg<N> msg, TbCallback callback) throws Exception;
128 128
129 @PreDestroy 129 @PreDestroy
130 public void destroy() { 130 public void destroy() {
@@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
16 package org.thingsboard.server.service.queue.processing; 16 package org.thingsboard.server.service.queue.processing;
17 17
18 import lombok.Getter; 18 import lombok.Getter;
  19 +import org.thingsboard.server.common.data.id.TenantId;
  20 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
19 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; 21 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
20 import org.thingsboard.server.queue.common.TbProtoQueueMsg; 22 import org.thingsboard.server.queue.common.TbProtoQueueMsg;
21 23
@@ -25,24 +27,28 @@ import java.util.concurrent.ConcurrentMap; @@ -25,24 +27,28 @@ import java.util.concurrent.ConcurrentMap;
25 public class TbRuleEngineProcessingResult { 27 public class TbRuleEngineProcessingResult {
26 28
27 @Getter 29 @Getter
28 - private boolean success; 30 + private final boolean success;
29 @Getter 31 @Getter
30 - private boolean timeout; 32 + private final boolean timeout;
31 @Getter 33 @Getter
32 - private ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> pendingMap; 34 + private final ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> pendingMap;
33 @Getter 35 @Getter
34 - private ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap; 36 + private final ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap;
35 @Getter 37 @Getter
36 - private ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failureMap; 38 + private final ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failureMap;
  39 + @Getter
  40 + private final ConcurrentMap<TenantId, RuleEngineException> exceptionsMap;
37 41
38 public TbRuleEngineProcessingResult(boolean timeout, 42 public TbRuleEngineProcessingResult(boolean timeout,
39 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> pendingMap, 43 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> pendingMap,
40 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap, 44 ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap,
41 - ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failureMap) { 45 + ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failureMap,
  46 + ConcurrentMap<TenantId, RuleEngineException> exceptionsMap) {
42 this.timeout = timeout; 47 this.timeout = timeout;
43 this.pendingMap = pendingMap; 48 this.pendingMap = pendingMap;
44 this.successMap = successMap; 49 this.successMap = successMap;
45 this.failureMap = failureMap; 50 this.failureMap = failureMap;
  51 + this.exceptionsMap = exceptionsMap;
46 this.success = !timeout && pendingMap.isEmpty() && failureMap.isEmpty(); 52 this.success = !timeout && pendingMap.isEmpty() && failureMap.isEmpty();
47 } 53 }
48 } 54 }
@@ -32,24 +32,25 @@ import java.util.concurrent.TimeUnit; @@ -32,24 +32,25 @@ import java.util.concurrent.TimeUnit;
32 @Slf4j 32 @Slf4j
33 public class TbRuleEngineProcessingStrategyFactory { 33 public class TbRuleEngineProcessingStrategyFactory {
34 34
35 - public TbRuleEngineProcessingStrategy newInstance(TbRuleEngineQueueAckStrategyConfiguration configuration) { 35 + public TbRuleEngineProcessingStrategy newInstance(String name, TbRuleEngineQueueAckStrategyConfiguration configuration) {
36 switch (configuration.getType()) { 36 switch (configuration.getType()) {
37 case "SKIP_ALL": 37 case "SKIP_ALL":
38 - return new SkipStrategy(); 38 + return new SkipStrategy(name);
39 case "RETRY_ALL": 39 case "RETRY_ALL":
40 - return new RetryStrategy(true, true, true, configuration); 40 + return new RetryStrategy(name, true, true, true, configuration);
41 case "RETRY_FAILED": 41 case "RETRY_FAILED":
42 - return new RetryStrategy(false, true, false, configuration); 42 + return new RetryStrategy(name, false, true, false, configuration);
43 case "RETRY_TIMED_OUT": 43 case "RETRY_TIMED_OUT":
44 - return new RetryStrategy(false, false, true, configuration); 44 + return new RetryStrategy(name, false, false, true, configuration);
45 case "RETRY_FAILED_AND_TIMED_OUT": 45 case "RETRY_FAILED_AND_TIMED_OUT":
46 - return new RetryStrategy(false, true, true, configuration); 46 + return new RetryStrategy(name, false, true, true, configuration);
47 default: 47 default:
48 throw new RuntimeException("TbRuleEngineProcessingStrategy with type " + configuration.getType() + " is not supported!"); 48 throw new RuntimeException("TbRuleEngineProcessingStrategy with type " + configuration.getType() + " is not supported!");
49 } 49 }
50 } 50 }
51 51
52 private static class RetryStrategy implements TbRuleEngineProcessingStrategy { 52 private static class RetryStrategy implements TbRuleEngineProcessingStrategy {
  53 + private final String queueName;
53 private final boolean retrySuccessful; 54 private final boolean retrySuccessful;
54 private final boolean retryFailed; 55 private final boolean retryFailed;
55 private final boolean retryTimeout; 56 private final boolean retryTimeout;
@@ -60,7 +61,8 @@ public class TbRuleEngineProcessingStrategyFactory { @@ -60,7 +61,8 @@ public class TbRuleEngineProcessingStrategyFactory {
60 private int initialTotalCount; 61 private int initialTotalCount;
61 private int retryCount; 62 private int retryCount;
62 63
63 - public RetryStrategy(boolean retrySuccessful, boolean retryFailed, boolean retryTimeout, TbRuleEngineQueueAckStrategyConfiguration configuration) { 64 + public RetryStrategy(String queueName, boolean retrySuccessful, boolean retryFailed, boolean retryTimeout, TbRuleEngineQueueAckStrategyConfiguration configuration) {
  65 + this.queueName = queueName;
64 this.retrySuccessful = retrySuccessful; 66 this.retrySuccessful = retrySuccessful;
65 this.retryFailed = retryFailed; 67 this.retryFailed = retryFailed;
66 this.retryTimeout = retryTimeout; 68 this.retryTimeout = retryTimeout;
@@ -80,10 +82,10 @@ public class TbRuleEngineProcessingStrategyFactory { @@ -80,10 +82,10 @@ public class TbRuleEngineProcessingStrategyFactory {
80 retryCount++; 82 retryCount++;
81 double failedCount = result.getFailureMap().size() + result.getPendingMap().size(); 83 double failedCount = result.getFailureMap().size() + result.getPendingMap().size();
82 if (maxRetries > 0 && retryCount > maxRetries) { 84 if (maxRetries > 0 && retryCount > maxRetries) {
83 - log.info("Skip reprocess of the rule engine pack due to max retries"); 85 + log.info("[{}] Skip reprocess of the rule engine pack due to max retries", queueName);
84 return new TbRuleEngineProcessingDecision(true, null); 86 return new TbRuleEngineProcessingDecision(true, null);
85 } else if (maxAllowedFailurePercentage > 0 && (failedCount / initialTotalCount) > maxAllowedFailurePercentage) { 87 } else if (maxAllowedFailurePercentage > 0 && (failedCount / initialTotalCount) > maxAllowedFailurePercentage) {
86 - log.info("Skip reprocess of the rule engine pack due to max allowed failure percentage"); 88 + log.info("[{}] Skip reprocess of the rule engine pack due to max allowed failure percentage", queueName);
87 return new TbRuleEngineProcessingDecision(true, null); 89 return new TbRuleEngineProcessingDecision(true, null);
88 } else { 90 } else {
89 ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> toReprocess = new ConcurrentHashMap<>(initialTotalCount); 91 ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> toReprocess = new ConcurrentHashMap<>(initialTotalCount);
@@ -96,8 +98,7 @@ public class TbRuleEngineProcessingStrategyFactory { @@ -96,8 +98,7 @@ public class TbRuleEngineProcessingStrategyFactory {
96 if (retrySuccessful) { 98 if (retrySuccessful) {
97 result.getSuccessMap().forEach(toReprocess::put); 99 result.getSuccessMap().forEach(toReprocess::put);
98 } 100 }
99 - log.info("Going to reprocess {} messages", toReprocess.size());  
100 - //TODO: 2.5 Log most popular rule nodes by error count; 101 + log.info("[{}] Going to reprocess {} messages", queueName, toReprocess.size());
101 if (log.isTraceEnabled()) { 102 if (log.isTraceEnabled()) {
102 toReprocess.forEach((id, msg) -> log.trace("Going to reprocess [{}]: {}", id, msg.getValue())); 103 toReprocess.forEach((id, msg) -> log.trace("Going to reprocess [{}]: {}", id, msg.getValue()));
103 } 104 }
@@ -116,9 +117,15 @@ public class TbRuleEngineProcessingStrategyFactory { @@ -116,9 +117,15 @@ public class TbRuleEngineProcessingStrategyFactory {
116 117
117 private static class SkipStrategy implements TbRuleEngineProcessingStrategy { 118 private static class SkipStrategy implements TbRuleEngineProcessingStrategy {
118 119
  120 + private final String queueName;
  121 +
  122 + public SkipStrategy(String name) {
  123 + this.queueName = name;
  124 + }
  125 +
119 @Override 126 @Override
120 public TbRuleEngineProcessingDecision analyze(TbRuleEngineProcessingResult result) { 127 public TbRuleEngineProcessingDecision analyze(TbRuleEngineProcessingResult result) {
121 - log.info("Skip reprocess of the rule engine pack"); 128 + log.info("[{}] Reprocessing skipped for {} failed and {} timeout messages", queueName, result.getFailureMap().size(), result.getPendingMap().size());
122 return new TbRuleEngineProcessingDecision(true, null); 129 return new TbRuleEngineProcessingDecision(true, null);
123 } 130 }
124 } 131 }
@@ -19,7 +19,6 @@ import lombok.Getter; @@ -19,7 +19,6 @@ import lombok.Getter;
19 import lombok.RequiredArgsConstructor; 19 import lombok.RequiredArgsConstructor;
20 import lombok.ToString; 20 import lombok.ToString;
21 import org.thingsboard.rule.engine.api.RpcError; 21 import org.thingsboard.rule.engine.api.RpcError;
22 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
23 22
24 import java.util.Optional; 23 import java.util.Optional;
25 import java.util.UUID; 24 import java.util.UUID;
@@ -22,11 +22,8 @@ import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; @@ -22,11 +22,8 @@ import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg;
22 import org.thingsboard.server.common.data.id.DeviceId; 22 import org.thingsboard.server.common.data.id.DeviceId;
23 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.common.msg.MsgType; 24 import org.thingsboard.server.common.msg.MsgType;
25 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
26 import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; 25 import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest;
27 26
28 -import java.util.Optional;  
29 -  
30 /** 27 /**
31 * Created by ashvayka on 16.04.18. 28 * Created by ashvayka on 16.04.18.
32 */ 29 */
@@ -55,7 +55,7 @@ import org.thingsboard.server.queue.discovery.PartitionService; @@ -55,7 +55,7 @@ import org.thingsboard.server.queue.discovery.PartitionService;
55 import org.thingsboard.server.common.msg.queue.ServiceType; 55 import org.thingsboard.server.common.msg.queue.ServiceType;
56 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; 56 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
57 import org.thingsboard.server.gen.transport.TransportProtos; 57 import org.thingsboard.server.gen.transport.TransportProtos;
58 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 58 +import org.thingsboard.server.common.msg.queue.TbCallback;
59 import org.thingsboard.server.queue.provider.TbQueueProducerProvider; 59 import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
60 import org.thingsboard.server.queue.util.TbCoreComponent; 60 import org.thingsboard.server.queue.util.TbCoreComponent;
61 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; 61 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
@@ -242,7 +242,7 @@ public class DefaultDeviceStateService implements DeviceStateService { @@ -242,7 +242,7 @@ public class DefaultDeviceStateService implements DeviceStateService {
242 } 242 }
243 243
244 @Override 244 @Override
245 - public void onQueueMsg(TransportProtos.DeviceStateServiceMsgProto proto, TbMsgCallback callback) { 245 + public void onQueueMsg(TransportProtos.DeviceStateServiceMsgProto proto, TbCallback callback) {
246 try { 246 try {
247 TenantId tenantId = new TenantId(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())); 247 TenantId tenantId = new TenantId(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB()));
248 DeviceId deviceId = new DeviceId(new UUID(proto.getDeviceIdMSB(), proto.getDeviceIdLSB())); 248 DeviceId deviceId = new DeviceId(new UUID(proto.getDeviceIdMSB(), proto.getDeviceIdLSB()));
@@ -20,7 +20,7 @@ import org.thingsboard.server.common.data.Device; @@ -20,7 +20,7 @@ import org.thingsboard.server.common.data.Device;
20 import org.thingsboard.server.common.data.id.DeviceId; 20 import org.thingsboard.server.common.data.id.DeviceId;
21 import org.thingsboard.server.queue.discovery.PartitionChangeEvent; 21 import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
22 import org.thingsboard.server.gen.transport.TransportProtos; 22 import org.thingsboard.server.gen.transport.TransportProtos;
23 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 23 +import org.thingsboard.server.common.msg.queue.TbCallback;
24 24
25 /** 25 /**
26 * Created by ashvayka on 01.05.18. 26 * Created by ashvayka on 01.05.18.
@@ -41,6 +41,6 @@ public interface DeviceStateService extends ApplicationListener<PartitionChangeE @@ -41,6 +41,6 @@ public interface DeviceStateService extends ApplicationListener<PartitionChangeE
41 41
42 void onDeviceInactivityTimeoutUpdate(DeviceId deviceId, long inactivityTimeout); 42 void onDeviceInactivityTimeoutUpdate(DeviceId deviceId, long inactivityTimeout);
43 43
44 - void onQueueMsg(TransportProtos.DeviceStateServiceMsgProto serverAddress, TbMsgCallback bytes); 44 + void onQueueMsg(TransportProtos.DeviceStateServiceMsgProto serverAddress, TbCallback bytes);
45 45
46 } 46 }
  1 +/**
  2 + * Copyright © 2016-2020 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.service.stats;
  17 +
  18 +import com.google.common.util.concurrent.FutureCallback;
  19 +import lombok.Data;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.springframework.stereotype.Service;
  22 +import org.thingsboard.server.common.data.asset.Asset;
  23 +import org.thingsboard.server.common.data.id.AssetId;
  24 +import org.thingsboard.server.common.data.id.TenantId;
  25 +import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
  26 +import org.thingsboard.server.common.data.kv.JsonDataEntry;
  27 +import org.thingsboard.server.common.data.kv.LongDataEntry;
  28 +import org.thingsboard.server.common.data.kv.TsKvEntry;
  29 +import org.thingsboard.server.dao.asset.AssetService;
  30 +import org.thingsboard.server.queue.discovery.TbServiceInfoProvider;
  31 +import org.thingsboard.server.queue.util.TbRuleEngineComponent;
  32 +import org.thingsboard.server.service.queue.TbRuleEngineConsumerStats;
  33 +import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
  34 +
  35 +import javax.annotation.Nullable;
  36 +import java.util.Collections;
  37 +import java.util.List;
  38 +import java.util.concurrent.ConcurrentHashMap;
  39 +import java.util.concurrent.ConcurrentMap;
  40 +import java.util.concurrent.locks.Lock;
  41 +import java.util.concurrent.locks.ReentrantLock;
  42 +import java.util.stream.Collectors;
  43 +
  44 +@TbRuleEngineComponent
  45 +@Service
  46 +@Slf4j
  47 +public class DefaultRuleEngineStatisticsService implements RuleEngineStatisticsService {
  48 +
  49 + public static final FutureCallback<Void> CALLBACK = new FutureCallback<Void>() {
  50 + @Override
  51 + public void onSuccess(@Nullable Void result) {
  52 +
  53 + }
  54 +
  55 + @Override
  56 + public void onFailure(Throwable t) {
  57 + log.warn("Failed to persist statistics", t);
  58 + }
  59 + };
  60 +
  61 + private final TbServiceInfoProvider serviceInfoProvider;
  62 + private final TelemetrySubscriptionService tsService;
  63 + private final Lock lock = new ReentrantLock();
  64 + private final AssetService assetService;
  65 + private final ConcurrentMap<TenantQueueKey, AssetId> tenantQueueAssets;
  66 +
  67 + public DefaultRuleEngineStatisticsService(TelemetrySubscriptionService tsService, TbServiceInfoProvider serviceInfoProvider, AssetService assetService) {
  68 + this.tsService = tsService;
  69 + this.serviceInfoProvider = serviceInfoProvider;
  70 + this.assetService = assetService;
  71 + this.tenantQueueAssets = new ConcurrentHashMap<>();
  72 + }
  73 +
  74 + @Override
  75 + public void reportQueueStats(long ts, TbRuleEngineConsumerStats ruleEngineStats) {
  76 + String queueName = ruleEngineStats.getQueueName();
  77 + ruleEngineStats.getTenantStats().forEach((id, stats) -> {
  78 + TenantId tenantId = new TenantId(id);
  79 + AssetId serviceAssetId = getServiceAssetId(tenantId, queueName);
  80 + if (stats.getTotalMsgCounter().get() > 0) {
  81 + List<TsKvEntry> tsList = stats.getCounters().entrySet().stream()
  82 + .map(kv -> new BasicTsKvEntry(ts, new LongDataEntry(kv.getKey(), (long) kv.getValue().get())))
  83 + .collect(Collectors.toList());
  84 + if (!tsList.isEmpty()) {
  85 + tsService.saveAndNotify(tenantId, serviceAssetId, tsList, CALLBACK);
  86 + }
  87 + }
  88 + });
  89 + ruleEngineStats.getTenantExceptions().forEach((tenantId, e) -> {
  90 + TsKvEntry tsKv = new BasicTsKvEntry(ts, new JsonDataEntry("ruleEngineException", e.toJsonString()));
  91 + tsService.saveAndNotify(tenantId, getServiceAssetId(tenantId, queueName), Collections.singletonList(tsKv), CALLBACK);
  92 + });
  93 + ruleEngineStats.reset();
  94 + }
  95 +
  96 + private AssetId getServiceAssetId(TenantId tenantId, String queueName) {
  97 + TenantQueueKey key = new TenantQueueKey(tenantId, queueName);
  98 + AssetId assetId = tenantQueueAssets.get(key);
  99 + if (assetId == null) {
  100 + lock.lock();
  101 + try {
  102 + assetId = tenantQueueAssets.get(key);
  103 + if (assetId == null) {
  104 + Asset asset = assetService.findAssetByTenantIdAndName(tenantId, queueName + "_" + serviceInfoProvider.getServiceId());
  105 + if (asset == null) {
  106 + asset = new Asset();
  107 + asset.setTenantId(tenantId);
  108 + asset.setName(queueName + "_" + serviceInfoProvider.getServiceId());
  109 + asset.setType("TbServiceQueue");
  110 + asset = assetService.saveAsset(asset);
  111 + }
  112 + assetId = asset.getId();
  113 + tenantQueueAssets.put(key, assetId);
  114 + }
  115 + } finally {
  116 + lock.unlock();
  117 + }
  118 + }
  119 + return assetId;
  120 + }
  121 +
  122 + @Data
  123 + private static class TenantQueueKey {
  124 + private final TenantId tenantId;
  125 + private final String queueName;
  126 + }
  127 +}
application/src/main/java/org/thingsboard/server/service/stats/RuleEngineStatisticsService.java renamed from common/message/src/main/java/org/thingsboard/server/common/msg/cluster/ServerType.java
@@ -13,11 +13,11 @@ @@ -13,11 +13,11 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.msg.cluster; 16 +package org.thingsboard.server.service.stats;
17 17
18 -/**  
19 - * Created by ashvayka on 23.09.18.  
20 - */  
21 -public enum ServerType {  
22 - CORE 18 +import org.thingsboard.server.service.queue.TbRuleEngineConsumerStats;
  19 +
  20 +public interface RuleEngineStatisticsService {
  21 +
  22 + void reportQueueStats(long ts, TbRuleEngineConsumerStats stats);
23 } 23 }
@@ -34,7 +34,7 @@ import org.thingsboard.server.common.data.kv.BasicTsKvEntry; @@ -34,7 +34,7 @@ import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
34 import org.thingsboard.server.common.data.kv.ReadTsKvQuery; 34 import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
35 import org.thingsboard.server.common.data.kv.TsKvEntry; 35 import org.thingsboard.server.common.data.kv.TsKvEntry;
36 import org.thingsboard.server.common.msg.queue.ServiceType; 36 import org.thingsboard.server.common.msg.queue.ServiceType;
37 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 37 +import org.thingsboard.server.common.msg.queue.TbCallback;
38 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; 38 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
39 import org.thingsboard.server.dao.attributes.AttributesService; 39 import org.thingsboard.server.dao.attributes.AttributesService;
40 import org.thingsboard.server.dao.timeseries.TimeseriesService; 40 import org.thingsboard.server.dao.timeseries.TimeseriesService;
@@ -123,7 +123,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer @@ -123,7 +123,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer
123 } 123 }
124 124
125 @Override 125 @Override
126 - public void addSubscription(TbSubscription subscription, TbMsgCallback callback) { 126 + public void addSubscription(TbSubscription subscription, TbCallback callback) {
127 log.trace("[{}][{}][{}] Registering remote subscription for entity [{}]", 127 log.trace("[{}][{}][{}] Registering remote subscription for entity [{}]",
128 subscription.getServiceId(), subscription.getSessionId(), subscription.getSubscriptionId(), subscription.getEntityId()); 128 subscription.getServiceId(), subscription.getSessionId(), subscription.getSubscriptionId(), subscription.getEntityId());
129 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, subscription.getTenantId(), subscription.getEntityId()); 129 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, subscription.getTenantId(), subscription.getEntityId());
@@ -151,7 +151,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer @@ -151,7 +151,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer
151 } 151 }
152 152
153 @Override 153 @Override
154 - public void cancelSubscription(String sessionId, int subscriptionId, TbMsgCallback callback) { 154 + public void cancelSubscription(String sessionId, int subscriptionId, TbCallback callback) {
155 log.debug("[{}][{}] Going to remove subscription.", sessionId, subscriptionId); 155 log.debug("[{}][{}] Going to remove subscription.", sessionId, subscriptionId);
156 Map<Integer, TbSubscription> sessionSubscriptions = subscriptionsByWsSessionId.get(sessionId); 156 Map<Integer, TbSubscription> sessionSubscriptions = subscriptionsByWsSessionId.get(sessionId);
157 if (sessionSubscriptions != null) { 157 if (sessionSubscriptions != null) {
@@ -189,7 +189,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer @@ -189,7 +189,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer
189 } 189 }
190 190
191 @Override 191 @Override
192 - public void onTimeSeriesUpdate(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, TbMsgCallback callback) { 192 + public void onTimeSeriesUpdate(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, TbCallback callback) {
193 onLocalSubUpdate(entityId, 193 onLocalSubUpdate(entityId,
194 s -> { 194 s -> {
195 if (TbSubscriptionType.TIMESERIES.equals(s.getType())) { 195 if (TbSubscriptionType.TIMESERIES.equals(s.getType())) {
@@ -213,7 +213,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer @@ -213,7 +213,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer
213 } 213 }
214 214
215 @Override 215 @Override
216 - public void onAttributesUpdate(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, TbMsgCallback callback) { 216 + public void onAttributesUpdate(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, TbCallback callback) {
217 onLocalSubUpdate(entityId, 217 onLocalSubUpdate(entityId,
218 s -> { 218 s -> {
219 if (TbSubscriptionType.ATTRIBUTES.equals(s.getType())) { 219 if (TbSubscriptionType.ATTRIBUTES.equals(s.getType())) {
@@ -261,7 +261,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer @@ -261,7 +261,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer
261 if (subscriptionUpdate != null && !subscriptionUpdate.isEmpty()) { 261 if (subscriptionUpdate != null && !subscriptionUpdate.isEmpty()) {
262 if (serviceId.equals(s.getServiceId())) { 262 if (serviceId.equals(s.getServiceId())) {
263 SubscriptionUpdate update = new SubscriptionUpdate(s.getSubscriptionId(), subscriptionUpdate); 263 SubscriptionUpdate update = new SubscriptionUpdate(s.getSubscriptionId(), subscriptionUpdate);
264 - localSubscriptionService.onSubscriptionUpdate(s.getSessionId(), update, TbMsgCallback.EMPTY); 264 + localSubscriptionService.onSubscriptionUpdate(s.getSessionId(), update, TbCallback.EMPTY);
265 } else { 265 } else {
266 TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, s.getServiceId()); 266 TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, s.getServiceId());
267 toCoreNotificationsProducer.send(tpi, toProto(s, subscriptionUpdate), null); 267 toCoreNotificationsProducer.send(tpi, toProto(s, subscriptionUpdate), null);
@@ -35,7 +35,7 @@ import org.thingsboard.server.queue.discovery.PartitionChangeEvent; @@ -35,7 +35,7 @@ import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
35 import org.thingsboard.server.queue.discovery.PartitionService; 35 import org.thingsboard.server.queue.discovery.PartitionService;
36 import org.thingsboard.server.common.msg.queue.ServiceType; 36 import org.thingsboard.server.common.msg.queue.ServiceType;
37 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; 37 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
38 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 38 +import org.thingsboard.server.common.msg.queue.TbCallback;
39 import org.thingsboard.server.queue.provider.TbQueueProducerProvider; 39 import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
40 import org.thingsboard.server.queue.util.TbCoreComponent; 40 import org.thingsboard.server.queue.util.TbCoreComponent;
41 import org.thingsboard.server.service.telemetry.TelemetryWebSocketService; 41 import org.thingsboard.server.service.telemetry.TelemetryWebSocketService;
@@ -135,7 +135,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer @@ -135,7 +135,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer
135 if (currentPartitions.contains(tpi)) { 135 if (currentPartitions.contains(tpi)) {
136 // Subscription is managed on the same server; 136 // Subscription is managed on the same server;
137 if (pushToLocalService) { 137 if (pushToLocalService) {
138 - subscriptionManagerService.addSubscription(subscription, TbMsgCallback.EMPTY); 138 + subscriptionManagerService.addSubscription(subscription, TbCallback.EMPTY);
139 } 139 }
140 } else { 140 } else {
141 // Push to the queue; 141 // Push to the queue;
@@ -145,7 +145,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer @@ -145,7 +145,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer
145 } 145 }
146 146
147 @Override 147 @Override
148 - public void onSubscriptionUpdate(String sessionId, SubscriptionUpdate update, TbMsgCallback callback) { 148 + public void onSubscriptionUpdate(String sessionId, SubscriptionUpdate update, TbCallback callback) {
149 TbSubscription subscription = subscriptionsBySessionId 149 TbSubscription subscription = subscriptionsBySessionId
150 .getOrDefault(sessionId, Collections.emptyMap()).get(update.getSubscriptionId()); 150 .getOrDefault(sessionId, Collections.emptyMap()).get(update.getSubscriptionId());
151 if (subscription != null) { 151 if (subscription != null) {
@@ -177,7 +177,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer @@ -177,7 +177,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer
177 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, subscription.getTenantId(), subscription.getEntityId()); 177 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, subscription.getTenantId(), subscription.getEntityId());
178 if (currentPartitions.contains(tpi)) { 178 if (currentPartitions.contains(tpi)) {
179 // Subscription is managed on the same server; 179 // Subscription is managed on the same server;
180 - subscriptionManagerService.cancelSubscription(sessionId, subscriptionId, TbMsgCallback.EMPTY); 180 + subscriptionManagerService.cancelSubscription(sessionId, subscriptionId, TbCallback.EMPTY);
181 } else { 181 } else {
182 // Push to the queue; 182 // Push to the queue;
183 TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toCloseSubscriptionProto(subscription); 183 TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toCloseSubscriptionProto(subscription);
@@ -21,18 +21,18 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -21,18 +21,18 @@ import org.thingsboard.server.common.data.id.TenantId;
21 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 21 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
22 import org.thingsboard.server.common.data.kv.TsKvEntry; 22 import org.thingsboard.server.common.data.kv.TsKvEntry;
23 import org.thingsboard.server.queue.discovery.PartitionChangeEvent; 23 import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
24 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 24 +import org.thingsboard.server.common.msg.queue.TbCallback;
25 25
26 import java.util.List; 26 import java.util.List;
27 27
28 public interface SubscriptionManagerService extends ApplicationListener<PartitionChangeEvent> { 28 public interface SubscriptionManagerService extends ApplicationListener<PartitionChangeEvent> {
29 29
30 - void addSubscription(TbSubscription subscription, TbMsgCallback callback); 30 + void addSubscription(TbSubscription subscription, TbCallback callback);
31 31
32 - void cancelSubscription(String sessionId, int subscriptionId, TbMsgCallback callback); 32 + void cancelSubscription(String sessionId, int subscriptionId, TbCallback callback);
33 33
34 - void onTimeSeriesUpdate(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, TbMsgCallback callback); 34 + void onTimeSeriesUpdate(TenantId tenantId, EntityId entityId, List<TsKvEntry> ts, TbCallback callback);
35 35
36 - void onAttributesUpdate(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, TbMsgCallback callback); 36 + void onAttributesUpdate(TenantId tenantId, EntityId entityId, String scope, List<AttributeKvEntry> attributes, TbCallback callback);
37 37
38 } 38 }
@@ -17,7 +17,7 @@ package org.thingsboard.server.service.subscription; @@ -17,7 +17,7 @@ package org.thingsboard.server.service.subscription;
17 17
18 import org.thingsboard.server.queue.discovery.ClusterTopologyChangeEvent; 18 import org.thingsboard.server.queue.discovery.ClusterTopologyChangeEvent;
19 import org.thingsboard.server.queue.discovery.PartitionChangeEvent; 19 import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
20 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 20 +import org.thingsboard.server.common.msg.queue.TbCallback;
21 import org.thingsboard.server.service.telemetry.sub.SubscriptionUpdate; 21 import org.thingsboard.server.service.telemetry.sub.SubscriptionUpdate;
22 22
23 public interface TbLocalSubscriptionService { 23 public interface TbLocalSubscriptionService {
@@ -28,7 +28,7 @@ public interface TbLocalSubscriptionService { @@ -28,7 +28,7 @@ public interface TbLocalSubscriptionService {
28 28
29 void cancelAllSessionSubscriptions(String sessionId); 29 void cancelAllSessionSubscriptions(String sessionId);
30 30
31 - void onSubscriptionUpdate(String sessionId, SubscriptionUpdate update, TbMsgCallback callback); 31 + void onSubscriptionUpdate(String sessionId, SubscriptionUpdate update, TbCallback callback);
32 32
33 void onApplicationEvent(PartitionChangeEvent event); 33 void onApplicationEvent(PartitionChangeEvent event);
34 34
@@ -41,7 +41,7 @@ import org.thingsboard.server.queue.discovery.PartitionChangeEvent; @@ -41,7 +41,7 @@ import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
41 import org.thingsboard.server.queue.discovery.PartitionService; 41 import org.thingsboard.server.queue.discovery.PartitionService;
42 import org.thingsboard.server.common.msg.queue.ServiceType; 42 import org.thingsboard.server.common.msg.queue.ServiceType;
43 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; 43 import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
44 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 44 +import org.thingsboard.server.common.msg.queue.TbCallback;
45 import org.thingsboard.server.queue.provider.TbQueueProducerProvider; 45 import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
46 import org.thingsboard.server.service.subscription.SubscriptionManagerService; 46 import org.thingsboard.server.service.subscription.SubscriptionManagerService;
47 import org.thingsboard.server.service.subscription.TbSubscriptionUtils; 47 import org.thingsboard.server.service.subscription.TbSubscriptionUtils;
@@ -166,7 +166,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio @@ -166,7 +166,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio
166 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId); 166 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId);
167 if (currentPartitions.contains(tpi)) { 167 if (currentPartitions.contains(tpi)) {
168 if (subscriptionManagerService.isPresent()) { 168 if (subscriptionManagerService.isPresent()) {
169 - subscriptionManagerService.get().onAttributesUpdate(tenantId, entityId, scope, attributes, TbMsgCallback.EMPTY); 169 + subscriptionManagerService.get().onAttributesUpdate(tenantId, entityId, scope, attributes, TbCallback.EMPTY);
170 } else { 170 } else {
171 log.warn("Possible misconfiguration because subscriptionManagerService is null!"); 171 log.warn("Possible misconfiguration because subscriptionManagerService is null!");
172 } 172 }
@@ -180,7 +180,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio @@ -180,7 +180,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio
180 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId); 180 TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId);
181 if (currentPartitions.contains(tpi)) { 181 if (currentPartitions.contains(tpi)) {
182 if (subscriptionManagerService.isPresent()) { 182 if (subscriptionManagerService.isPresent()) {
183 - subscriptionManagerService.get().onTimeSeriesUpdate(tenantId, entityId, ts, TbMsgCallback.EMPTY); 183 + subscriptionManagerService.get().onTimeSeriesUpdate(tenantId, entityId, ts, TbCallback.EMPTY);
184 } else { 184 } else {
185 log.warn("Possible misconfiguration because subscriptionManagerService is null!"); 185 log.warn("Possible misconfiguration because subscriptionManagerService is null!");
186 } 186 }
@@ -17,11 +17,7 @@ package org.thingsboard.server.service.telemetry; @@ -17,11 +17,7 @@ package org.thingsboard.server.service.telemetry;
17 17
18 import org.springframework.context.ApplicationListener; 18 import org.springframework.context.ApplicationListener;
19 import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; 19 import org.thingsboard.rule.engine.api.RuleEngineTelemetryService;
20 -import org.thingsboard.server.common.data.id.EntityId;  
21 -import org.thingsboard.server.common.data.id.TenantId;  
22 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
23 import org.thingsboard.server.queue.discovery.PartitionChangeEvent; 20 import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
24 -import org.thingsboard.server.service.telemetry.sub.SubscriptionState;  
25 21
26 /** 22 /**
27 * Created by ashvayka on 27.03.18. 23 * Created by ashvayka on 27.03.18.
1 -/**  
2 - * Copyright © 2016-2020 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.service.telemetry.sub;  
17 -  
18 -import lombok.AllArgsConstructor;  
19 -import lombok.Data;  
20 -import org.thingsboard.server.common.data.id.EntityId;  
21 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
22 -import org.thingsboard.server.service.telemetry.TelemetryFeature;  
23 -  
24 -import java.util.Map;  
25 -  
26 -@Data  
27 -@AllArgsConstructor  
28 -public class Subscription {  
29 -  
30 - private final SubscriptionState sub;  
31 - private final boolean local;  
32 - private ServerAddress server;  
33 - private long startTime;  
34 - private long endTime;  
35 -  
36 - public Subscription(SubscriptionState sub, boolean local, ServerAddress server) {  
37 - this(sub, local, server, 0L, 0L);  
38 - }  
39 -  
40 - public String getWsSessionId() {  
41 - return getSub().getWsSessionId();  
42 - }  
43 -  
44 - public int getSubscriptionId() {  
45 - return getSub().getSubscriptionId();  
46 - }  
47 -  
48 - public EntityId getEntityId() {  
49 - return getSub().getEntityId();  
50 - }  
51 -  
52 - public TelemetryFeature getType() {  
53 - return getSub().getType();  
54 - }  
55 -  
56 - public String getScope() {  
57 - return getSub().getScope();  
58 - }  
59 -  
60 - public boolean isAllKeys() {  
61 - return getSub().isAllKeys();  
62 - }  
63 -  
64 - public Map<String, Long> getKeyStates() {  
65 - return getSub().getKeyStates();  
66 - }  
67 -  
68 - public void setKeyState(String key, long ts) {  
69 - getSub().getKeyStates().put(key, ts);  
70 - }  
71 -  
72 - @Override  
73 - public String toString() {  
74 - return "Subscription{" +  
75 - "sub=" + sub +  
76 - ", local=" + local +  
77 - ", server=" + server +  
78 - '}';  
79 - }  
80 -}  
@@ -22,7 +22,6 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory; @@ -22,7 +22,6 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory;
22 import org.thingsboard.rule.engine.api.RuleChainTransactionService; 22 import org.thingsboard.rule.engine.api.RuleChainTransactionService;
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 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
26 import org.thingsboard.server.queue.util.TbRuleEngineComponent; 25 import org.thingsboard.server.queue.util.TbRuleEngineComponent;
27 import org.thingsboard.server.service.executors.DbCallbackExecutorService; 26 import org.thingsboard.server.service.executors.DbCallbackExecutorService;
28 27
@@ -114,13 +113,6 @@ public class BaseRuleChainTransactionService implements RuleChainTransactionServ @@ -114,13 +113,6 @@ public class BaseRuleChainTransactionService implements RuleChainTransactionServ
114 // } 113 // }
115 } 114 }
116 115
117 - @Override  
118 - public void onRemoteTransactionMsg(ServerAddress serverAddress, byte[] data) {  
119 - endLocalTransaction(TbMsg.fromBytes(data, null), msg -> {  
120 - }, error -> {  
121 - });  
122 - }  
123 -  
124 private void addMsgToQueues(BlockingQueue<TbTransactionTask> queue, TbTransactionTask transactionTask) { 116 private void addMsgToQueues(BlockingQueue<TbTransactionTask> queue, TbTransactionTask transactionTask) {
125 queue.offer(transactionTask); 117 queue.offer(transactionTask);
126 timeoutQueue.offer(transactionTask); 118 timeoutQueue.offer(transactionTask);
@@ -230,9 +222,4 @@ public class BaseRuleChainTransactionService implements RuleChainTransactionServ @@ -230,9 +222,4 @@ public class BaseRuleChainTransactionService implements RuleChainTransactionServ
230 callbackExecutor.executeAsync(task); 222 callbackExecutor.executeAsync(task);
231 } 223 }
232 224
233 - private void sendTransactionEventToRemoteServer(TbMsg msg, ServerAddress address) {  
234 - log.trace("[{}][{}] Originator is monitored on other server: {}", msg.getTransactionData().getOriginatorId(), msg.getTransactionData().getTransactionId(), address);  
235 - //TODO 2.5  
236 -// clusterRpcService.tell(address, ClusterAPIProtos.MessageType.CLUSTER_TRANSACTION_SERVICE_MESSAGE, TbMsg.toByteArray(msg));  
237 - }  
238 } 225 }
@@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.TbActorMsg; @@ -23,7 +23,7 @@ import org.thingsboard.server.common.msg.TbActorMsg;
23 import org.thingsboard.server.common.msg.aware.DeviceAwareMsg; 23 import org.thingsboard.server.common.msg.aware.DeviceAwareMsg;
24 import org.thingsboard.server.common.msg.aware.TenantAwareMsg; 24 import org.thingsboard.server.common.msg.aware.TenantAwareMsg;
25 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; 25 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
26 -import org.thingsboard.server.common.msg.queue.TbMsgCallback; 26 +import org.thingsboard.server.common.msg.queue.TbCallback;
27 27
28 import java.io.Serializable; 28 import java.io.Serializable;
29 import java.util.UUID; 29 import java.util.UUID;
@@ -37,9 +37,9 @@ public class TransportToDeviceActorMsgWrapper implements TbActorMsg, DeviceAware @@ -37,9 +37,9 @@ public class TransportToDeviceActorMsgWrapper implements TbActorMsg, DeviceAware
37 private final TenantId tenantId; 37 private final TenantId tenantId;
38 private final DeviceId deviceId; 38 private final DeviceId deviceId;
39 private final TransportToDeviceActorMsg msg; 39 private final TransportToDeviceActorMsg msg;
40 - private final TbMsgCallback callback; 40 + private final TbCallback callback;
41 41
42 - public TransportToDeviceActorMsgWrapper(TransportToDeviceActorMsg msg, TbMsgCallback callback) { 42 + public TransportToDeviceActorMsgWrapper(TransportToDeviceActorMsg msg, TbCallback callback) {
43 this.msg = msg; 43 this.msg = msg;
44 this.callback = callback; 44 this.callback = callback;
45 this.tenantId = new TenantId(new UUID(msg.getSessionInfo().getTenantIdMSB(), msg.getSessionInfo().getTenantIdLSB())); 45 this.tenantId = new TenantId(new UUID(msg.getSessionInfo().getTenantIdMSB(), msg.getSessionInfo().getTenantIdLSB()));
@@ -27,8 +27,8 @@ @@ -27,8 +27,8 @@
27 27
28 <logger name="org.thingsboard.server" level="INFO" /> 28 <logger name="org.thingsboard.server" level="INFO" />
29 <logger name="akka" level="INFO" /> 29 <logger name="akka" level="INFO" />
30 - <logger name="org.thingsboard.server.service.queue" level="TRACE" />  
31 - <logger name="org.thingsboard.server.service.transport" level="TRACE" /> 30 +<!-- <logger name="org.thingsboard.server.service.queue" level="TRACE" />-->
  31 +<!-- <logger name="org.thingsboard.server.service.transport" level="TRACE" />-->
32 32
33 <root level="INFO"> 33 <root level="INFO">
34 <appender-ref ref="STDOUT"/> 34 <appender-ref ref="STDOUT"/>
@@ -561,7 +561,7 @@ queue: @@ -561,7 +561,7 @@ queue:
561 poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}" 561 poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}"
562 pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" 562 pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}"
563 stats: 563 stats:
564 - enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:false}" 564 + enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}"
565 print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}" 565 print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}"
566 queues: # TODO 2.5: specify correct ENV variable names. 566 queues: # TODO 2.5: specify correct ENV variable names.
567 - 567 -
@@ -577,7 +577,7 @@ queue: @@ -577,7 +577,7 @@ queue:
577 failure-percentage: "${TB_QUEUE_RULE_ENGINE_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages; 577 failure-percentage: "${TB_QUEUE_RULE_ENGINE_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages;
578 pause-between-retries: "${TB_QUEUE_RULE_ENGINE_STRATEGY_RETRY_PAUSE:3}"# Time in seconds to wait in consumer thread before retries; 578 pause-between-retries: "${TB_QUEUE_RULE_ENGINE_STRATEGY_RETRY_PAUSE:3}"# Time in seconds to wait in consumer thread before retries;
579 - 579 -
580 - name: "HighPriority" 580 + name: "${TB_QUEUE_RULE_ENGINE_HP_QUEUE_NAME:HighPriority}"
581 topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb.rule-engine.hp}" 581 topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb.rule-engine.hp}"
582 poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}" 582 poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}"
583 partitions: "${TB_QUEUE_RULE_ENGINE_PARTITIONS:3}" 583 partitions: "${TB_QUEUE_RULE_ENGINE_PARTITIONS:3}"
@@ -594,7 +594,7 @@ queue: @@ -594,7 +594,7 @@ queue:
594 poll_interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" 594 poll_interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}"
595 595
596 service: 596 service:
597 - type: "${TB_SERVICE_TYPE:monolith}" # monolith or tb-core or tb-rule-engine or tb-transport 597 + type: "${TB_SERVICE_TYPE:monolith}" # monolith or tb-core or tb-rule-engine
598 # Unique id for this service (autogenerated if empty) 598 # Unique id for this service (autogenerated if empty)
599 id: "${TB_SERVICE_ID:}" 599 id: "${TB_SERVICE_ID:}"
600 tenant_id: "${TB_SERVICE_TENANT_ID:}" # empty or specific tenant id. 600 tenant_id: "${TB_SERVICE_TENANT_ID:}" # empty or specific tenant id.
@@ -35,8 +35,6 @@ import org.thingsboard.server.common.data.security.Authority; @@ -35,8 +35,6 @@ import org.thingsboard.server.common.data.security.Authority;
35 import org.thingsboard.server.common.msg.TbMsg; 35 import org.thingsboard.server.common.msg.TbMsg;
36 import org.thingsboard.server.common.msg.TbMsgDataType; 36 import org.thingsboard.server.common.msg.TbMsgDataType;
37 import org.thingsboard.server.common.msg.TbMsgMetaData; 37 import org.thingsboard.server.common.msg.TbMsgMetaData;
38 -import org.thingsboard.server.common.msg.cluster.SendToClusterMsg;  
39 -import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;  
40 import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; 38 import org.thingsboard.server.controller.AbstractRuleEngineControllerTest;
41 import org.thingsboard.server.dao.attributes.AttributesService; 39 import org.thingsboard.server.dao.attributes.AttributesService;
42 40
@@ -39,8 +39,6 @@ import org.thingsboard.server.common.data.security.Authority; @@ -39,8 +39,6 @@ import org.thingsboard.server.common.data.security.Authority;
39 import org.thingsboard.server.common.msg.TbMsg; 39 import org.thingsboard.server.common.msg.TbMsg;
40 import org.thingsboard.server.common.msg.TbMsgDataType; 40 import org.thingsboard.server.common.msg.TbMsgDataType;
41 import org.thingsboard.server.common.msg.TbMsgMetaData; 41 import org.thingsboard.server.common.msg.TbMsgMetaData;
42 -import org.thingsboard.server.common.msg.cluster.SendToClusterMsg;  
43 -import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;  
44 import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; 42 import org.thingsboard.server.controller.AbstractRuleEngineControllerTest;
45 import org.thingsboard.server.dao.attributes.AttributesService; 43 import org.thingsboard.server.dao.attributes.AttributesService;
46 44
@@ -34,11 +34,6 @@ public enum MsgType { @@ -34,11 +34,6 @@ public enum MsgType {
34 APP_INIT_MSG, 34 APP_INIT_MSG,
35 35
36 /** 36 /**
37 - * All messages, could be send to cluster  
38 - */  
39 - SEND_TO_CLUSTER_MSG,  
40 -  
41 - /**  
42 * ADDED/UPDATED/DELETED events for main entities. 37 * ADDED/UPDATED/DELETED events for main entities.
43 * 38 *
44 * See {@link org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg} 39 * See {@link org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg}
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
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 * 7 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 + * http://www.apache.org/licenses/LICENSE-2.0
9 * 9 *
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,
@@ -17,7 +17,6 @@ package org.thingsboard.server.common.msg; @@ -17,7 +17,6 @@ package org.thingsboard.server.common.msg;
17 17
18 import com.google.protobuf.ByteString; 18 import com.google.protobuf.ByteString;
19 import com.google.protobuf.InvalidProtocolBufferException; 19 import com.google.protobuf.InvalidProtocolBufferException;
20 -import lombok.AllArgsConstructor;  
21 import lombok.Builder; 20 import lombok.Builder;
22 import lombok.Data; 21 import lombok.Data;
23 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
@@ -29,7 +28,6 @@ import org.thingsboard.server.common.msg.gen.MsgProtos; @@ -29,7 +28,6 @@ import org.thingsboard.server.common.msg.gen.MsgProtos;
29 import org.thingsboard.server.common.msg.queue.TbMsgCallback; 28 import org.thingsboard.server.common.msg.queue.TbMsgCallback;
30 29
31 import java.io.Serializable; 30 import java.io.Serializable;
32 -import java.nio.ByteBuffer;  
33 import java.util.UUID; 31 import java.util.UUID;
34 32
35 /** 33 /**
@@ -33,6 +33,7 @@ public final class QueueToRuleEngineMsg implements TbActorMsg { @@ -33,6 +33,7 @@ public final class QueueToRuleEngineMsg implements TbActorMsg {
33 private final TenantId tenantId; 33 private final TenantId tenantId;
34 private final TbMsg tbMsg; 34 private final TbMsg tbMsg;
35 private final Set<String> relationTypes; 35 private final Set<String> relationTypes;
  36 + private final String failureMessage;
36 37
37 @Override 38 @Override
38 public MsgType getMsgType() { 39 public MsgType getMsgType() {
common/message/src/main/java/org/thingsboard/server/common/msg/queue/RuleEngineException.java renamed from common/message/src/main/java/org/thingsboard/server/common/msg/cluster/ServerAddress.java
@@ -13,35 +13,26 @@ @@ -13,35 +13,26 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.msg.cluster; 16 +package org.thingsboard.server.common.msg.queue;
17 17
18 -import lombok.Data;  
19 -import lombok.EqualsAndHashCode; 18 +import com.fasterxml.jackson.core.JsonProcessingException;
  19 +import com.fasterxml.jackson.databind.ObjectMapper;
  20 +import lombok.extern.slf4j.Slf4j;
20 21
21 -import java.io.Serializable; 22 +@Slf4j
  23 +public class RuleEngineException extends Exception {
  24 + protected static final ObjectMapper mapper = new ObjectMapper();
22 25
23 -/**  
24 - * @author Andrew Shvayka  
25 - */  
26 -@Data  
27 -@EqualsAndHashCode  
28 -public class ServerAddress implements Comparable<ServerAddress>, Serializable {  
29 -  
30 - private final String host;  
31 - private final int port;  
32 - private final ServerType serverType;  
33 -  
34 - @Override  
35 - public int compareTo(ServerAddress o) {  
36 - int result = this.host.compareTo(o.host);  
37 - if (result == 0) {  
38 - result = this.port - o.port;  
39 - }  
40 - return result; 26 + public RuleEngineException(String message) {
  27 + super(message != null ? message : "Unknown");
41 } 28 }
42 29
43 - @Override  
44 - public String toString() {  
45 - return '[' + host + ':' + port + ']'; 30 + public String toJsonString() {
  31 + try {
  32 + return mapper.writeValueAsString(mapper.createObjectNode().put("message", getMessage()));
  33 + } catch (JsonProcessingException e) {
  34 + log.warn("Failed to serialize exception ", e);
  35 + throw new RuntimeException(e);
  36 + }
46 } 37 }
47 } 38 }
  1 +/**
  2 + * Copyright © 2016-2020 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.queue;
  17 +
  18 +import com.fasterxml.jackson.core.JsonProcessingException;
  19 +import lombok.Getter;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +import org.thingsboard.server.common.data.id.RuleChainId;
  22 +import org.thingsboard.server.common.data.id.RuleNodeId;
  23 +import org.thingsboard.server.common.data.rule.RuleNode;
  24 +
  25 +@Slf4j
  26 +public class RuleNodeException extends RuleEngineException {
  27 + @Getter
  28 + private final String ruleChainName;
  29 + @Getter
  30 + private final String ruleNodeName;
  31 + @Getter
  32 + private final RuleChainId ruleChainId;
  33 + @Getter
  34 + private final RuleNodeId ruleNodeId;
  35 +
  36 + public RuleNodeException(String message, String ruleChainName, RuleNode ruleNode) {
  37 + super(message);
  38 + this.ruleChainName = ruleChainName;
  39 + this.ruleNodeName = ruleNode.getName();
  40 + this.ruleChainId = ruleNode.getRuleChainId();
  41 + this.ruleNodeId = ruleNode.getId();
  42 + }
  43 +
  44 + public String toJsonString() {
  45 + try {
  46 + return mapper.writeValueAsString(mapper.createObjectNode()
  47 + .put("ruleNodeId", ruleNodeId.toString())
  48 + .put("ruleChainId", ruleChainId.toString())
  49 + .put("ruleNodeName", ruleNodeName)
  50 + .put("ruleChainName", ruleChainName)
  51 + .put("message", getMessage()));
  52 + } catch (JsonProcessingException e) {
  53 + log.warn("Failed to serialize exception ", e);
  54 + throw new RuntimeException(e);
  55 + }
  56 + }
  57 +
  58 +}
common/message/src/main/java/org/thingsboard/server/common/msg/queue/TbCallback.java renamed from application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java
@@ -13,36 +13,25 @@ @@ -13,36 +13,25 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.actors.shared.rulechain;  
17 -  
18 -import org.thingsboard.server.actors.ActorSystemContext;  
19 -import org.thingsboard.server.actors.service.DefaultActorService;  
20 -import org.thingsboard.server.common.data.id.TenantId;  
21 -import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction;  
22 -import org.thingsboard.server.common.data.page.TextPageData;  
23 -import org.thingsboard.server.common.data.rule.RuleChain;  
24 -import org.thingsboard.server.dao.model.ModelConstants;  
25 -  
26 -import java.util.Collections;  
27 -  
28 -public class SystemRuleChainManager extends RuleChainManager {  
29 -  
30 - public SystemRuleChainManager(ActorSystemContext systemContext) {  
31 - super(systemContext);  
32 - }  
33 -  
34 - @Override  
35 - protected FetchFunction<RuleChain> getFetchEntitiesFunction() {  
36 - return link -> new TextPageData<>(Collections.emptyList(), link);  
37 - }  
38 -  
39 - @Override  
40 - protected TenantId getTenantId() {  
41 - return ModelConstants.SYSTEM_TENANT;  
42 - }  
43 -  
44 - @Override  
45 - protected String getDispatcherName() {  
46 - return DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME;  
47 - } 16 +package org.thingsboard.server.common.msg.queue;
  17 +
  18 +public interface TbCallback {
  19 +
  20 + TbCallback EMPTY = new TbCallback() {
  21 +
  22 + @Override
  23 + public void onSuccess() {
  24 +
  25 + }
  26 +
  27 + @Override
  28 + public void onFailure(Throwable t) {
  29 +
  30 + }
  31 + };
  32 +
  33 + void onSuccess();
  34 +
  35 + void onFailure(Throwable t);
  36 +
48 } 37 }
@@ -25,13 +25,13 @@ public interface TbMsgCallback { @@ -25,13 +25,13 @@ public interface TbMsgCallback {
25 } 25 }
26 26
27 @Override 27 @Override
28 - public void onFailure(Throwable t) { 28 + public void onFailure(RuleEngineException e) {
29 29
30 } 30 }
31 }; 31 };
32 32
33 void onSuccess(); 33 void onSuccess();
34 34
35 - void onFailure(Throwable t); 35 + void onFailure(RuleEngineException e);
36 36
37 } 37 }
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.queue.common; 16 package org.thingsboard.server.queue.common;
17 17
  18 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  19 +import org.thingsboard.server.common.msg.queue.TbCallback;
18 import org.thingsboard.server.common.msg.queue.TbMsgCallback; 20 import org.thingsboard.server.common.msg.queue.TbMsgCallback;
19 import org.thingsboard.server.queue.TbQueueCallback; 21 import org.thingsboard.server.queue.TbQueueCallback;
20 import org.thingsboard.server.queue.TbQueueMsgMetadata; 22 import org.thingsboard.server.queue.TbQueueMsgMetadata;
@@ -40,6 +42,6 @@ public class MultipleTbQueueTbMsgCallbackWrapper implements TbQueueCallback { @@ -40,6 +42,6 @@ public class MultipleTbQueueTbMsgCallbackWrapper implements TbQueueCallback {
40 42
41 @Override 43 @Override
42 public void onFailure(Throwable t) { 44 public void onFailure(Throwable t) {
43 - tbMsgCallback.onFailure(t); 45 + tbMsgCallback.onFailure(new RuleEngineException(t.getMessage()));
44 } 46 }
45 } 47 }
@@ -15,12 +15,12 @@ @@ -15,12 +15,12 @@
15 */ 15 */
16 package org.thingsboard.server.queue.common; 16 package org.thingsboard.server.queue.common;
17 17
  18 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  19 +import org.thingsboard.server.common.msg.queue.TbCallback;
18 import org.thingsboard.server.common.msg.queue.TbMsgCallback; 20 import org.thingsboard.server.common.msg.queue.TbMsgCallback;
19 import org.thingsboard.server.queue.TbQueueCallback; 21 import org.thingsboard.server.queue.TbQueueCallback;
20 import org.thingsboard.server.queue.TbQueueMsgMetadata; 22 import org.thingsboard.server.queue.TbQueueMsgMetadata;
21 23
22 -import java.util.concurrent.atomic.AtomicInteger;  
23 -  
24 public class TbQueueTbMsgCallbackWrapper implements TbQueueCallback { 24 public class TbQueueTbMsgCallbackWrapper implements TbQueueCallback {
25 25
26 private final TbMsgCallback tbMsgCallback; 26 private final TbMsgCallback tbMsgCallback;
@@ -36,6 +36,6 @@ public class TbQueueTbMsgCallbackWrapper implements TbQueueCallback { @@ -36,6 +36,6 @@ public class TbQueueTbMsgCallbackWrapper implements TbQueueCallback {
36 36
37 @Override 37 @Override
38 public void onFailure(Throwable t) { 38 public void onFailure(Throwable t) {
39 - tbMsgCallback.onFailure(t); 39 + tbMsgCallback.onFailure(new RuleEngineException(t.getMessage()));
40 } 40 }
41 } 41 }
@@ -86,24 +86,6 @@ public class ConsistentHashPartitionService implements PartitionService { @@ -86,24 +86,6 @@ public class ConsistentHashPartitionService implements PartitionService {
86 partitionTopics.put(new ServiceQueue(ServiceType.TB_CORE), coreTopic); 86 partitionTopics.put(new ServiceQueue(ServiceType.TB_CORE), coreTopic);
87 } 87 }
88 88
89 -// public Set<TopicPartitionInfo> getCurrentPartitions(ServiceType serviceType) {  
90 -// ServiceInfo currentService = serviceInfoProvider.getServiceInfo();  
91 -// TenantId tenantId = getSystemOrIsolatedTenantId(currentService);  
92 -// ServiceQueueKey serviceQueueKey = new ServiceQueueKey(serviceType, tenantId);  
93 -// List<Integer> partitions = myPartitions.get(serviceQueueKey);  
94 -// Set<TopicPartitionInfo> topicPartitions = new LinkedHashSet<>();  
95 -// for (Integer partition : partitions) {  
96 -// TopicPartitionInfo.TopicPartitionInfoBuilder tpi = TopicPartitionInfo.builder();  
97 -// tpi.topic(partitionTopics.get(serviceType));  
98 -// tpi.partition(partition);  
99 -// if (!tenantId.isNullUid()) {  
100 -// tpi.tenantId(tenantId);  
101 -// }  
102 -// topicPartitions.add(tpi.build());  
103 -// }  
104 -// return topicPartitions;  
105 -// }  
106 -  
107 @Override 89 @Override
108 public TopicPartitionInfo resolve(ServiceType serviceType, TenantId tenantId, EntityId entityId) { 90 public TopicPartitionInfo resolve(ServiceType serviceType, TenantId tenantId, EntityId entityId) {
109 return resolve(new ServiceQueue(serviceType), tenantId, entityId); 91 return resolve(new ServiceQueue(serviceType), tenantId, entityId);
@@ -131,15 +113,7 @@ public class ConsistentHashPartitionService implements PartitionService { @@ -131,15 +113,7 @@ public class ConsistentHashPartitionService implements PartitionService {
131 Map<ServiceQueueKey, ConsistentHashCircle<ServiceInfo>> circles = new HashMap<>(); 113 Map<ServiceQueueKey, ConsistentHashCircle<ServiceInfo>> circles = new HashMap<>();
132 addNode(circles, currentService); 114 addNode(circles, currentService);
133 for (ServiceInfo other : otherServices) { 115 for (ServiceInfo other : otherServices) {
134 - TenantId tenantId = getSystemOrIsolatedTenantId(other);  
135 addNode(circles, other); 116 addNode(circles, other);
136 - if (!tenantId.isNullUid()) {  
137 - isolatedTenants.putIfAbsent(tenantId, new HashSet<>());  
138 - for (String serviceType : other.getServiceTypesList()) {  
139 - isolatedTenants.get(tenantId).add(ServiceType.valueOf(serviceType.toUpperCase()));  
140 - }  
141 -  
142 - }  
143 } 117 }
144 ConcurrentMap<ServiceQueueKey, List<Integer>> oldPartitions = myPartitions; 118 ConcurrentMap<ServiceQueueKey, List<Integer>> oldPartitions = myPartitions;
145 TenantId myTenantId = getSystemOrIsolatedTenantId(currentService); 119 TenantId myTenantId = getSystemOrIsolatedTenantId(currentService);
@@ -214,6 +188,11 @@ public class ConsistentHashPartitionService implements PartitionService { @@ -214,6 +188,11 @@ public class ConsistentHashPartitionService implements PartitionService {
214 } 188 }
215 } 189 }
216 190
  191 + @Override
  192 + public Set<TenantId> getIsolatedTenants(ServiceType serviceType) {
  193 + throw new RuntimeException("Not Implemented!");
  194 + }
  195 +
217 private Map<ServiceQueueKey, List<ServiceInfo>> getServiceKeyListMap(List<ServiceInfo> services) { 196 private Map<ServiceQueueKey, List<ServiceInfo>> getServiceKeyListMap(List<ServiceInfo> services) {
218 final Map<ServiceQueueKey, List<ServiceInfo>> currentMap = new HashMap<>(); 197 final Map<ServiceQueueKey, List<ServiceInfo>> currentMap = new HashMap<>();
219 services.forEach(serviceInfo -> { 198 services.forEach(serviceInfo -> {
@@ -280,6 +259,12 @@ public class ConsistentHashPartitionService implements PartitionService { @@ -280,6 +259,12 @@ public class ConsistentHashPartitionService implements PartitionService {
280 259
281 private void addNode(Map<ServiceQueueKey, ConsistentHashCircle<ServiceInfo>> circles, ServiceInfo instance) { 260 private void addNode(Map<ServiceQueueKey, ConsistentHashCircle<ServiceInfo>> circles, ServiceInfo instance) {
282 TenantId tenantId = getSystemOrIsolatedTenantId(instance); 261 TenantId tenantId = getSystemOrIsolatedTenantId(instance);
  262 + if (!tenantId.isNullUid()) {
  263 + isolatedTenants.putIfAbsent(tenantId, new HashSet<>());
  264 + for (String serviceType : instance.getServiceTypesList()) {
  265 + isolatedTenants.get(tenantId).add(ServiceType.valueOf(serviceType.toUpperCase()));
  266 + }
  267 + }
283 for (String serviceTypeStr : instance.getServiceTypesList()) { 268 for (String serviceTypeStr : instance.getServiceTypesList()) {
284 ServiceType serviceType = ServiceType.valueOf(serviceTypeStr.toUpperCase()); 269 ServiceType serviceType = ServiceType.valueOf(serviceTypeStr.toUpperCase());
285 if (ServiceType.TB_RULE_ENGINE.equals(serviceType)) { 270 if (ServiceType.TB_RULE_ENGINE.equals(serviceType)) {
@@ -34,6 +34,7 @@ import java.net.UnknownHostException; @@ -34,6 +34,7 @@ import java.net.UnknownHostException;
34 import java.util.Arrays; 34 import java.util.Arrays;
35 import java.util.Collections; 35 import java.util.Collections;
36 import java.util.List; 36 import java.util.List;
  37 +import java.util.Optional;
37 import java.util.UUID; 38 import java.util.UUID;
38 import java.util.stream.Collectors; 39 import java.util.stream.Collectors;
39 40
@@ -58,6 +59,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { @@ -58,6 +59,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider {
58 59
59 private List<ServiceType> serviceTypes; 60 private List<ServiceType> serviceTypes;
60 private ServiceInfo serviceInfo; 61 private ServiceInfo serviceInfo;
  62 + private TenantId isolatedTenant;
61 63
62 @PostConstruct 64 @PostConstruct
63 public void init() { 65 public void init() {
@@ -80,6 +82,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { @@ -80,6 +82,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider {
80 UUID tenantId; 82 UUID tenantId;
81 if (!StringUtils.isEmpty(tenantIdStr)) { 83 if (!StringUtils.isEmpty(tenantIdStr)) {
82 tenantId = UUID.fromString(tenantIdStr); 84 tenantId = UUID.fromString(tenantIdStr);
  85 + isolatedTenant = new TenantId(tenantId);
83 } else { 86 } else {
84 tenantId = TenantId.NULL_UUID; 87 tenantId = TenantId.NULL_UUID;
85 } 88 }
@@ -103,4 +106,14 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { @@ -103,4 +106,14 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider {
103 public ServiceInfo getServiceInfo() { 106 public ServiceInfo getServiceInfo() {
104 return serviceInfo; 107 return serviceInfo;
105 } 108 }
  109 +
  110 + @Override
  111 + public boolean isService(ServiceType serviceType) {
  112 + return serviceTypes.contains(serviceType);
  113 + }
  114 +
  115 + @Override
  116 + public Optional<TenantId> getIsolatedTenant() {
  117 + return Optional.ofNullable(isolatedTenant);
  118 + }
106 } 119 }
@@ -47,6 +47,8 @@ public interface PartitionService { @@ -47,6 +47,8 @@ public interface PartitionService {
47 */ 47 */
48 Set<String> getAllServiceIds(ServiceType serviceType); 48 Set<String> getAllServiceIds(ServiceType serviceType);
49 49
  50 + Set<TenantId> getIsolatedTenants(ServiceType serviceType);
  51 +
50 /** 52 /**
51 * Each Service should start a consumer for messages that target individual service instance based on serviceId. 53 * Each Service should start a consumer for messages that target individual service instance based on serviceId.
52 * This topic is likely to have single partition, and is always assigned to the service. 54 * This topic is likely to have single partition, and is always assigned to the service.
@@ -15,12 +15,20 @@ @@ -15,12 +15,20 @@
15 */ 15 */
16 package org.thingsboard.server.queue.discovery; 16 package org.thingsboard.server.queue.discovery;
17 17
  18 +import org.thingsboard.server.common.data.id.TenantId;
  19 +import org.thingsboard.server.common.msg.queue.ServiceType;
18 import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; 20 import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo;
19 21
  22 +import java.util.Optional;
  23 +
20 public interface TbServiceInfoProvider { 24 public interface TbServiceInfoProvider {
21 25
22 String getServiceId(); 26 String getServiceId();
23 27
24 ServiceInfo getServiceInfo(); 28 ServiceInfo getServiceInfo();
25 29
  30 + boolean isService(ServiceType serviceType);
  31 +
  32 + Optional<TenantId> getIsolatedTenant();
  33 +
26 } 34 }
@@ -17,7 +17,9 @@ package org.thingsboard.server.queue.settings; @@ -17,7 +17,9 @@ package org.thingsboard.server.queue.settings;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
  20 +import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.beans.factory.annotation.Value; 21 import org.springframework.beans.factory.annotation.Value;
  22 +import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
21 import org.springframework.boot.context.properties.ConfigurationProperties; 23 import org.springframework.boot.context.properties.ConfigurationProperties;
22 import org.springframework.context.annotation.Configuration; 24 import org.springframework.context.annotation.Configuration;
23 25
@@ -26,6 +28,7 @@ import java.util.List; @@ -26,6 +28,7 @@ import java.util.List;
26 28
27 @Slf4j 29 @Slf4j
28 @Data 30 @Data
  31 +@EnableAutoConfiguration
29 @Configuration 32 @Configuration
30 @ConfigurationProperties(prefix = "queue.rule-engine") 33 @ConfigurationProperties(prefix = "queue.rule-engine")
31 public class TbQueueRuleEngineSettings { 34 public class TbQueueRuleEngineSettings {
@@ -388,6 +388,7 @@ message ToRuleEngineMsg { @@ -388,6 +388,7 @@ message ToRuleEngineMsg {
388 int64 tenantIdLSB = 2; 388 int64 tenantIdLSB = 2;
389 bytes tbMsg = 3; 389 bytes tbMsg = 3;
390 repeated string relationTypes = 4; 390 repeated string relationTypes = 4;
  391 + string failureMessage = 5;
391 } 392 }
392 393
393 message ToRuleEngineNotificationMsg { 394 message ToRuleEngineNotificationMsg {
@@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
16 package org.thingsboard.rule.engine.api; 16 package org.thingsboard.rule.engine.api;
17 17
18 import org.thingsboard.server.common.msg.TbMsg; 18 import org.thingsboard.server.common.msg.TbMsg;
19 -import org.thingsboard.server.common.msg.cluster.ServerAddress;  
20 19
21 import java.util.function.Consumer; 20 import java.util.function.Consumer;
22 21
@@ -26,6 +25,4 @@ public interface RuleChainTransactionService { @@ -26,6 +25,4 @@ public interface RuleChainTransactionService {
26 25
27 void endTransaction(TbMsg msg, Consumer<TbMsg> onSuccess, Consumer<Throwable> onFailure); 26 void endTransaction(TbMsg msg, Consumer<TbMsg> onSuccess, Consumer<Throwable> onFailure);
28 27
29 - void onRemoteTransactionMsg(ServerAddress serverAddress, byte[] bytes);  
30 -  
31 } 28 }
@@ -26,10 +26,8 @@ import org.thingsboard.server.common.data.asset.Asset; @@ -26,10 +26,8 @@ import org.thingsboard.server.common.data.asset.Asset;
26 import org.thingsboard.server.common.data.id.EntityId; 26 import org.thingsboard.server.common.data.id.EntityId;
27 import org.thingsboard.server.common.data.id.RuleNodeId; 27 import org.thingsboard.server.common.data.id.RuleNodeId;
28 import org.thingsboard.server.common.data.id.TenantId; 28 import org.thingsboard.server.common.data.id.TenantId;
29 -import org.thingsboard.server.common.data.rule.RuleNode;  
30 import org.thingsboard.server.common.msg.TbMsg; 29 import org.thingsboard.server.common.msg.TbMsg;
31 import org.thingsboard.server.common.msg.TbMsgMetaData; 30 import org.thingsboard.server.common.msg.TbMsgMetaData;
32 -import org.thingsboard.server.common.msg.queue.TbMsgCallback;  
33 import org.thingsboard.server.dao.alarm.AlarmService; 31 import org.thingsboard.server.dao.alarm.AlarmService;
34 import org.thingsboard.server.dao.asset.AssetService; 32 import org.thingsboard.server.dao.asset.AssetService;
35 import org.thingsboard.server.dao.attributes.AttributesService; 33 import org.thingsboard.server.dao.attributes.AttributesService;
@@ -116,6 +114,8 @@ public interface TbContext { @@ -116,6 +114,8 @@ public interface TbContext {
116 */ 114 */
117 void enqueue(TbMsg msg, String queueName, Runnable onSuccess, Consumer<Throwable> onFailure); 115 void enqueue(TbMsg msg, String queueName, Runnable onSuccess, Consumer<Throwable> onFailure);
118 116
  117 + void enqueueForTellFailure(TbMsg msg, String failureMessage);
  118 +
119 void enqueueForTellNext(TbMsg msg, String relationType); 119 void enqueueForTellNext(TbMsg msg, String relationType);
120 120
121 void enqueueForTellNext(TbMsg msg, Set<String> relationTypes); 121 void enqueueForTellNext(TbMsg msg, Set<String> relationTypes);
  1 +/**
  2 + * Copyright © 2016-2020 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.rule.engine.flow;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.thingsboard.rule.engine.api.EmptyNodeConfiguration;
  20 +import org.thingsboard.rule.engine.api.RuleNode;
  21 +import org.thingsboard.rule.engine.api.TbContext;
  22 +import org.thingsboard.rule.engine.api.TbNode;
  23 +import org.thingsboard.rule.engine.api.TbNodeConfiguration;
  24 +import org.thingsboard.rule.engine.api.TbNodeException;
  25 +import org.thingsboard.rule.engine.api.TbRelationTypes;
  26 +import org.thingsboard.rule.engine.api.util.TbNodeUtils;
  27 +import org.thingsboard.server.common.data.plugin.ComponentType;
  28 +import org.thingsboard.server.common.msg.TbMsg;
  29 +
  30 +@Slf4j
  31 +@RuleNode(
  32 + type = ComponentType.ACTION,
  33 + name = "acknowledge",
  34 + configClazz = EmptyNodeConfiguration.class,
  35 + nodeDescription = "Acknowledges the incoming message",
  36 + nodeDetails = "After acknowledgement, the message is pushed to related rule nodes. Useful if you don't care what happens to this message next.")
  37 +
  38 +public class TbAckNode implements TbNode {
  39 +
  40 + @Override
  41 + public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
  42 + }
  43 +
  44 + @Override
  45 + public void onMsg(TbContext ctx, TbMsg msg) {
  46 + ctx.ack(msg);
  47 + ctx.tellSuccess(msg);
  48 + }
  49 +
  50 + @Override
  51 + public void destroy() {
  52 + }
  53 +}
  1 +/**
  2 + * Copyright © 2016-2020 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.rule.engine.flow;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.thingsboard.rule.engine.api.RuleNode;
  20 +import org.thingsboard.rule.engine.api.ScriptEngine;
  21 +import org.thingsboard.rule.engine.api.TbContext;
  22 +import org.thingsboard.rule.engine.api.TbNode;
  23 +import org.thingsboard.rule.engine.api.TbNodeConfiguration;
  24 +import org.thingsboard.rule.engine.api.TbNodeException;
  25 +import org.thingsboard.rule.engine.api.TbRelationTypes;
  26 +import org.thingsboard.rule.engine.api.util.TbNodeUtils;
  27 +import org.thingsboard.server.common.data.plugin.ComponentType;
  28 +import org.thingsboard.server.common.msg.TbMsg;
  29 +
  30 +import static org.thingsboard.common.util.DonAsynchron.withCallback;
  31 +
  32 +@Slf4j
  33 +@RuleNode(
  34 + type = ComponentType.ACTION,
  35 + name = "checkpoint",
  36 + configClazz = TbCheckpointNodeConfiguration.class,
  37 + nodeDescription = "transfers the message to another queue",
  38 + nodeDetails = "After successful transfer incoming message is automatically acknowledged. Queue name is configurable.")
  39 +
  40 +public class TbCheckpointNode implements TbNode {
  41 +
  42 + private TbCheckpointNodeConfiguration config;
  43 +
  44 + @Override
  45 + public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
  46 + this.config = TbNodeUtils.convert(configuration, TbCheckpointNodeConfiguration.class);
  47 + }
  48 +
  49 + @Override
  50 + public void onMsg(TbContext ctx, TbMsg msg) {
  51 + ctx.enqueueForTellNext(msg, config.getQueueName(), TbRelationTypes.SUCCESS, () -> ctx.ack(msg), error -> ctx.tellFailure(msg, error));
  52 + }
  53 +
  54 + @Override
  55 + public void destroy() {
  56 + }
  57 +}
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeConfiguration.java renamed from common/message/src/main/java/org/thingsboard/server/common/msg/cluster/SendToClusterMsg.java
@@ -13,28 +13,20 @@ @@ -13,28 +13,20 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.common.msg.cluster; 16 +package org.thingsboard.rule.engine.flow;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 -import org.thingsboard.server.common.data.id.DeviceId;  
20 -import org.thingsboard.server.common.data.id.EntityId;  
21 -import org.thingsboard.server.common.msg.MsgType;  
22 -import org.thingsboard.server.common.msg.TbActorMsg; 19 +import org.thingsboard.rule.engine.api.NodeConfiguration;
23 20
24 @Data 21 @Data
25 -public class SendToClusterMsg implements TbActorMsg {  
26 -  
27 - private TbActorMsg msg;  
28 - private EntityId entityId;  
29 -  
30 - public SendToClusterMsg(EntityId entityId, TbActorMsg msg) {  
31 - this.entityId = entityId;  
32 - this.msg = msg;  
33 - } 22 +public class TbCheckpointNodeConfiguration implements NodeConfiguration<TbCheckpointNodeConfiguration> {
34 23
  24 + private String queueName;
35 25
36 @Override 26 @Override
37 - public MsgType getMsgType() {  
38 - return MsgType.SEND_TO_CLUSTER_MSG; 27 + public TbCheckpointNodeConfiguration defaultConfiguration() {
  28 + TbCheckpointNodeConfiguration configuration = new TbCheckpointNodeConfiguration();
  29 + configuration.setQueueName("HighPriority");
  30 + return configuration;
39 } 31 }
40 } 32 }
@@ -116,8 +116,7 @@ public class TbSendRPCRequestNode implements TbNode { @@ -116,8 +116,7 @@ public class TbSendRPCRequestNode implements TbNode {
116 ctx.enqueueForTellNext(next, TbRelationTypes.SUCCESS); 116 ctx.enqueueForTellNext(next, TbRelationTypes.SUCCESS);
117 } else { 117 } else {
118 TbMsg next = ctx.newMsg(msg.getType(), msg.getOriginator(), msg.getMetaData(), wrap("error", ruleEngineDeviceRpcResponse.getError().get().name())); 118 TbMsg next = ctx.newMsg(msg.getType(), msg.getOriginator(), msg.getMetaData(), wrap("error", ruleEngineDeviceRpcResponse.getError().get().name()));
119 - ctx.tellFailure(next, new RuntimeException(ruleEngineDeviceRpcResponse.getError().get().name()));  
120 - ctx.enqueueForTellNext(next, TbRelationTypes.FAILURE); 119 + ctx.enqueueForTellFailure(next, ruleEngineDeviceRpcResponse.getError().get().name());
121 } 120 }
122 }); 121 });
123 ctx.ack(msg); 122 ctx.ack(msg);
@@ -102,20 +102,44 @@ queue: @@ -102,20 +102,44 @@ queue:
102 stats: 102 stats:
103 enabled: "${TB_QUEUE_CORE_STATS_ENABLED:false}" 103 enabled: "${TB_QUEUE_CORE_STATS_ENABLED:false}"
104 print_interval_ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}" 104 print_interval_ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}"
105 - rule_engine: 105 + rule-engine:
106 topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb.rule-engine}" 106 topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb.rule-engine}"
107 - poll_interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}"  
108 - partitions: "${TB_QUEUE_RULE_ENGINE_PARTITIONS:10}"  
109 - pack_processing_timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" 107 + poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}"
  108 + pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}"
110 stats: 109 stats:
111 - enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:false}"  
112 - print_interval_ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}" 110 + enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}"
  111 + print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}"
  112 + queues: # TODO 2.5: specify correct ENV variable names.
  113 + -
  114 + name: "Main"
  115 + topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb.rule-engine.main}"
  116 + poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}"
  117 + partitions: "${TB_QUEUE_RULE_ENGINE_PARTITIONS:10}"
  118 + pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}"
  119 + ack-strategy:
  120 + type: "${TB_QUEUE_RULE_ENGINE_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT
  121 + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT
  122 + retries: "${TB_QUEUE_RULE_ENGINE_STRATEGY_RETRIES:3}" # Number of retries, 0 is unlimited
  123 + failure-percentage: "${TB_QUEUE_RULE_ENGINE_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages;
  124 + pause-between-retries: "${TB_QUEUE_RULE_ENGINE_STRATEGY_RETRY_PAUSE:3}"# Time in seconds to wait in consumer thread before retries;
  125 + -
  126 + name: "HighPriority"
  127 + topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb.rule-engine.hp}"
  128 + poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}"
  129 + partitions: "${TB_QUEUE_RULE_ENGINE_PARTITIONS:3}"
  130 + pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}"
  131 + ack-strategy:
  132 + type: "${TB_QUEUE_RULE_ENGINE_STRATEGY_TYPE:RETRY_FAILED_AND_TIMED_OUT}" # SKIP_ALL_FAILURES, RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT
  133 + # For RETRY_ALL, RETRY_FAILED, RETRY_TIMED_OUT, RETRY_FAILED_AND_TIMED_OUT
  134 + retries: "${TB_QUEUE_RULE_ENGINE_STRATEGY_RETRIES:0}" # Number of retries, 0 is unlimited
  135 + failure-percentage: "${TB_QUEUE_RULE_ENGINE_STRATEGY_FAILURE_PERCENTAGE:0}" # Skip retry if failures or timeouts are less then X percentage of messages;
  136 + pause-between-retries: "${TB_QUEUE_RULE_ENGINE_STRATEGY_RETRY_PAUSE:1}"# Time in seconds to wait in consumer thread before retries;
113 transport: 137 transport:
114 notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb.transport.notifications}" 138 notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb.transport.notifications}"
115 poll_interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" 139 poll_interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}"
116 140
117 service: 141 service:
118 - type: "${TB_SERVICE_TYPE:tb-transport}" # monolith or tb-core or tb-rule-engine or tb-transport 142 + type: "${TB_SERVICE_TYPE:tb-transport}"
119 # Unique id for this service (autogenerated if empty) 143 # Unique id for this service (autogenerated if empty)
120 id: "${TB_SERVICE_ID:}" 144 id: "${TB_SERVICE_ID:}"
121 tenant_id: "${TB_SERVICE_TENANT_ID:}" # empty or specific tenant id. 145 tenant_id: "${TB_SERVICE_TENANT_ID:}" # empty or specific tenant id.