Showing
64 changed files
with
976 additions
and
720 deletions
... | ... | @@ -24,10 +24,9 @@ import akka.actor.Terminated; |
24 | 24 | import com.google.common.collect.BiMap; |
25 | 25 | import com.google.common.collect.HashBiMap; |
26 | 26 | import org.thingsboard.server.actors.ActorSystemContext; |
27 | -import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; | |
27 | +import org.thingsboard.server.actors.service.ContextAwareActor; | |
28 | 28 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
29 | 29 | import org.thingsboard.server.actors.service.DefaultActorService; |
30 | -import org.thingsboard.server.actors.shared.rulechain.SystemRuleChainManager; | |
31 | 30 | import org.thingsboard.server.actors.tenant.TenantActor; |
32 | 31 | import org.thingsboard.server.common.data.EntityType; |
33 | 32 | import org.thingsboard.server.common.data.Tenant; |
... | ... | @@ -37,16 +36,14 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
37 | 36 | import org.thingsboard.server.common.msg.MsgType; |
38 | 37 | import org.thingsboard.server.common.msg.TbActorMsg; |
39 | 38 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; |
40 | -import org.thingsboard.server.common.msg.cluster.SendToClusterMsg; | |
41 | 39 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
42 | -import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | |
43 | 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 | 42 | import org.thingsboard.server.dao.model.ModelConstants; |
46 | 43 | import org.thingsboard.server.dao.tenant.TenantService; |
47 | 44 | import scala.concurrent.duration.Duration; |
48 | 45 | |
49 | -public class AppActor extends RuleChainManagerActor { | |
46 | +public class AppActor extends ContextAwareActor { | |
50 | 47 | |
51 | 48 | private static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID); |
52 | 49 | private final TenantService tenantService; |
... | ... | @@ -54,7 +51,7 @@ public class AppActor extends RuleChainManagerActor { |
54 | 51 | private boolean ruleChainsInitialized; |
55 | 52 | |
56 | 53 | private AppActor(ActorSystemContext systemContext) { |
57 | - super(systemContext, new SystemRuleChainManager(systemContext)); | |
54 | + super(systemContext); | |
58 | 55 | this.tenantService = systemContext.getTenantService(); |
59 | 56 | this.tenantActors = HashBiMap.create(); |
60 | 57 | } |
... | ... | @@ -80,9 +77,6 @@ public class AppActor extends RuleChainManagerActor { |
80 | 77 | switch (msg.getMsgType()) { |
81 | 78 | case APP_INIT_MSG: |
82 | 79 | break; |
83 | - case SEND_TO_CLUSTER_MSG: | |
84 | - onPossibleClusterMsg((SendToClusterMsg) msg); | |
85 | - break; | |
86 | 80 | case PARTITION_CHANGE_MSG: |
87 | 81 | broadcast(msg); |
88 | 82 | break; |
... | ... | @@ -98,7 +92,6 @@ public class AppActor extends RuleChainManagerActor { |
98 | 92 | case DEVICE_NAME_OR_TYPE_UPDATE_TO_DEVICE_ACTOR_MSG: |
99 | 93 | case DEVICE_RPC_REQUEST_TO_DEVICE_ACTOR_MSG: |
100 | 94 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
101 | - case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG: | |
102 | 95 | onToDeviceActorMsg((TenantAwareMsg) msg); |
103 | 96 | break; |
104 | 97 | default: |
... | ... | @@ -110,7 +103,6 @@ public class AppActor extends RuleChainManagerActor { |
110 | 103 | private void initRuleChainsAndTenantActors() { |
111 | 104 | log.info("Starting main system actor."); |
112 | 105 | try { |
113 | - initRuleChains(); | |
114 | 106 | if (systemContext.isTenantComponentsInitEnabled()) { |
115 | 107 | PageDataIterable<Tenant> tenantIterator = new PageDataIterable<>(tenantService::findTenants, ENTITY_PACK_LIMIT); |
116 | 108 | for (Tenant tenant : tenantIterator) { |
... | ... | @@ -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 | 120 | private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) { |
141 | 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 | 123 | } else { |
145 | 124 | getOrCreateTenantActor(msg.getTenantId()).tell(msg, self()); |
146 | 125 | } |
147 | 126 | } |
148 | 127 | |
149 | - @Override | |
150 | 128 | protected void broadcast(Object msg) { |
151 | - super.broadcast(msg); | |
152 | 129 | tenantActors.values().forEach(actorRef -> actorRef.tell(msg, ActorRef.noSender())); |
153 | 130 | } |
154 | 131 | |
155 | 132 | private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { |
156 | 133 | ActorRef target = null; |
157 | 134 | if (SYSTEM_TENANT.equals(msg.getTenantId())) { |
158 | - target = getEntityActorRef(msg.getEntityId()); | |
135 | + log.warn("Message has system tenant id: {}", msg); | |
159 | 136 | } else { |
160 | 137 | if (msg.getEntityId().getEntityType() == EntityType.TENANT |
161 | 138 | && msg.getEvent() == ComponentLifecycleEvent.DELETED) { | ... | ... |
... | ... | @@ -56,7 +56,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMs |
56 | 56 | import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg; |
57 | 57 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
58 | 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 | 60 | import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; |
61 | 61 | import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; |
62 | 62 | import org.thingsboard.server.service.rpc.ToServerRpcResponseActorMsg; |
... | ... | @@ -213,7 +213,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
213 | 213 | |
214 | 214 | void process(ActorContext context, TransportToDeviceActorMsgWrapper wrapper) { |
215 | 215 | TransportToDeviceActorMsg msg = wrapper.getMsg(); |
216 | - TbMsgCallback callback = wrapper.getCallback(); | |
216 | + TbCallback callback = wrapper.getCallback(); | |
217 | 217 | if (msg.hasSessionEvent()) { |
218 | 218 | processSessionStateMsgs(msg.getSessionInfo(), msg.getSessionEvent()); |
219 | 219 | } | ... | ... |
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 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 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
... | ... | @@ -110,7 +110,7 @@ class DefaultTbContext implements TbContext { |
110 | 110 | if (nodeCtx.getSelf().isDebugMode()) { |
111 | 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 | 116 | @Override |
... | ... | @@ -140,52 +140,60 @@ class DefaultTbContext implements TbContext { |
140 | 140 | } |
141 | 141 | |
142 | 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 | 149 | public void enqueueForTellNext(TbMsg tbMsg, String relationType) { |
144 | 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 | 154 | @Override |
149 | 155 | public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes) { |
150 | 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 | 160 | @Override |
155 | 161 | public void enqueueForTellNext(TbMsg tbMsg, String relationType, Runnable onSuccess, Consumer<Throwable> onFailure) { |
156 | 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 | 166 | @Override |
161 | 167 | public void enqueueForTellNext(TbMsg tbMsg, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) { |
162 | 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 | 172 | @Override |
167 | 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 | 178 | @Override |
173 | 179 | public void enqueueForTellNext(TbMsg tbMsg, String queueName, Set<String> relationTypes, Runnable onSuccess, Consumer<Throwable> onFailure) { |
174 | 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 | 185 | RuleChainId ruleChainId = nodeCtx.getSelf().getRuleChainId(); |
180 | 186 | RuleNodeId ruleNodeId = nodeCtx.getSelf().getId(); |
181 | 187 | tbMsg = TbMsg.newMsg(tbMsg, ruleChainId, ruleNodeId); |
182 | - TransportProtos.ToRuleEngineMsg msg = TransportProtos.ToRuleEngineMsg.newBuilder() | |
188 | + TransportProtos.ToRuleEngineMsg.Builder msg = TransportProtos.ToRuleEngineMsg.newBuilder() | |
183 | 189 | .setTenantIdMSB(getTenantId().getId().getMostSignificantBits()) |
184 | 190 | .setTenantIdLSB(getTenantId().getId().getLeastSignificantBits()) |
185 | 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 | 199 | @Override |
... | ... | @@ -207,7 +215,8 @@ class DefaultTbContext implements TbContext { |
207 | 215 | if (nodeCtx.getSelf().isDebugMode()) { |
208 | 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 | 222 | public void updateSelf(RuleNode self) { | ... | ... |
application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java
deleted
100644 → 0
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 | 22 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
23 | 23 | import org.thingsboard.server.common.data.id.RuleChainId; |
24 | 24 | import org.thingsboard.server.common.data.id.TenantId; |
25 | +import org.thingsboard.server.common.data.rule.RuleChain; | |
25 | 26 | import org.thingsboard.server.common.msg.TbActorMsg; |
26 | 27 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
27 | 28 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
... | ... | @@ -30,9 +31,9 @@ import scala.concurrent.duration.Duration; |
30 | 31 | |
31 | 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 | 37 | context().parent(), context().self())); |
37 | 38 | } |
38 | 39 | |
... | ... | @@ -46,7 +47,6 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe |
46 | 47 | processor.onQueueToRuleEngineMsg((QueueToRuleEngineMsg) msg); |
47 | 48 | break; |
48 | 49 | case RULE_TO_RULE_CHAIN_TELL_NEXT_MSG: |
49 | - case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG: | |
50 | 50 | processor.onTellNext((RuleNodeToRuleChainTellNextMsg) msg); |
51 | 51 | break; |
52 | 52 | case RULE_CHAIN_TO_RULE_CHAIN_MSG: |
... | ... | @@ -68,17 +68,17 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe |
68 | 68 | private static final long serialVersionUID = 1L; |
69 | 69 | |
70 | 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 | 74 | super(context); |
75 | 75 | this.tenantId = tenantId; |
76 | - this.ruleChainId = pluginId; | |
76 | + this.ruleChain = ruleChain; | |
77 | 77 | } |
78 | 78 | |
79 | 79 | @Override |
80 | 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 | 5 | * you may not use this file except in compliance with the License. |
6 | 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 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
... | ... | @@ -37,6 +37,8 @@ import org.thingsboard.server.common.msg.TbMsg; |
37 | 37 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
38 | 38 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
39 | 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 | 42 | import org.thingsboard.server.common.msg.queue.ServiceType; |
41 | 43 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
42 | 44 | import org.thingsboard.server.dao.rule.RuleChainService; |
... | ... | @@ -67,14 +69,16 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
67 | 69 | private final Map<RuleNodeId, List<RuleNodeRelation>> nodeRoutes; |
68 | 70 | private final RuleChainService service; |
69 | 71 | private final TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> producer; |
72 | + private String ruleChainName; | |
70 | 73 | |
71 | 74 | private RuleNodeId firstId; |
72 | 75 | private RuleNodeCtx firstNode; |
73 | 76 | private boolean started; |
74 | 77 | |
75 | - RuleChainActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, ActorSystemContext systemContext | |
78 | + RuleChainActorMessageProcessor(TenantId tenantId, RuleChain ruleChain, ActorSystemContext systemContext | |
76 | 79 | , ActorRef parent, ActorRef self) { |
77 | - super(systemContext, tenantId, ruleChainId); | |
80 | + super(systemContext, tenantId, ruleChain.getId()); | |
81 | + this.ruleChainName = ruleChain.getName(); | |
78 | 82 | this.parent = parent; |
79 | 83 | this.self = self; |
80 | 84 | this.nodeActors = new HashMap<>(); |
... | ... | @@ -113,6 +117,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
113 | 117 | public void onUpdate(ActorContext context) { |
114 | 118 | RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); |
115 | 119 | if (ruleChain != null) { |
120 | + ruleChainName = ruleChain.getName(); | |
116 | 121 | List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId); |
117 | 122 | log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); |
118 | 123 | for (RuleNode ruleNode : ruleNodeList) { |
... | ... | @@ -194,7 +199,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
194 | 199 | void onQueueToRuleEngineMsg(QueueToRuleEngineMsg envelope) { |
195 | 200 | TbMsg msg = envelope.getTbMsg(); |
196 | 201 | log.trace("[{}][{}] Processing message [{}]: {}", entityId, firstId, msg.getId(), msg); |
197 | - if (envelope.getRelationTypes() == null) { | |
202 | + if (envelope.getRelationTypes() == null || envelope.getRelationTypes().isEmpty()) { | |
198 | 203 | try { |
199 | 204 | checkActive(); |
200 | 205 | RuleNodeId targetId = msg.getRuleNodeId(); |
... | ... | @@ -213,10 +218,10 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
213 | 218 | msg.getCallback().onSuccess(); |
214 | 219 | } |
215 | 220 | } catch (Exception e) { |
216 | - envelope.getTbMsg().getCallback().onFailure(e); | |
221 | + envelope.getTbMsg().getCallback().onFailure(new RuleEngineException(e.getMessage())); | |
217 | 222 | } |
218 | 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 | 235 | } |
231 | 236 | |
232 | 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 | 242 | try { |
238 | 243 | checkActive(); |
239 | 244 | EntityId entityId = msg.getOriginator(); |
... | ... | @@ -245,9 +250,14 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
245 | 250 | if (relationsCount == 0) { |
246 | 251 | log.trace("[{}][{}][{}] No outbound relations to process", tenantId, entityId, msg.getId()); |
247 | 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 | 261 | } else { |
252 | 262 | msg.getCallback().onSuccess(); |
253 | 263 | } |
... | ... | @@ -265,7 +275,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh |
265 | 275 | } |
266 | 276 | } |
267 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.actors.ruleChain; |
17 | 17 | |
18 | +import akka.actor.ActorContext; | |
18 | 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 | 24 | import org.thingsboard.server.actors.ActorSystemContext; |
20 | 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 | 28 | import org.thingsboard.server.common.data.id.EntityId; |
23 | 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 | 33 | import org.thingsboard.server.dao.rule.RuleChainService; |
25 | 34 | |
35 | +import java.util.function.Function; | |
36 | + | |
26 | 37 | /** |
27 | 38 | * Created by ashvayka on 15.03.18. |
28 | 39 | */ |
29 | 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 | 51 | super(systemContext); |
36 | - this.ruleChainManager = ruleChainManager; | |
52 | + this.tenantId = tenantId; | |
53 | + this.actors = HashBiMap.create(); | |
37 | 54 | this.ruleChainService = systemContext.getRuleChainService(); |
38 | 55 | } |
39 | 56 | |
40 | 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 | 87 | protected ActorRef getEntityActorRef(EntityId entityId) { |
45 | 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 | 92 | return target; |
52 | 93 | } |
53 | 94 | |
54 | 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 | 34 | private final RuleNodeId originator; |
35 | 35 | private final Set<String> relationTypes; |
36 | 36 | private final TbMsg msg; |
37 | + private final String failureMessage; | |
37 | 38 | |
38 | 39 | @Override |
39 | 40 | public MsgType getMsgType() { | ... | ... |
application/src/main/java/org/thingsboard/server/actors/shared/EntityActorsManager.java
deleted
100644 → 0
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 | -} |
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java
deleted
100644 → 0
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 | -} |
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/TenantRuleChainManager.java
deleted
100644 → 0
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 | 24 | import org.thingsboard.server.common.data.DataConstants; |
25 | 25 | import org.thingsboard.server.common.data.Event; |
26 | 26 | import org.thingsboard.server.common.msg.TbActorMsg; |
27 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | |
28 | 27 | |
29 | 28 | @Slf4j |
30 | 29 | public class StatsActor extends ContextAwareActor { | ... | ... |
... | ... | @@ -30,7 +30,6 @@ import org.thingsboard.server.actors.device.DeviceActorCreator; |
30 | 30 | import org.thingsboard.server.actors.ruleChain.RuleChainManagerActor; |
31 | 31 | import org.thingsboard.server.actors.service.ContextBasedCreator; |
32 | 32 | import org.thingsboard.server.actors.service.DefaultActorService; |
33 | -import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager; | |
34 | 33 | import org.thingsboard.server.common.data.EntityType; |
35 | 34 | import org.thingsboard.server.common.data.id.DeviceId; |
36 | 35 | import org.thingsboard.server.common.data.id.RuleChainId; |
... | ... | @@ -43,6 +42,7 @@ import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg; |
43 | 42 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
44 | 43 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
45 | 44 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; |
45 | +import org.thingsboard.server.common.msg.queue.RuleEngineException; | |
46 | 46 | import org.thingsboard.server.common.msg.queue.ServiceType; |
47 | 47 | import scala.concurrent.duration.Duration; |
48 | 48 | |
... | ... | @@ -51,12 +51,12 @@ import java.util.stream.Collectors; |
51 | 51 | |
52 | 52 | public class TenantActor extends RuleChainManagerActor { |
53 | 53 | |
54 | - private final TenantId tenantId; | |
55 | 54 | private final BiMap<DeviceId, ActorRef> deviceActors; |
55 | + private boolean isRuleEngine; | |
56 | + private boolean isCore; | |
56 | 57 | |
57 | 58 | private TenantActor(ActorSystemContext systemContext, TenantId tenantId) { |
58 | - super(systemContext, new TenantRuleChainManager(systemContext, tenantId)); | |
59 | - this.tenantId = tenantId; | |
59 | + super(systemContext, tenantId); | |
60 | 60 | this.deviceActors = HashBiMap.create(); |
61 | 61 | } |
62 | 62 | |
... | ... | @@ -69,7 +69,11 @@ public class TenantActor extends RuleChainManagerActor { |
69 | 69 | public void preStart() { |
70 | 70 | log.info("[{}] Starting tenant actor.", tenantId); |
71 | 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 | 77 | log.info("[{}] Tenant actor started.", tenantId); |
74 | 78 | } catch (Exception e) { |
75 | 79 | log.warn("[{}] Unknown failure", tenantId, e); |
... | ... | @@ -115,7 +119,6 @@ public class TenantActor extends RuleChainManagerActor { |
115 | 119 | onToDeviceActorMsg((DeviceAwareMsg) msg); |
116 | 120 | break; |
117 | 121 | case RULE_CHAIN_TO_RULE_CHAIN_MSG: |
118 | - case REMOTE_TO_RULE_CHAIN_TELL_NEXT_MSG: | |
119 | 122 | onRuleChainMsg((RuleChainAwareMsg) msg); |
120 | 123 | break; |
121 | 124 | default: |
... | ... | @@ -129,16 +132,19 @@ public class TenantActor extends RuleChainManagerActor { |
129 | 132 | } |
130 | 133 | |
131 | 134 | private void onQueueToRuleEngineMsg(QueueToRuleEngineMsg msg) { |
135 | + if (!isRuleEngine) { | |
136 | + log.warn("RECEIVED INVALID MESSAGE: {}", msg); | |
137 | + } | |
132 | 138 | TbMsg tbMsg = msg.getTbMsg(); |
133 | 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 | 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 | 144 | log.info("[{}] No Root Chain: {}", tenantId, msg); |
139 | 145 | } |
140 | 146 | } else { |
141 | - ActorRef ruleChainActor = ruleChainManager.get(tbMsg.getRuleChainId()); | |
147 | + ActorRef ruleChainActor = get(tbMsg.getRuleChainId()); | |
142 | 148 | if (ruleChainActor != null) { |
143 | 149 | ruleChainActor.tell(msg, self()); |
144 | 150 | } else { |
... | ... | @@ -150,24 +156,29 @@ public class TenantActor extends RuleChainManagerActor { |
150 | 156 | } |
151 | 157 | |
152 | 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 | 162 | private void onToDeviceActorMsg(DeviceAwareMsg msg) { |
163 | + if (!isCore) { | |
164 | + log.warn("RECEIVED INVALID MESSAGE: {}", msg); | |
165 | + } | |
157 | 166 | getOrCreateDeviceActor(msg.getDeviceId()).tell(msg, ActorRef.noSender()); |
158 | 167 | } |
159 | 168 | |
160 | 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 | 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 | 92 | try { |
93 | 93 | SessionMetaData sessionMd = internalSessionMap.get(session.getId()); |
94 | 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 | 96 | webSocketService.handleWebSocketMsg(sessionMd.sessionRef, message.getPayload()); |
97 | 97 | } else { |
98 | - log.warn("[{}] Failed to find session", session.getId()); | |
98 | + log.trace("[{}] Failed to find session", session.getId()); | |
99 | 99 | session.close(CloseStatus.SERVER_ERROR.withReason("Session not found!")); |
100 | 100 | } |
101 | 101 | } catch (IOException e) { |
... | ... | @@ -139,7 +139,7 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements Telemetr |
139 | 139 | if (sessionMd != null) { |
140 | 140 | processInWebSocketService(sessionMd.sessionRef, SessionEvent.onError(tError)); |
141 | 141 | } else { |
142 | - log.warn("[{}] Failed to find session", session.getId()); | |
142 | + log.trace("[{}] Failed to find session", session.getId()); | |
143 | 143 | } |
144 | 144 | log.trace("[{}] Session transport error", session.getId(), tError); |
145 | 145 | } | ... | ... |
... | ... | @@ -25,7 +25,7 @@ import org.thingsboard.server.actors.ActorSystemContext; |
25 | 25 | import org.thingsboard.server.common.data.id.TenantId; |
26 | 26 | import org.thingsboard.server.common.msg.TbActorMsg; |
27 | 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 | 29 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; |
30 | 30 | import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto; |
31 | 31 | import org.thingsboard.server.gen.transport.TransportProtos.LocalSubscriptionServiceMsgProto; |
... | ... | @@ -120,8 +120,8 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore |
120 | 120 | ConcurrentMap<UUID, TbProtoQueueMsg<ToCoreMsg>> failedMap = new ConcurrentHashMap<>(); |
121 | 121 | CountDownLatch processingTimeoutLatch = new CountDownLatch(1); |
122 | 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 | 125 | try { |
126 | 126 | ToCoreMsg toCoreMsg = msg.getValue(); |
127 | 127 | if (toCoreMsg.hasToSubscriptionMgrMsg()) { |
... | ... | @@ -182,7 +182,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore |
182 | 182 | } |
183 | 183 | |
184 | 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 | 186 | ToCoreNotificationMsg toCoreMsg = msg.getValue(); |
187 | 187 | if (toCoreMsg.hasToLocalSubscriptionServiceMsg()) { |
188 | 188 | log.trace("[{}] Forwarding message to local subscription service {}", id, toCoreMsg.getToLocalSubscriptionServiceMsg()); |
... | ... | @@ -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 | 204 | RpcError error = proto.getError() > 0 ? RpcError.values()[proto.getError()] : null; |
205 | 205 | FromDeviceRpcResponse response = new FromDeviceRpcResponse(new UUID(proto.getRequestIdMSB(), proto.getRequestIdLSB()) |
206 | 206 | , proto.getResponse(), error); |
... | ... | @@ -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 | 219 | if (msg.hasSubUpdate()) { |
220 | 220 | localSubscriptionService.onSubscriptionUpdate(msg.getSubUpdate().getSessionId(), TbSubscriptionUtils.fromProto(msg.getSubUpdate()), callback); |
221 | 221 | } else { |
... | ... | @@ -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 | 227 | if (msg.hasAttributeSub()) { |
228 | 228 | subscriptionManagerService.addSubscription(TbSubscriptionUtils.fromProto(msg.getAttributeSub()), callback); |
229 | 229 | } else if (msg.hasTelemetrySub()) { |
... | ... | @@ -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 | 252 | if (statsEnabled) { |
253 | 253 | stats.log(deviceStateServiceMsg); |
254 | 254 | } |
255 | 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 | 259 | if (statsEnabled) { |
260 | 260 | stats.log(toDeviceActorMsg); |
261 | 261 | } |
262 | 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 | 266 | log.warn("Message not handled: {}", msg); |
267 | 267 | callback.onFailure(new RuntimeException("Message not handled!")); |
268 | 268 | } | ... | ... |
... | ... | @@ -27,8 +27,11 @@ import org.thingsboard.server.common.data.id.TenantId; |
27 | 27 | import org.thingsboard.server.common.msg.TbActorMsg; |
28 | 28 | import org.thingsboard.server.common.msg.TbMsg; |
29 | 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 | 32 | import org.thingsboard.server.common.msg.queue.ServiceQueue; |
31 | 33 | import org.thingsboard.server.common.msg.queue.ServiceType; |
34 | +import org.thingsboard.server.common.msg.queue.TbCallback; | |
32 | 35 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
33 | 36 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
34 | 37 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg; |
... | ... | @@ -45,6 +48,7 @@ import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingDec |
45 | 48 | import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingResult; |
46 | 49 | import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategy; |
47 | 50 | import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory; |
51 | +import org.thingsboard.server.service.stats.RuleEngineStatisticsService; | |
48 | 52 | |
49 | 53 | import javax.annotation.PostConstruct; |
50 | 54 | import java.util.Collections; |
... | ... | @@ -69,20 +73,22 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< |
69 | 73 | private long pollDuration; |
70 | 74 | @Value("${queue.rule-engine.pack-processing-timeout}") |
71 | 75 | private long packProcessingTimeout; |
72 | - @Value("${queue.rule-engine.stats.enabled:false}") | |
76 | + @Value("${queue.rule-engine.stats.enabled:true}") | |
73 | 77 | private boolean statsEnabled; |
74 | 78 | |
75 | - private final TbCoreConsumerStats stats = new TbCoreConsumerStats(); | |
76 | 79 | private final TbRuleEngineProcessingStrategyFactory factory; |
77 | 80 | private final TbRuleEngineQueueFactory tbRuleEngineQueueFactory; |
78 | 81 | private final TbQueueRuleEngineSettings ruleEngineSettings; |
82 | + private final RuleEngineStatisticsService statisticsService; | |
79 | 83 | private final ConcurrentMap<String, TbQueueConsumer<TbProtoQueueMsg<ToRuleEngineMsg>>> consumers = new ConcurrentHashMap<>(); |
80 | 84 | private final ConcurrentMap<String, TbRuleEngineQueueConfiguration> consumerConfigurations = new ConcurrentHashMap<>(); |
85 | + private final ConcurrentMap<String, TbRuleEngineConsumerStats> consumerStats = new ConcurrentHashMap<>(); | |
81 | 86 | |
82 | 87 | public DefaultTbRuleEngineConsumerService(TbRuleEngineProcessingStrategyFactory factory, TbQueueRuleEngineSettings ruleEngineSettings, |
83 | - TbRuleEngineQueueFactory tbRuleEngineQueueFactory, | |
88 | + TbRuleEngineQueueFactory tbRuleEngineQueueFactory, RuleEngineStatisticsService statisticsService, | |
84 | 89 | ActorSystemContext actorContext, DataDecodingEncodingService encodingService) { |
85 | 90 | super(actorContext, encodingService, tbRuleEngineQueueFactory.createToRuleEngineNotificationsMsgConsumer()); |
91 | + this.statisticsService = statisticsService; | |
86 | 92 | this.ruleEngineSettings = ruleEngineSettings; |
87 | 93 | this.tbRuleEngineQueueFactory = tbRuleEngineQueueFactory; |
88 | 94 | this.factory = factory; |
... | ... | @@ -92,7 +98,9 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< |
92 | 98 | public void init() { |
93 | 99 | super.init("tb-rule-engine-consumer", "tb-rule-engine-notifications-consumer"); |
94 | 100 | for (TbRuleEngineQueueConfiguration configuration : ruleEngineSettings.getQueues()) { |
101 | + consumerConfigurations.putIfAbsent(configuration.getName(), configuration); | |
95 | 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 | 115 | |
108 | 116 | @Override |
109 | 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 | 121 | @Override |
... | ... | @@ -115,7 +123,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< |
115 | 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 | 127 | consumersExecutor.execute(() -> { |
120 | 128 | while (!stopped) { |
121 | 129 | try { |
... | ... | @@ -123,7 +131,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< |
123 | 131 | if (msgs.isEmpty()) { |
124 | 132 | continue; |
125 | 133 | } |
126 | - TbRuleEngineProcessingStrategy strategy = factory.newInstance(configuration.getAckStrategy()); | |
134 | + TbRuleEngineProcessingStrategy strategy = factory.newInstance(configuration.getName(), configuration.getAckStrategy()); | |
127 | 135 | TbRuleEngineProcessingDecision decision = null; |
128 | 136 | boolean firstAttempt = true; |
129 | 137 | while (!stopped && (firstAttempt || !decision.isCommit())) { |
... | ... | @@ -137,21 +145,21 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< |
137 | 145 | } |
138 | 146 | ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap = new ConcurrentHashMap<>(); |
139 | 147 | ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failedMap = new ConcurrentHashMap<>(); |
140 | - | |
148 | + ConcurrentMap<TenantId, RuleEngineException> exceptionsMap = new ConcurrentHashMap<>(); | |
141 | 149 | CountDownLatch processingTimeoutLatch = new CountDownLatch(1); |
142 | 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 | 155 | try { |
146 | - ToRuleEngineMsg toRuleEngineMsg = msg.getValue(); | |
147 | - TenantId tenantId = new TenantId(new UUID(toRuleEngineMsg.getTenantIdMSB(), toRuleEngineMsg.getTenantIdLSB())); | |
148 | 156 | if (toRuleEngineMsg.getTbMsg() != null && !toRuleEngineMsg.getTbMsg().isEmpty()) { |
149 | 157 | forwardToRuleEngineActor(tenantId, toRuleEngineMsg, callback); |
150 | 158 | } else { |
151 | 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 | 167 | if (!processingTimeoutLatch.await(packProcessingTimeout, TimeUnit.MILLISECONDS)) { |
160 | 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 | 176 | consumer.commit(); |
165 | 177 | } catch (Exception e) { |
... | ... | @@ -193,7 +205,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< |
193 | 205 | } |
194 | 206 | |
195 | 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 | 209 | ToRuleEngineNotificationMsg nfMsg = msg.getValue(); |
198 | 210 | if (nfMsg.getComponentLifecycleMsg() != null && !nfMsg.getComponentLifecycleMsg().isEmpty()) { |
199 | 211 | Optional<TbActorMsg> actorMsg = encodingService.decode(nfMsg.getComponentLifecycleMsg().toByteArray()); |
... | ... | @@ -219,18 +231,18 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< |
219 | 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 | 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 | 238 | @Scheduled(fixedDelayString = "${queue.rule-engine.stats.print-interval-ms}") |
231 | 239 | public void printStats() { |
232 | 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 | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | |
18 | 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 | 21 | import java.util.UUID; |
23 | -import java.util.concurrent.ConcurrentHashMap; | |
24 | 22 | import java.util.concurrent.ConcurrentMap; |
25 | 23 | import java.util.concurrent.CountDownLatch; |
26 | 24 | |
27 | 25 | @Slf4j |
28 | -public class MsgPackCallback<T> implements TbMsgCallback { | |
26 | +public class TbPackCallback<T> implements TbCallback { | |
29 | 27 | private final CountDownLatch processingTimeoutLatch; |
30 | 28 | private final ConcurrentMap<UUID, T> ackMap; |
31 | - private final ConcurrentMap<UUID, T> successMap; | |
32 | 29 | private final ConcurrentMap<UUID, T> failedMap; |
33 | 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 | 36 | this.id = id; |
40 | 37 | this.processingTimeoutLatch = processingTimeoutLatch; |
41 | 38 | this.ackMap = ackMap; |
42 | - this.successMap = successMap; | |
43 | 39 | this.failedMap = failedMap; |
44 | 40 | } |
45 | 41 | |
... | ... | @@ -47,9 +43,6 @@ public class MsgPackCallback<T> implements TbMsgCallback { |
47 | 43 | public void onSuccess() { |
48 | 44 | log.trace("[{}] ON SUCCESS", id); |
49 | 45 | T msg = ackMap.remove(id); |
50 | - if (msg != null) { | |
51 | - successMap.put(id, msg); | |
52 | - } | |
53 | 46 | if (msg != null && ackMap.isEmpty()) { |
54 | 47 | processingTimeoutLatch.countDown(); |
55 | 48 | } |
... | ... | @@ -57,7 +50,7 @@ public class MsgPackCallback<T> implements TbMsgCallback { |
57 | 50 | |
58 | 51 | @Override |
59 | 52 | public void onFailure(Throwable t) { |
60 | - log.trace("[{}] ON FAILURE", id); | |
53 | + log.trace("[{}] ON FAILURE", id, t); | |
61 | 54 | T msg = ackMap.remove(id); |
62 | 55 | if (msg != null) { |
63 | 56 | failedMap.put(id, msg); | ... | ... |
... | ... | @@ -15,38 +15,119 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | |
18 | +import lombok.Data; | |
18 | 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 | 32 | import java.util.concurrent.atomic.AtomicInteger; |
22 | 33 | |
23 | 34 | @Slf4j |
35 | +@Data | |
24 | 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 | 117 | public void printStats() { |
45 | - int total = totalCounter.getAndSet(0); | |
118 | + int total = totalMsgCounter.get(); | |
46 | 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 | } | ... | ... |
application/src/main/java/org/thingsboard/server/service/queue/TbTenantRuleEngineStats.java
0 → 100644
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 | 22 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
23 | 23 | import org.thingsboard.server.actors.ActorSystemContext; |
24 | 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 | 26 | import org.thingsboard.server.queue.TbQueueConsumer; |
27 | 27 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
28 | 28 | import org.thingsboard.server.queue.discovery.PartitionChangeEvent; |
29 | 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 | 32 | import javax.annotation.PreDestroy; |
33 | 33 | import java.util.List; |
... | ... | @@ -95,8 +95,8 @@ public abstract class AbstractConsumerService<N extends com.google.protobuf.Gene |
95 | 95 | ConcurrentMap<UUID, TbProtoQueueMsg<N>> failedMap = new ConcurrentHashMap<>(); |
96 | 96 | CountDownLatch processingTimeoutLatch = new CountDownLatch(1); |
97 | 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 | 100 | try { |
101 | 101 | handleNotification(id, msg, callback); |
102 | 102 | } catch (Throwable e) { |
... | ... | @@ -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 | 129 | @PreDestroy |
130 | 130 | public void destroy() { | ... | ... |
... | ... | @@ -16,6 +16,8 @@ |
16 | 16 | package org.thingsboard.server.service.queue.processing; |
17 | 17 | |
18 | 18 | import lombok.Getter; |
19 | +import org.thingsboard.server.common.data.id.TenantId; | |
20 | +import org.thingsboard.server.common.msg.queue.RuleEngineException; | |
19 | 21 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
20 | 22 | import org.thingsboard.server.queue.common.TbProtoQueueMsg; |
21 | 23 | |
... | ... | @@ -25,24 +27,28 @@ import java.util.concurrent.ConcurrentMap; |
25 | 27 | public class TbRuleEngineProcessingResult { |
26 | 28 | |
27 | 29 | @Getter |
28 | - private boolean success; | |
30 | + private final boolean success; | |
29 | 31 | @Getter |
30 | - private boolean timeout; | |
32 | + private final boolean timeout; | |
31 | 33 | @Getter |
32 | - private ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> pendingMap; | |
34 | + private final ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> pendingMap; | |
33 | 35 | @Getter |
34 | - private ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap; | |
36 | + private final ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap; | |
35 | 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 | 42 | public TbRuleEngineProcessingResult(boolean timeout, |
39 | 43 | ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> pendingMap, |
40 | 44 | ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> successMap, |
41 | - ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failureMap) { | |
45 | + ConcurrentMap<UUID, TbProtoQueueMsg<ToRuleEngineMsg>> failureMap, | |
46 | + ConcurrentMap<TenantId, RuleEngineException> exceptionsMap) { | |
42 | 47 | this.timeout = timeout; |
43 | 48 | this.pendingMap = pendingMap; |
44 | 49 | this.successMap = successMap; |
45 | 50 | this.failureMap = failureMap; |
51 | + this.exceptionsMap = exceptionsMap; | |
46 | 52 | this.success = !timeout && pendingMap.isEmpty() && failureMap.isEmpty(); |
47 | 53 | } |
48 | 54 | } | ... | ... |
... | ... | @@ -32,24 +32,25 @@ import java.util.concurrent.TimeUnit; |
32 | 32 | @Slf4j |
33 | 33 | public class TbRuleEngineProcessingStrategyFactory { |
34 | 34 | |
35 | - public TbRuleEngineProcessingStrategy newInstance(TbRuleEngineQueueAckStrategyConfiguration configuration) { | |
35 | + public TbRuleEngineProcessingStrategy newInstance(String name, TbRuleEngineQueueAckStrategyConfiguration configuration) { | |
36 | 36 | switch (configuration.getType()) { |
37 | 37 | case "SKIP_ALL": |
38 | - return new SkipStrategy(); | |
38 | + return new SkipStrategy(name); | |
39 | 39 | case "RETRY_ALL": |
40 | - return new RetryStrategy(true, true, true, configuration); | |
40 | + return new RetryStrategy(name, true, true, true, configuration); | |
41 | 41 | case "RETRY_FAILED": |
42 | - return new RetryStrategy(false, true, false, configuration); | |
42 | + return new RetryStrategy(name, false, true, false, configuration); | |
43 | 43 | case "RETRY_TIMED_OUT": |
44 | - return new RetryStrategy(false, false, true, configuration); | |
44 | + return new RetryStrategy(name, false, false, true, configuration); | |
45 | 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 | 47 | default: |
48 | 48 | throw new RuntimeException("TbRuleEngineProcessingStrategy with type " + configuration.getType() + " is not supported!"); |
49 | 49 | } |
50 | 50 | } |
51 | 51 | |
52 | 52 | private static class RetryStrategy implements TbRuleEngineProcessingStrategy { |
53 | + private final String queueName; | |
53 | 54 | private final boolean retrySuccessful; |
54 | 55 | private final boolean retryFailed; |
55 | 56 | private final boolean retryTimeout; |
... | ... | @@ -60,7 +61,8 @@ public class TbRuleEngineProcessingStrategyFactory { |
60 | 61 | private int initialTotalCount; |
61 | 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 | 66 | this.retrySuccessful = retrySuccessful; |
65 | 67 | this.retryFailed = retryFailed; |
66 | 68 | this.retryTimeout = retryTimeout; |
... | ... | @@ -80,10 +82,10 @@ public class TbRuleEngineProcessingStrategyFactory { |
80 | 82 | retryCount++; |
81 | 83 | double failedCount = result.getFailureMap().size() + result.getPendingMap().size(); |
82 | 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 | 86 | return new TbRuleEngineProcessingDecision(true, null); |
85 | 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 | 89 | return new TbRuleEngineProcessingDecision(true, null); |
88 | 90 | } else { |
89 | 91 | ConcurrentMap<UUID, TbProtoQueueMsg<TransportProtos.ToRuleEngineMsg>> toReprocess = new ConcurrentHashMap<>(initialTotalCount); |
... | ... | @@ -96,8 +98,7 @@ public class TbRuleEngineProcessingStrategyFactory { |
96 | 98 | if (retrySuccessful) { |
97 | 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 | 102 | if (log.isTraceEnabled()) { |
102 | 103 | toReprocess.forEach((id, msg) -> log.trace("Going to reprocess [{}]: {}", id, msg.getValue())); |
103 | 104 | } |
... | ... | @@ -116,9 +117,15 @@ public class TbRuleEngineProcessingStrategyFactory { |
116 | 117 | |
117 | 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 | 126 | @Override |
120 | 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 | 129 | return new TbRuleEngineProcessingDecision(true, null); |
123 | 130 | } |
124 | 131 | } | ... | ... |
... | ... | @@ -19,7 +19,6 @@ import lombok.Getter; |
19 | 19 | import lombok.RequiredArgsConstructor; |
20 | 20 | import lombok.ToString; |
21 | 21 | import org.thingsboard.rule.engine.api.RpcError; |
22 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | |
23 | 22 | |
24 | 23 | import java.util.Optional; |
25 | 24 | import java.util.UUID; | ... | ... |
... | ... | @@ -22,11 +22,8 @@ import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; |
22 | 22 | import org.thingsboard.server.common.data.id.DeviceId; |
23 | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | 24 | import org.thingsboard.server.common.msg.MsgType; |
25 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | |
26 | 25 | import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; |
27 | 26 | |
28 | -import java.util.Optional; | |
29 | - | |
30 | 27 | /** |
31 | 28 | * Created by ashvayka on 16.04.18. |
32 | 29 | */ | ... | ... |
... | ... | @@ -55,7 +55,7 @@ import org.thingsboard.server.queue.discovery.PartitionService; |
55 | 55 | import org.thingsboard.server.common.msg.queue.ServiceType; |
56 | 56 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
57 | 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 | 59 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
60 | 60 | import org.thingsboard.server.queue.util.TbCoreComponent; |
61 | 61 | import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; |
... | ... | @@ -242,7 +242,7 @@ public class DefaultDeviceStateService implements DeviceStateService { |
242 | 242 | } |
243 | 243 | |
244 | 244 | @Override |
245 | - public void onQueueMsg(TransportProtos.DeviceStateServiceMsgProto proto, TbMsgCallback callback) { | |
245 | + public void onQueueMsg(TransportProtos.DeviceStateServiceMsgProto proto, TbCallback callback) { | |
246 | 246 | try { |
247 | 247 | TenantId tenantId = new TenantId(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())); |
248 | 248 | DeviceId deviceId = new DeviceId(new UUID(proto.getDeviceIdMSB(), proto.getDeviceIdLSB())); | ... | ... |
... | ... | @@ -20,7 +20,7 @@ import org.thingsboard.server.common.data.Device; |
20 | 20 | import org.thingsboard.server.common.data.id.DeviceId; |
21 | 21 | import org.thingsboard.server.queue.discovery.PartitionChangeEvent; |
22 | 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 | 26 | * Created by ashvayka on 01.05.18. |
... | ... | @@ -41,6 +41,6 @@ public interface DeviceStateService extends ApplicationListener<PartitionChangeE |
41 | 41 | |
42 | 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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 34 | import org.thingsboard.server.common.data.kv.ReadTsKvQuery; |
35 | 35 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
36 | 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 | 38 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
39 | 39 | import org.thingsboard.server.dao.attributes.AttributesService; |
40 | 40 | import org.thingsboard.server.dao.timeseries.TimeseriesService; |
... | ... | @@ -123,7 +123,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer |
123 | 123 | } |
124 | 124 | |
125 | 125 | @Override |
126 | - public void addSubscription(TbSubscription subscription, TbMsgCallback callback) { | |
126 | + public void addSubscription(TbSubscription subscription, TbCallback callback) { | |
127 | 127 | log.trace("[{}][{}][{}] Registering remote subscription for entity [{}]", |
128 | 128 | subscription.getServiceId(), subscription.getSessionId(), subscription.getSubscriptionId(), subscription.getEntityId()); |
129 | 129 | TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, subscription.getTenantId(), subscription.getEntityId()); |
... | ... | @@ -151,7 +151,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer |
151 | 151 | } |
152 | 152 | |
153 | 153 | @Override |
154 | - public void cancelSubscription(String sessionId, int subscriptionId, TbMsgCallback callback) { | |
154 | + public void cancelSubscription(String sessionId, int subscriptionId, TbCallback callback) { | |
155 | 155 | log.debug("[{}][{}] Going to remove subscription.", sessionId, subscriptionId); |
156 | 156 | Map<Integer, TbSubscription> sessionSubscriptions = subscriptionsByWsSessionId.get(sessionId); |
157 | 157 | if (sessionSubscriptions != null) { |
... | ... | @@ -189,7 +189,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer |
189 | 189 | } |
190 | 190 | |
191 | 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 | 193 | onLocalSubUpdate(entityId, |
194 | 194 | s -> { |
195 | 195 | if (TbSubscriptionType.TIMESERIES.equals(s.getType())) { |
... | ... | @@ -213,7 +213,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer |
213 | 213 | } |
214 | 214 | |
215 | 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 | 217 | onLocalSubUpdate(entityId, |
218 | 218 | s -> { |
219 | 219 | if (TbSubscriptionType.ATTRIBUTES.equals(s.getType())) { |
... | ... | @@ -261,7 +261,7 @@ public class DefaultSubscriptionManagerService implements SubscriptionManagerSer |
261 | 261 | if (subscriptionUpdate != null && !subscriptionUpdate.isEmpty()) { |
262 | 262 | if (serviceId.equals(s.getServiceId())) { |
263 | 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 | 265 | } else { |
266 | 266 | TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, s.getServiceId()); |
267 | 267 | toCoreNotificationsProducer.send(tpi, toProto(s, subscriptionUpdate), null); | ... | ... |
... | ... | @@ -35,7 +35,7 @@ import org.thingsboard.server.queue.discovery.PartitionChangeEvent; |
35 | 35 | import org.thingsboard.server.queue.discovery.PartitionService; |
36 | 36 | import org.thingsboard.server.common.msg.queue.ServiceType; |
37 | 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 | 39 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
40 | 40 | import org.thingsboard.server.queue.util.TbCoreComponent; |
41 | 41 | import org.thingsboard.server.service.telemetry.TelemetryWebSocketService; |
... | ... | @@ -135,7 +135,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer |
135 | 135 | if (currentPartitions.contains(tpi)) { |
136 | 136 | // Subscription is managed on the same server; |
137 | 137 | if (pushToLocalService) { |
138 | - subscriptionManagerService.addSubscription(subscription, TbMsgCallback.EMPTY); | |
138 | + subscriptionManagerService.addSubscription(subscription, TbCallback.EMPTY); | |
139 | 139 | } |
140 | 140 | } else { |
141 | 141 | // Push to the queue; |
... | ... | @@ -145,7 +145,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer |
145 | 145 | } |
146 | 146 | |
147 | 147 | @Override |
148 | - public void onSubscriptionUpdate(String sessionId, SubscriptionUpdate update, TbMsgCallback callback) { | |
148 | + public void onSubscriptionUpdate(String sessionId, SubscriptionUpdate update, TbCallback callback) { | |
149 | 149 | TbSubscription subscription = subscriptionsBySessionId |
150 | 150 | .getOrDefault(sessionId, Collections.emptyMap()).get(update.getSubscriptionId()); |
151 | 151 | if (subscription != null) { |
... | ... | @@ -177,7 +177,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer |
177 | 177 | TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, subscription.getTenantId(), subscription.getEntityId()); |
178 | 178 | if (currentPartitions.contains(tpi)) { |
179 | 179 | // Subscription is managed on the same server; |
180 | - subscriptionManagerService.cancelSubscription(sessionId, subscriptionId, TbMsgCallback.EMPTY); | |
180 | + subscriptionManagerService.cancelSubscription(sessionId, subscriptionId, TbCallback.EMPTY); | |
181 | 181 | } else { |
182 | 182 | // Push to the queue; |
183 | 183 | TransportProtos.ToCoreMsg toCoreMsg = TbSubscriptionUtils.toCloseSubscriptionProto(subscription); | ... | ... |
... | ... | @@ -21,18 +21,18 @@ import org.thingsboard.server.common.data.id.TenantId; |
21 | 21 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
22 | 22 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
23 | 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 | 26 | import java.util.List; |
27 | 27 | |
28 | 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 | 17 | |
18 | 18 | import org.thingsboard.server.queue.discovery.ClusterTopologyChangeEvent; |
19 | 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 | 21 | import org.thingsboard.server.service.telemetry.sub.SubscriptionUpdate; |
22 | 22 | |
23 | 23 | public interface TbLocalSubscriptionService { |
... | ... | @@ -28,7 +28,7 @@ public interface TbLocalSubscriptionService { |
28 | 28 | |
29 | 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 | 33 | void onApplicationEvent(PartitionChangeEvent event); |
34 | 34 | ... | ... |
... | ... | @@ -41,7 +41,7 @@ import org.thingsboard.server.queue.discovery.PartitionChangeEvent; |
41 | 41 | import org.thingsboard.server.queue.discovery.PartitionService; |
42 | 42 | import org.thingsboard.server.common.msg.queue.ServiceType; |
43 | 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 | 45 | import org.thingsboard.server.queue.provider.TbQueueProducerProvider; |
46 | 46 | import org.thingsboard.server.service.subscription.SubscriptionManagerService; |
47 | 47 | import org.thingsboard.server.service.subscription.TbSubscriptionUtils; |
... | ... | @@ -166,7 +166,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio |
166 | 166 | TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId); |
167 | 167 | if (currentPartitions.contains(tpi)) { |
168 | 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 | 170 | } else { |
171 | 171 | log.warn("Possible misconfiguration because subscriptionManagerService is null!"); |
172 | 172 | } |
... | ... | @@ -180,7 +180,7 @@ public class DefaultTelemetrySubscriptionService implements TelemetrySubscriptio |
180 | 180 | TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, entityId); |
181 | 181 | if (currentPartitions.contains(tpi)) { |
182 | 182 | if (subscriptionManagerService.isPresent()) { |
183 | - subscriptionManagerService.get().onTimeSeriesUpdate(tenantId, entityId, ts, TbMsgCallback.EMPTY); | |
183 | + subscriptionManagerService.get().onTimeSeriesUpdate(tenantId, entityId, ts, TbCallback.EMPTY); | |
184 | 184 | } else { |
185 | 185 | log.warn("Possible misconfiguration because subscriptionManagerService is null!"); |
186 | 186 | } | ... | ... |
application/src/main/java/org/thingsboard/server/service/telemetry/TelemetrySubscriptionService.java
... | ... | @@ -17,11 +17,7 @@ package org.thingsboard.server.service.telemetry; |
17 | 17 | |
18 | 18 | import org.springframework.context.ApplicationListener; |
19 | 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 | 20 | import org.thingsboard.server.queue.discovery.PartitionChangeEvent; |
24 | -import org.thingsboard.server.service.telemetry.sub.SubscriptionState; | |
25 | 21 | |
26 | 22 | /** |
27 | 23 | * Created by ashvayka on 27.03.18. | ... | ... |
application/src/main/java/org/thingsboard/server/service/telemetry/sub/Subscription.java
deleted
100644 → 0
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 | 22 | import org.thingsboard.rule.engine.api.RuleChainTransactionService; |
23 | 23 | import org.thingsboard.server.common.data.id.EntityId; |
24 | 24 | import org.thingsboard.server.common.msg.TbMsg; |
25 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | |
26 | 25 | import org.thingsboard.server.queue.util.TbRuleEngineComponent; |
27 | 26 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
28 | 27 | |
... | ... | @@ -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 | 116 | private void addMsgToQueues(BlockingQueue<TbTransactionTask> queue, TbTransactionTask transactionTask) { |
125 | 117 | queue.offer(transactionTask); |
126 | 118 | timeoutQueue.offer(transactionTask); |
... | ... | @@ -230,9 +222,4 @@ public class BaseRuleChainTransactionService implements RuleChainTransactionServ |
230 | 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 | 23 | import org.thingsboard.server.common.msg.aware.DeviceAwareMsg; |
24 | 24 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; |
25 | 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 | 28 | import java.io.Serializable; |
29 | 29 | import java.util.UUID; |
... | ... | @@ -37,9 +37,9 @@ public class TransportToDeviceActorMsgWrapper implements TbActorMsg, DeviceAware |
37 | 37 | private final TenantId tenantId; |
38 | 38 | private final DeviceId deviceId; |
39 | 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 | 43 | this.msg = msg; |
44 | 44 | this.callback = callback; |
45 | 45 | this.tenantId = new TenantId(new UUID(msg.getSessionInfo().getTenantIdMSB(), msg.getSessionInfo().getTenantIdLSB())); | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | |
28 | 28 | <logger name="org.thingsboard.server" level="INFO" /> |
29 | 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 | 33 | <root level="INFO"> |
34 | 34 | <appender-ref ref="STDOUT"/> | ... | ... |
... | ... | @@ -561,7 +561,7 @@ queue: |
561 | 561 | poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}" |
562 | 562 | pack-processing-timeout: "${TB_QUEUE_RULE_ENGINE_PACK_PROCESSING_TIMEOUT_MS:60000}" |
563 | 563 | stats: |
564 | - enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:false}" | |
564 | + enabled: "${TB_QUEUE_RULE_ENGINE_STATS_ENABLED:true}" | |
565 | 565 | print-interval-ms: "${TB_QUEUE_RULE_ENGINE_STATS_PRINT_INTERVAL_MS:10000}" |
566 | 566 | queues: # TODO 2.5: specify correct ENV variable names. |
567 | 567 | - |
... | ... | @@ -577,7 +577,7 @@ queue: |
577 | 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 | 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 | 581 | topic: "${TB_QUEUE_RULE_ENGINE_TOPIC:tb.rule-engine.hp}" |
582 | 582 | poll-interval: "${TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS:25}" |
583 | 583 | partitions: "${TB_QUEUE_RULE_ENGINE_PARTITIONS:3}" |
... | ... | @@ -594,7 +594,7 @@ queue: |
594 | 594 | poll_interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" |
595 | 595 | |
596 | 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 | 598 | # Unique id for this service (autogenerated if empty) |
599 | 599 | id: "${TB_SERVICE_ID:}" |
600 | 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 | 35 | import org.thingsboard.server.common.msg.TbMsg; |
36 | 36 | import org.thingsboard.server.common.msg.TbMsgDataType; |
37 | 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 | 38 | import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; |
41 | 39 | import org.thingsboard.server.dao.attributes.AttributesService; |
42 | 40 | ... | ... |
... | ... | @@ -39,8 +39,6 @@ import org.thingsboard.server.common.data.security.Authority; |
39 | 39 | import org.thingsboard.server.common.msg.TbMsg; |
40 | 40 | import org.thingsboard.server.common.msg.TbMsgDataType; |
41 | 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 | 42 | import org.thingsboard.server.controller.AbstractRuleEngineControllerTest; |
45 | 43 | import org.thingsboard.server.dao.attributes.AttributesService; |
46 | 44 | ... | ... |
... | ... | @@ -34,11 +34,6 @@ public enum MsgType { |
34 | 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 | 37 | * ADDED/UPDATED/DELETED events for main entities. |
43 | 38 | * |
44 | 39 | * See {@link org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg} | ... | ... |
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | * you may not use this file except in compliance with the License. |
6 | 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 | 10 | * Unless required by applicable law or agreed to in writing, software |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
... | ... | @@ -17,7 +17,6 @@ package org.thingsboard.server.common.msg; |
17 | 17 | |
18 | 18 | import com.google.protobuf.ByteString; |
19 | 19 | import com.google.protobuf.InvalidProtocolBufferException; |
20 | -import lombok.AllArgsConstructor; | |
21 | 20 | import lombok.Builder; |
22 | 21 | import lombok.Data; |
23 | 22 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -29,7 +28,6 @@ import org.thingsboard.server.common.msg.gen.MsgProtos; |
29 | 28 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
30 | 29 | |
31 | 30 | import java.io.Serializable; |
32 | -import java.nio.ByteBuffer; | |
33 | 31 | import java.util.UUID; |
34 | 32 | |
35 | 33 | /** | ... | ... |
... | ... | @@ -33,6 +33,7 @@ public final class QueueToRuleEngineMsg implements TbActorMsg { |
33 | 33 | private final TenantId tenantId; |
34 | 34 | private final TbMsg tbMsg; |
35 | 35 | private final Set<String> relationTypes; |
36 | + private final String failureMessage; | |
36 | 37 | |
37 | 38 | @Override |
38 | 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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | } | ... | ... |
common/message/src/main/java/org/thingsboard/server/common/msg/queue/RuleNodeException.java
0 → 100644
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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 25 | } |
26 | 26 | |
27 | 27 | @Override |
28 | - public void onFailure(Throwable t) { | |
28 | + public void onFailure(RuleEngineException e) { | |
29 | 29 | |
30 | 30 | } |
31 | 31 | }; |
32 | 32 | |
33 | 33 | void onSuccess(); |
34 | 34 | |
35 | - void onFailure(Throwable t); | |
35 | + void onFailure(RuleEngineException e); | |
36 | 36 | |
37 | 37 | } | ... | ... |
... | ... | @@ -15,6 +15,8 @@ |
15 | 15 | */ |
16 | 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 | 20 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
19 | 21 | import org.thingsboard.server.queue.TbQueueCallback; |
20 | 22 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
... | ... | @@ -40,6 +42,6 @@ public class MultipleTbQueueTbMsgCallbackWrapper implements TbQueueCallback { |
40 | 42 | |
41 | 43 | @Override |
42 | 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 | 15 | */ |
16 | 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 | 20 | import org.thingsboard.server.common.msg.queue.TbMsgCallback; |
19 | 21 | import org.thingsboard.server.queue.TbQueueCallback; |
20 | 22 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
21 | 23 | |
22 | -import java.util.concurrent.atomic.AtomicInteger; | |
23 | - | |
24 | 24 | public class TbQueueTbMsgCallbackWrapper implements TbQueueCallback { |
25 | 25 | |
26 | 26 | private final TbMsgCallback tbMsgCallback; |
... | ... | @@ -36,6 +36,6 @@ public class TbQueueTbMsgCallbackWrapper implements TbQueueCallback { |
36 | 36 | |
37 | 37 | @Override |
38 | 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 | 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 | 89 | @Override |
108 | 90 | public TopicPartitionInfo resolve(ServiceType serviceType, TenantId tenantId, EntityId entityId) { |
109 | 91 | return resolve(new ServiceQueue(serviceType), tenantId, entityId); |
... | ... | @@ -131,15 +113,7 @@ public class ConsistentHashPartitionService implements PartitionService { |
131 | 113 | Map<ServiceQueueKey, ConsistentHashCircle<ServiceInfo>> circles = new HashMap<>(); |
132 | 114 | addNode(circles, currentService); |
133 | 115 | for (ServiceInfo other : otherServices) { |
134 | - TenantId tenantId = getSystemOrIsolatedTenantId(other); | |
135 | 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 | 118 | ConcurrentMap<ServiceQueueKey, List<Integer>> oldPartitions = myPartitions; |
145 | 119 | TenantId myTenantId = getSystemOrIsolatedTenantId(currentService); |
... | ... | @@ -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 | 196 | private Map<ServiceQueueKey, List<ServiceInfo>> getServiceKeyListMap(List<ServiceInfo> services) { |
218 | 197 | final Map<ServiceQueueKey, List<ServiceInfo>> currentMap = new HashMap<>(); |
219 | 198 | services.forEach(serviceInfo -> { |
... | ... | @@ -280,6 +259,12 @@ public class ConsistentHashPartitionService implements PartitionService { |
280 | 259 | |
281 | 260 | private void addNode(Map<ServiceQueueKey, ConsistentHashCircle<ServiceInfo>> circles, ServiceInfo instance) { |
282 | 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 | 268 | for (String serviceTypeStr : instance.getServiceTypesList()) { |
284 | 269 | ServiceType serviceType = ServiceType.valueOf(serviceTypeStr.toUpperCase()); |
285 | 270 | if (ServiceType.TB_RULE_ENGINE.equals(serviceType)) { | ... | ... |
... | ... | @@ -34,6 +34,7 @@ import java.net.UnknownHostException; |
34 | 34 | import java.util.Arrays; |
35 | 35 | import java.util.Collections; |
36 | 36 | import java.util.List; |
37 | +import java.util.Optional; | |
37 | 38 | import java.util.UUID; |
38 | 39 | import java.util.stream.Collectors; |
39 | 40 | |
... | ... | @@ -58,6 +59,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { |
58 | 59 | |
59 | 60 | private List<ServiceType> serviceTypes; |
60 | 61 | private ServiceInfo serviceInfo; |
62 | + private TenantId isolatedTenant; | |
61 | 63 | |
62 | 64 | @PostConstruct |
63 | 65 | public void init() { |
... | ... | @@ -80,6 +82,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { |
80 | 82 | UUID tenantId; |
81 | 83 | if (!StringUtils.isEmpty(tenantIdStr)) { |
82 | 84 | tenantId = UUID.fromString(tenantIdStr); |
85 | + isolatedTenant = new TenantId(tenantId); | |
83 | 86 | } else { |
84 | 87 | tenantId = TenantId.NULL_UUID; |
85 | 88 | } |
... | ... | @@ -103,4 +106,14 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { |
103 | 106 | public ServiceInfo getServiceInfo() { |
104 | 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 | 47 | */ |
48 | 48 | Set<String> getAllServiceIds(ServiceType serviceType); |
49 | 49 | |
50 | + Set<TenantId> getIsolatedTenants(ServiceType serviceType); | |
51 | + | |
50 | 52 | /** |
51 | 53 | * Each Service should start a consumer for messages that target individual service instance based on serviceId. |
52 | 54 | * This topic is likely to have single partition, and is always assigned to the service. | ... | ... |
... | ... | @@ -15,12 +15,20 @@ |
15 | 15 | */ |
16 | 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 | 20 | import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; |
19 | 21 | |
22 | +import java.util.Optional; | |
23 | + | |
20 | 24 | public interface TbServiceInfoProvider { |
21 | 25 | |
22 | 26 | String getServiceId(); |
23 | 27 | |
24 | 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 | 17 | |
18 | 18 | import lombok.Data; |
19 | 19 | import lombok.extern.slf4j.Slf4j; |
20 | +import org.springframework.beans.factory.annotation.Autowired; | |
20 | 21 | import org.springframework.beans.factory.annotation.Value; |
22 | +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | |
21 | 23 | import org.springframework.boot.context.properties.ConfigurationProperties; |
22 | 24 | import org.springframework.context.annotation.Configuration; |
23 | 25 | |
... | ... | @@ -26,6 +28,7 @@ import java.util.List; |
26 | 28 | |
27 | 29 | @Slf4j |
28 | 30 | @Data |
31 | +@EnableAutoConfiguration | |
29 | 32 | @Configuration |
30 | 33 | @ConfigurationProperties(prefix = "queue.rule-engine") |
31 | 34 | public class TbQueueRuleEngineSettings { | ... | ... |
... | ... | @@ -16,7 +16,6 @@ |
16 | 16 | package org.thingsboard.rule.engine.api; |
17 | 17 | |
18 | 18 | import org.thingsboard.server.common.msg.TbMsg; |
19 | -import org.thingsboard.server.common.msg.cluster.ServerAddress; | |
20 | 19 | |
21 | 20 | import java.util.function.Consumer; |
22 | 21 | |
... | ... | @@ -26,6 +25,4 @@ public interface RuleChainTransactionService { |
26 | 25 | |
27 | 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 | 26 | import org.thingsboard.server.common.data.id.EntityId; |
27 | 27 | import org.thingsboard.server.common.data.id.RuleNodeId; |
28 | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | -import org.thingsboard.server.common.data.rule.RuleNode; | |
30 | 29 | import org.thingsboard.server.common.msg.TbMsg; |
31 | 30 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
32 | -import org.thingsboard.server.common.msg.queue.TbMsgCallback; | |
33 | 31 | import org.thingsboard.server.dao.alarm.AlarmService; |
34 | 32 | import org.thingsboard.server.dao.asset.AssetService; |
35 | 33 | import org.thingsboard.server.dao.attributes.AttributesService; |
... | ... | @@ -116,6 +114,8 @@ public interface TbContext { |
116 | 114 | */ |
117 | 115 | void enqueue(TbMsg msg, String queueName, Runnable onSuccess, Consumer<Throwable> onFailure); |
118 | 116 | |
117 | + void enqueueForTellFailure(TbMsg msg, String failureMessage); | |
118 | + | |
119 | 119 | void enqueueForTellNext(TbMsg msg, String relationType); |
120 | 120 | |
121 | 121 | void enqueueForTellNext(TbMsg msg, Set<String> relationTypes); | ... | ... |
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java
0 → 100644
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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 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 | 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 | 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 | 116 | ctx.enqueueForTellNext(next, TbRelationTypes.SUCCESS); |
117 | 117 | } else { |
118 | 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 | 122 | ctx.ack(msg); | ... | ... |
... | ... | @@ -102,20 +102,44 @@ queue: |
102 | 102 | stats: |
103 | 103 | enabled: "${TB_QUEUE_CORE_STATS_ENABLED:false}" |
104 | 104 | print_interval_ms: "${TB_QUEUE_CORE_STATS_PRINT_INTERVAL_MS:10000}" |
105 | - rule_engine: | |
105 | + rule-engine: | |
106 | 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 | 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 | 137 | transport: |
114 | 138 | notifications_topic: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_TOPIC:tb.transport.notifications}" |
115 | 139 | poll_interval: "${TB_QUEUE_CORE_POLL_INTERVAL_MS:25}" |
116 | 140 | |
117 | 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 | 143 | # Unique id for this service (autogenerated if empty) |
120 | 144 | id: "${TB_SERVICE_ID:}" |
121 | 145 | tenant_id: "${TB_SERVICE_TENANT_ID:}" # empty or specific tenant id. |
\ No newline at end of file | ... | ... |