Commit 193cccf1232d9d3117f98cb03bde603c396aa3ed
1 parent
36f6ad2a
Refactored Edge session message poll mechanism. Removed tech dept - Integer.MAX_…
…INTEGER. Code refactoring
Showing
25 changed files
with
448 additions
and
116 deletions
@@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | @@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | ||
34 | import org.thingsboard.server.common.msg.MsgType; | 34 | import org.thingsboard.server.common.msg.MsgType; |
35 | import org.thingsboard.server.common.msg.TbActorMsg; | 35 | import org.thingsboard.server.common.msg.TbActorMsg; |
36 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; | 36 | import org.thingsboard.server.common.msg.aware.TenantAwareMsg; |
37 | +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; | ||
37 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 38 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
38 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | 39 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; |
39 | import org.thingsboard.server.common.msg.queue.RuleEngineException; | 40 | import org.thingsboard.server.common.msg.queue.RuleEngineException; |
@@ -93,6 +94,9 @@ public class AppActor extends ContextAwareActor { | @@ -93,6 +94,9 @@ public class AppActor extends ContextAwareActor { | ||
93 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: | 94 | case SERVER_RPC_RESPONSE_TO_DEVICE_ACTOR_MSG: |
94 | onToDeviceActorMsg((TenantAwareMsg) msg, true); | 95 | onToDeviceActorMsg((TenantAwareMsg) msg, true); |
95 | break; | 96 | break; |
97 | + case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG: | ||
98 | + onToTenantActorMsg((EdgeEventUpdateMsg) msg); | ||
99 | + break; | ||
96 | default: | 100 | default: |
97 | return false; | 101 | return false; |
98 | } | 102 | } |
@@ -186,6 +190,20 @@ public class AppActor extends ContextAwareActor { | @@ -186,6 +190,20 @@ public class AppActor extends ContextAwareActor { | ||
186 | () -> new TenantActor.ActorCreator(systemContext, tenantId)); | 190 | () -> new TenantActor.ActorCreator(systemContext, tenantId)); |
187 | } | 191 | } |
188 | 192 | ||
193 | + private void onToTenantActorMsg(EdgeEventUpdateMsg msg) { | ||
194 | + TbActorRef target = null; | ||
195 | + if (SYSTEM_TENANT.equals(msg.getTenantId())) { | ||
196 | + log.warn("Message has system tenant id: {}", msg); | ||
197 | + } else { | ||
198 | + target = getOrCreateTenantActor(msg.getTenantId()); | ||
199 | + } | ||
200 | + if (target != null) { | ||
201 | + target.tellWithHighPriority(msg); | ||
202 | + } else { | ||
203 | + log.debug("[{}] Invalid edge event update msg: {}", msg.getTenantId(), msg); | ||
204 | + } | ||
205 | + } | ||
206 | + | ||
189 | public static class ActorCreator extends ContextBasedCreator { | 207 | public static class ActorCreator extends ContextBasedCreator { |
190 | 208 | ||
191 | public ActorCreator(ActorSystemContext context) { | 209 | public ActorCreator(ActorSystemContext context) { |
@@ -145,8 +145,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -145,8 +145,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
145 | if (result != null && result.size() > 0) { | 145 | if (result != null && result.size() > 0) { |
146 | EntityRelation relationToEdge = result.get(0); | 146 | EntityRelation relationToEdge = result.get(0); |
147 | if (relationToEdge.getFrom() != null && relationToEdge.getFrom().getId() != null) { | 147 | if (relationToEdge.getFrom() != null && relationToEdge.getFrom().getId() != null) { |
148 | + log.trace("[{}][{}] found edge [{}] for device", tenantId, deviceId, relationToEdge.getFrom().getId()); | ||
148 | return new EdgeId(relationToEdge.getFrom().getId()); | 149 | return new EdgeId(relationToEdge.getFrom().getId()); |
150 | + } else { | ||
151 | + log.trace("[{}][{}] edge relation is empty {}", tenantId, deviceId, relationToEdge); | ||
149 | } | 152 | } |
153 | + } else { | ||
154 | + log.trace("[{}][{}] device doesn't have any related edge", tenantId, deviceId); | ||
150 | } | 155 | } |
151 | return null; | 156 | return null; |
152 | } | 157 | } |
@@ -165,6 +170,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -165,6 +170,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
165 | 170 | ||
166 | boolean sent; | 171 | boolean sent; |
167 | if (systemContext.isEdgesRpcEnabled() && edgeId != null) { | 172 | if (systemContext.isEdgesRpcEnabled() && edgeId != null) { |
173 | + log.debug("[{}][{}] device is related to edge [{}]. Saving RPC request to edge queue", tenantId, deviceId, edgeId.getId()); | ||
168 | saveRpcRequestToEdgeQueue(request, rpcRequest.getRequestId()); | 174 | saveRpcRequestToEdgeQueue(request, rpcRequest.getRequestId()); |
169 | sent = true; | 175 | sent = true; |
170 | } else { | 176 | } else { |
@@ -516,6 +522,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -516,6 +522,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
516 | } | 522 | } |
517 | 523 | ||
518 | void processEdgeUpdate(DeviceEdgeUpdateMsg msg) { | 524 | void processEdgeUpdate(DeviceEdgeUpdateMsg msg) { |
525 | + log.trace("[{}] Processing edge update {}", deviceId, msg); | ||
519 | this.edgeId = msg.getEdgeId(); | 526 | this.edgeId = msg.getEdgeId(); |
520 | } | 527 | } |
521 | 528 | ||
@@ -568,7 +575,18 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | @@ -568,7 +575,18 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { | ||
568 | edgeEvent.setBody(body); | 575 | edgeEvent.setBody(body); |
569 | 576 | ||
570 | edgeEvent.setEdgeId(edgeId); | 577 | edgeEvent.setEdgeId(edgeId); |
571 | - systemContext.getEdgeEventService().saveAsync(edgeEvent); | 578 | + ListenableFuture<EdgeEvent> future = systemContext.getEdgeEventService().saveAsync(edgeEvent); |
579 | + Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | ||
580 | + @Override | ||
581 | + public void onSuccess( EdgeEvent result) { | ||
582 | + systemContext.getClusterService().onEdgeEventUpdate(tenantId, edgeId); | ||
583 | + } | ||
584 | + | ||
585 | + @Override | ||
586 | + public void onFailure(Throwable t) { | ||
587 | + log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | ||
588 | + } | ||
589 | + }, systemContext.getDbCallbackExecutor()); | ||
572 | } | 590 | } |
573 | 591 | ||
574 | private List<TsKvProto> toTsKvProtos(@Nullable List<AttributeKvEntry> result) { | 592 | private List<TsKvProto> toTsKvProtos(@Nullable List<AttributeKvEntry> result) { |
@@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.DataConstants; | @@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.DataConstants; | ||
36 | import org.thingsboard.server.common.data.Device; | 36 | import org.thingsboard.server.common.data.Device; |
37 | import org.thingsboard.server.common.data.alarm.Alarm; | 37 | import org.thingsboard.server.common.data.alarm.Alarm; |
38 | import org.thingsboard.server.common.data.asset.Asset; | 38 | import org.thingsboard.server.common.data.asset.Asset; |
39 | +import org.thingsboard.server.common.data.id.EdgeId; | ||
39 | import org.thingsboard.server.common.data.id.EntityId; | 40 | import org.thingsboard.server.common.data.id.EntityId; |
40 | import org.thingsboard.server.common.data.id.RuleChainId; | 41 | import org.thingsboard.server.common.data.id.RuleChainId; |
41 | import org.thingsboard.server.common.data.id.RuleNodeId; | 42 | import org.thingsboard.server.common.data.id.RuleNodeId; |
@@ -269,6 +270,11 @@ class DefaultTbContext implements TbContext { | @@ -269,6 +270,11 @@ class DefaultTbContext implements TbContext { | ||
269 | return entityActionMsg(alarm, alarm.getId(), ruleNodeId, action); | 270 | return entityActionMsg(alarm, alarm.getId(), ruleNodeId, action); |
270 | } | 271 | } |
271 | 272 | ||
273 | + @Override | ||
274 | + public void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId) { | ||
275 | + mainCtx.getClusterService().onEdgeEventUpdate(tenantId, edgeId); | ||
276 | + } | ||
277 | + | ||
272 | public <E, I extends EntityId> TbMsg entityActionMsg(E entity, I id, RuleNodeId ruleNodeId, String action) { | 278 | public <E, I extends EntityId> TbMsg entityActionMsg(E entity, I id, RuleNodeId ruleNodeId, String action) { |
273 | try { | 279 | try { |
274 | return TbMsg.newMsg(action, id, getActionMetaData(ruleNodeId), mapper.writeValueAsString(mapper.valueToTree(entity))); | 280 | return TbMsg.newMsg(action, id, getActionMetaData(ruleNodeId), mapper.writeValueAsString(mapper.valueToTree(entity))); |
@@ -45,6 +45,7 @@ import org.thingsboard.server.common.msg.TbActorMsg; | @@ -45,6 +45,7 @@ import org.thingsboard.server.common.msg.TbActorMsg; | ||
45 | import org.thingsboard.server.common.msg.TbMsg; | 45 | import org.thingsboard.server.common.msg.TbMsg; |
46 | import org.thingsboard.server.common.msg.aware.DeviceAwareMsg; | 46 | import org.thingsboard.server.common.msg.aware.DeviceAwareMsg; |
47 | import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg; | 47 | import org.thingsboard.server.common.msg.aware.RuleChainAwareMsg; |
48 | +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; | ||
48 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 49 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
49 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; | 50 | import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; |
50 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; | 51 | import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; |
@@ -157,6 +158,9 @@ public class TenantActor extends RuleChainManagerActor { | @@ -157,6 +158,9 @@ public class TenantActor extends RuleChainManagerActor { | ||
157 | case RULE_CHAIN_TO_RULE_CHAIN_MSG: | 158 | case RULE_CHAIN_TO_RULE_CHAIN_MSG: |
158 | onRuleChainMsg((RuleChainAwareMsg) msg); | 159 | onRuleChainMsg((RuleChainAwareMsg) msg); |
159 | break; | 160 | break; |
161 | + case EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG: | ||
162 | + onToEdgeSessionMsg((EdgeEventUpdateMsg) msg); | ||
163 | + break; | ||
160 | default: | 164 | default: |
161 | return false; | 165 | return false; |
162 | } | 166 | } |
@@ -242,6 +246,11 @@ public class TenantActor extends RuleChainManagerActor { | @@ -242,6 +246,11 @@ public class TenantActor extends RuleChainManagerActor { | ||
242 | () -> new DeviceActorCreator(systemContext, tenantId, deviceId)); | 246 | () -> new DeviceActorCreator(systemContext, tenantId, deviceId)); |
243 | } | 247 | } |
244 | 248 | ||
249 | + private void onToEdgeSessionMsg(EdgeEventUpdateMsg msg) { | ||
250 | + log.trace("[{}] onToEdgeSessionMsg [{}]", msg.getTenantId(), msg); | ||
251 | + systemContext.getEdgeRpcService().onEdgeEvent(msg.getEdgeId()); | ||
252 | + } | ||
253 | + | ||
245 | public static class ActorCreator extends ContextBasedCreator { | 254 | public static class ActorCreator extends ContextBasedCreator { |
246 | 255 | ||
247 | private final TenantId tenantId; | 256 | private final TenantId tenantId; |
@@ -832,6 +832,7 @@ public abstract class BaseController { | @@ -832,6 +832,7 @@ public abstract class BaseController { | ||
832 | builder.setBody(body); | 832 | builder.setBody(body); |
833 | } | 833 | } |
834 | TransportProtos.EdgeNotificationMsgProto msg = builder.build(); | 834 | TransportProtos.EdgeNotificationMsgProto msg = builder.build(); |
835 | + log.trace("[{}] sending notification to edge service {}", tenantId.getId(), msg); | ||
835 | tbClusterService.pushMsgToCore(tenantId, entityId != null ? entityId : tenantId, | 836 | tbClusterService.pushMsgToCore(tenantId, entityId != null ? entityId : tenantId, |
836 | TransportProtos.ToCoreMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null); | 837 | TransportProtos.ToCoreMsg.newBuilder().setEdgeNotificationMsg(msg).build(), null); |
837 | } | 838 | } |
@@ -251,12 +251,11 @@ public class RuleChainController extends BaseController { | @@ -251,12 +251,11 @@ public class RuleChainController extends BaseController { | ||
251 | try { | 251 | try { |
252 | TenantId tenantId = getCurrentUser().getTenantId(); | 252 | TenantId tenantId = getCurrentUser().getTenantId(); |
253 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 253 | TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); |
254 | + RuleChainType type = RuleChainType.CORE; | ||
254 | if (typeStr != null && typeStr.trim().length() > 0) { | 255 | if (typeStr != null && typeStr.trim().length() > 0) { |
255 | - RuleChainType type = RuleChainType.valueOf(typeStr); | ||
256 | - return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink)); | ||
257 | - } else { | ||
258 | - return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, pageLink)); | 256 | + type = RuleChainType.valueOf(typeStr); |
259 | } | 257 | } |
258 | + return checkNotNull(ruleChainService.findTenantRuleChainsByType(tenantId, type, pageLink)); | ||
260 | } catch (Exception e) { | 259 | } catch (Exception e) { |
261 | throw handleException(e); | 260 | throw handleException(e); |
262 | } | 261 | } |
@@ -55,6 +55,7 @@ import org.thingsboard.server.dao.user.UserService; | @@ -55,6 +55,7 @@ import org.thingsboard.server.dao.user.UserService; | ||
55 | import org.thingsboard.server.gen.transport.TransportProtos; | 55 | import org.thingsboard.server.gen.transport.TransportProtos; |
56 | import org.thingsboard.server.queue.util.TbCoreComponent; | 56 | import org.thingsboard.server.queue.util.TbCoreComponent; |
57 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; | 57 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
58 | +import org.thingsboard.server.service.queue.TbClusterService; | ||
58 | 59 | ||
59 | import javax.annotation.PostConstruct; | 60 | import javax.annotation.PostConstruct; |
60 | import javax.annotation.PreDestroy; | 61 | import javax.annotation.PreDestroy; |
@@ -74,6 +75,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -74,6 +75,8 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
74 | 75 | ||
75 | private static final ObjectMapper mapper = new ObjectMapper(); | 76 | private static final ObjectMapper mapper = new ObjectMapper(); |
76 | 77 | ||
78 | + private static final int DEFAULT_LIMIT = 100; | ||
79 | + | ||
77 | @Autowired | 80 | @Autowired |
78 | private EdgeService edgeService; | 81 | private EdgeService edgeService; |
79 | 82 | ||
@@ -90,6 +93,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -90,6 +93,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
90 | private EdgeEventService edgeEventService; | 93 | private EdgeEventService edgeEventService; |
91 | 94 | ||
92 | @Autowired | 95 | @Autowired |
96 | + private TbClusterService clusterService; | ||
97 | + | ||
98 | + @Autowired | ||
93 | private DbCallbackExecutorService dbCallbackExecutorService; | 99 | private DbCallbackExecutorService dbCallbackExecutorService; |
94 | 100 | ||
95 | private ExecutorService tsCallBackExecutor; | 101 | private ExecutorService tsCallBackExecutor; |
@@ -137,7 +143,19 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -137,7 +143,19 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
137 | edgeEvent.setEntityId(entityId.getId()); | 143 | edgeEvent.setEntityId(entityId.getId()); |
138 | } | 144 | } |
139 | edgeEvent.setBody(body); | 145 | edgeEvent.setBody(body); |
140 | - edgeEventService.saveAsync(edgeEvent); | 146 | + ListenableFuture<EdgeEvent> future = edgeEventService.saveAsync(edgeEvent); |
147 | + Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | ||
148 | + @Override | ||
149 | + public void onSuccess(@Nullable EdgeEvent result) { | ||
150 | + clusterService.onEdgeEventUpdate(tenantId, edgeId); | ||
151 | + } | ||
152 | + | ||
153 | + @Override | ||
154 | + public void onFailure(Throwable t) { | ||
155 | + log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | ||
156 | + } | ||
157 | + }, dbCallbackExecutorService); | ||
158 | + | ||
141 | } | 159 | } |
142 | 160 | ||
143 | @Override | 161 | @Override |
@@ -195,13 +213,20 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -195,13 +213,20 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
195 | public void onSuccess(@Nullable Edge edge) { | 213 | public void onSuccess(@Nullable Edge edge) { |
196 | if (edge != null && !customerId.isNullUid()) { | 214 | if (edge != null && !customerId.isNullUid()) { |
197 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null); | 215 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null); |
198 | - TextPageData<User> pageData = userService.findCustomerUsers(tenantId, customerId, new TextPageLink(Integer.MAX_VALUE)); | ||
199 | - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
200 | - log.trace("[{}] [{}] user(s) are going to be added to edge.", edge.getId(), pageData.getData().size()); | ||
201 | - for (User user : pageData.getData()) { | ||
202 | - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, EdgeEventActionType.ADDED, user.getId(), null); | 216 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); |
217 | + TextPageData<User> pageData; | ||
218 | + do { | ||
219 | + pageData = userService.findCustomerUsers(tenantId, customerId, pageLink); | ||
220 | + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
221 | + log.trace("[{}] [{}] user(s) are going to be added to edge.", edge.getId(), pageData.getData().size()); | ||
222 | + for (User user : pageData.getData()) { | ||
223 | + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, EdgeEventActionType.ADDED, user.getId(), null); | ||
224 | + } | ||
225 | + if (pageData.hasNext()) { | ||
226 | + pageLink = pageData.getNextPageLink(); | ||
227 | + } | ||
203 | } | 228 | } |
204 | - } | 229 | + } while (pageData != null && pageData.hasNext()); |
205 | } | 230 | } |
206 | } | 231 | } |
207 | 232 | ||
@@ -242,12 +267,19 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -242,12 +267,19 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
242 | case ADDED: | 267 | case ADDED: |
243 | case UPDATED: | 268 | case UPDATED: |
244 | case DELETED: | 269 | case DELETED: |
245 | - TextPageData<Edge> edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); | ||
246 | - if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { | ||
247 | - for (Edge edge : edgesByTenantId.getData()) { | ||
248 | - saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | 270 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); |
271 | + TextPageData<Edge> pageData; | ||
272 | + do { | ||
273 | + pageData = edgeService.findEdgesByTenantId(tenantId, pageLink); | ||
274 | + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
275 | + for (Edge edge : pageData.getData()) { | ||
276 | + saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | ||
277 | + } | ||
278 | + if (pageData.hasNext()) { | ||
279 | + pageLink = pageData.getNextPageLink(); | ||
280 | + } | ||
249 | } | 281 | } |
250 | - } | 282 | + } while (pageData != null && pageData.hasNext()); |
251 | break; | 283 | break; |
252 | } | 284 | } |
253 | } | 285 | } |
@@ -256,21 +288,28 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -256,21 +288,28 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
256 | EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); | 288 | EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); |
257 | EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); | 289 | EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); |
258 | EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); | 290 | EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); |
259 | - TextPageData<Edge> edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); | ||
260 | - if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { | ||
261 | - for (Edge edge : edgesByTenantId.getData()) { | ||
262 | - switch (actionType) { | ||
263 | - case UPDATED: | ||
264 | - if (!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(entityId)) { | 291 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); |
292 | + TextPageData<Edge> pageData; | ||
293 | + do { | ||
294 | + pageData = edgeService.findEdgesByTenantId(tenantId, pageLink); | ||
295 | + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
296 | + for (Edge edge : pageData.getData()) { | ||
297 | + switch (actionType) { | ||
298 | + case UPDATED: | ||
299 | + if (!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(entityId)) { | ||
300 | + saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | ||
301 | + } | ||
302 | + break; | ||
303 | + case DELETED: | ||
265 | saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | 304 | saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); |
266 | - } | ||
267 | - break; | ||
268 | - case DELETED: | ||
269 | - saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | ||
270 | - break; | 305 | + break; |
306 | + } | ||
307 | + } | ||
308 | + if (pageData.hasNext()) { | ||
309 | + pageLink = pageData.getNextPageLink(); | ||
271 | } | 310 | } |
272 | } | 311 | } |
273 | - } | 312 | + } while (pageData != null && pageData.hasNext()); |
274 | } | 313 | } |
275 | 314 | ||
276 | private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { | 315 | private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { |
@@ -337,26 +376,33 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -337,26 +376,33 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
337 | }, dbCallbackExecutorService); | 376 | }, dbCallbackExecutorService); |
338 | break; | 377 | break; |
339 | case DELETED: | 378 | case DELETED: |
340 | - TextPageData<Edge> edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); | ||
341 | - if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) { | ||
342 | - for (Edge edge : edgesByTenantId.getData()) { | ||
343 | - saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | 379 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); |
380 | + TextPageData<Edge> pageData; | ||
381 | + do { | ||
382 | + pageData = edgeService.findEdgesByTenantId(tenantId, pageLink); | ||
383 | + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
384 | + for (Edge edge : pageData.getData()) { | ||
385 | + saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); | ||
386 | + } | ||
387 | + if (pageData.hasNext()) { | ||
388 | + pageLink = pageData.getNextPageLink(); | ||
389 | + } | ||
344 | } | 390 | } |
345 | - } | 391 | + } while (pageData != null && pageData.hasNext()); |
346 | break; | 392 | break; |
347 | case ASSIGNED_TO_EDGE: | 393 | case ASSIGNED_TO_EDGE: |
348 | case UNASSIGNED_FROM_EDGE: | 394 | case UNASSIGNED_FROM_EDGE: |
349 | EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); | 395 | EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); |
350 | saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); | 396 | saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); |
351 | if (type.equals(EdgeEventType.RULE_CHAIN)) { | 397 | if (type.equals(EdgeEventType.RULE_CHAIN)) { |
352 | - updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId); | 398 | + updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId, new TimePageLink(DEFAULT_LIMIT)); |
353 | } | 399 | } |
354 | break; | 400 | break; |
355 | } | 401 | } |
356 | } | 402 | } |
357 | 403 | ||
358 | - private void updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) { | ||
359 | - ListenableFuture<TimePageData<RuleChain>> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, new TimePageLink(Integer.MAX_VALUE)); | 404 | + private void updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId, TimePageLink pageLink) { |
405 | + ListenableFuture<TimePageData<RuleChain>> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); | ||
360 | Futures.addCallback(future, new FutureCallback<TimePageData<RuleChain>>() { | 406 | Futures.addCallback(future, new FutureCallback<TimePageData<RuleChain>>() { |
361 | @Override | 407 | @Override |
362 | public void onSuccess(@Nullable TimePageData<RuleChain> pageData) { | 408 | public void onSuccess(@Nullable TimePageData<RuleChain> pageData) { |
@@ -379,6 +425,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | @@ -379,6 +425,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { | ||
379 | } | 425 | } |
380 | } | 426 | } |
381 | } | 427 | } |
428 | + if (pageData.hasNext()) { | ||
429 | + updateDependentRuleChains(tenantId, processingRuleChainId, edgeId, pageData.getNextPageLink()); | ||
430 | + } | ||
382 | } | 431 | } |
383 | } | 432 | } |
384 | 433 |
@@ -49,6 +49,7 @@ import java.io.IOException; | @@ -49,6 +49,7 @@ import java.io.IOException; | ||
49 | import java.util.Collections; | 49 | import java.util.Collections; |
50 | import java.util.Map; | 50 | import java.util.Map; |
51 | import java.util.concurrent.ConcurrentHashMap; | 51 | import java.util.concurrent.ConcurrentHashMap; |
52 | +import java.util.concurrent.ConcurrentMap; | ||
52 | import java.util.concurrent.ExecutorService; | 53 | import java.util.concurrent.ExecutorService; |
53 | import java.util.concurrent.Executors; | 54 | import java.util.concurrent.Executors; |
54 | import java.util.concurrent.TimeUnit; | 55 | import java.util.concurrent.TimeUnit; |
@@ -59,7 +60,8 @@ import java.util.concurrent.TimeUnit; | @@ -59,7 +60,8 @@ import java.util.concurrent.TimeUnit; | ||
59 | @TbCoreComponent | 60 | @TbCoreComponent |
60 | public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { | 61 | public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService { |
61 | 62 | ||
62 | - private final Map<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>(); | 63 | + private final ConcurrentMap<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>(); |
64 | + private final ConcurrentMap<EdgeId, Boolean> sessionNewEvents = new ConcurrentHashMap<>(); | ||
63 | private static final ObjectMapper mapper = new ObjectMapper(); | 65 | private static final ObjectMapper mapper = new ObjectMapper(); |
64 | 66 | ||
65 | @Value("${edges.rpc.port}") | 67 | @Value("${edges.rpc.port}") |
@@ -147,12 +149,23 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -147,12 +149,23 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
147 | log.debug("Closing and removing session for edge [{}]", edgeId); | 149 | log.debug("Closing and removing session for edge [{}]", edgeId); |
148 | session.close(); | 150 | session.close(); |
149 | sessions.remove(edgeId); | 151 | sessions.remove(edgeId); |
152 | + sessionNewEvents.remove(edgeId); | ||
153 | + } | ||
154 | + } | ||
155 | + | ||
156 | + @Override | ||
157 | + public void onEdgeEvent(EdgeId edgeId) { | ||
158 | + log.trace("[{}] onEdgeEvent", edgeId.getId()); | ||
159 | + if (!sessionNewEvents.get(edgeId)) { | ||
160 | + log.trace("[{}] set session new events flag to true", edgeId.getId()); | ||
161 | + sessionNewEvents.put(edgeId, true); | ||
150 | } | 162 | } |
151 | } | 163 | } |
152 | 164 | ||
153 | private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { | 165 | private void onEdgeConnect(EdgeId edgeId, EdgeGrpcSession edgeGrpcSession) { |
154 | log.debug("[{}] onEdgeConnect [{}]", edgeId, edgeGrpcSession.getSessionId()); | 166 | log.debug("[{}] onEdgeConnect [{}]", edgeId, edgeGrpcSession.getSessionId()); |
155 | sessions.put(edgeId, edgeGrpcSession); | 167 | sessions.put(edgeId, edgeGrpcSession); |
168 | + sessionNewEvents.put(edgeId, false); | ||
156 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true); | 169 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true); |
157 | save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, System.currentTimeMillis()); | 170 | save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, System.currentTimeMillis()); |
158 | } | 171 | } |
@@ -171,15 +184,23 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -171,15 +184,23 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
171 | while (!Thread.interrupted()) { | 184 | while (!Thread.interrupted()) { |
172 | try { | 185 | try { |
173 | if (sessions.size() > 0) { | 186 | if (sessions.size() > 0) { |
174 | - for (EdgeGrpcSession session : sessions.values()) { | ||
175 | - session.processHandleMessages(); | 187 | + for (Map.Entry<EdgeId, EdgeGrpcSession> entry : sessions.entrySet()) { |
188 | + EdgeId edgeId = entry.getKey(); | ||
189 | + EdgeGrpcSession session = entry.getValue(); | ||
190 | + if (sessionNewEvents.get(edgeId)) { | ||
191 | + log.trace("[{}] set session new events flag to false", edgeId.getId()); | ||
192 | + sessionNewEvents.put(edgeId, false); | ||
193 | + // TODO: voba - at the moment all edge events are processed in a single thread. Maybe this should be updated? | ||
194 | + session.processHandleMessages(); | ||
195 | + } | ||
176 | } | 196 | } |
177 | } else { | 197 | } else { |
178 | - log.trace("No sessions available, sleep for the next run"); | ||
179 | - try { | ||
180 | - Thread.sleep(1000); | ||
181 | - } catch (InterruptedException ignore) { | ||
182 | - } | 198 | + log.trace("No sessions available"); |
199 | + } | ||
200 | + log.trace("Sleep for the next run"); | ||
201 | + try { | ||
202 | + Thread.sleep(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()); | ||
203 | + } catch (InterruptedException ignore) { | ||
183 | } | 204 | } |
184 | } catch (Exception e) { | 205 | } catch (Exception e) { |
185 | log.warn("Failed to process messages handling!", e); | 206 | log.warn("Failed to process messages handling!", e); |
@@ -195,6 +216,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | @@ -195,6 +216,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i | ||
195 | private void onEdgeDisconnect(EdgeId edgeId) { | 216 | private void onEdgeDisconnect(EdgeId edgeId) { |
196 | log.debug("[{}] onEdgeDisconnect", edgeId); | 217 | log.debug("[{}] onEdgeDisconnect", edgeId); |
197 | sessions.remove(edgeId); | 218 | sessions.remove(edgeId); |
219 | + sessionNewEvents.remove(edgeId); | ||
198 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false); | 220 | save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false); |
199 | save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, System.currentTimeMillis()); | 221 | save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, System.currentTimeMillis()); |
200 | } | 222 | } |
@@ -304,11 +304,6 @@ public final class EdgeGrpcSession implements Closeable { | @@ -304,11 +304,6 @@ public final class EdgeGrpcSession implements Closeable { | ||
304 | Long newStartTs = UUIDs.unixTimestamp(ifOffset); | 304 | Long newStartTs = UUIDs.unixTimestamp(ifOffset); |
305 | updateQueueStartTs(newStartTs); | 305 | updateQueueStartTs(newStartTs); |
306 | } | 306 | } |
307 | - try { | ||
308 | - Thread.sleep(ctx.getEdgeEventStorageSettings().getNoRecordsSleepInterval()); | ||
309 | - } catch (InterruptedException e) { | ||
310 | - log.error("[{}] Error during sleep between no records interval", this.sessionId, e); | ||
311 | - } | ||
312 | } | 307 | } |
313 | log.trace("[{}] processHandleMessages finished", this.sessionId); | 308 | log.trace("[{}] processHandleMessages finished", this.sessionId); |
314 | } | 309 | } |
@@ -82,6 +82,7 @@ import org.thingsboard.server.gen.edge.RelationRequestMsg; | @@ -82,6 +82,7 @@ import org.thingsboard.server.gen.edge.RelationRequestMsg; | ||
82 | import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; | 82 | import org.thingsboard.server.gen.edge.RuleChainMetadataRequestMsg; |
83 | import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; | 83 | import org.thingsboard.server.gen.edge.UserCredentialsRequestMsg; |
84 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; | 84 | import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
85 | +import org.thingsboard.server.service.queue.TbClusterService; | ||
85 | 86 | ||
86 | import java.io.File; | 87 | import java.io.File; |
87 | import java.nio.charset.StandardCharsets; | 88 | import java.nio.charset.StandardCharsets; |
@@ -99,6 +100,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -99,6 +100,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
99 | 100 | ||
100 | private static final ObjectMapper mapper = new ObjectMapper(); | 101 | private static final ObjectMapper mapper = new ObjectMapper(); |
101 | 102 | ||
103 | + private static final int DEFAULT_LIMIT = 100; | ||
104 | + | ||
102 | @Autowired | 105 | @Autowired |
103 | private EdgeEventService edgeEventService; | 106 | private EdgeEventService edgeEventService; |
104 | 107 | ||
@@ -138,28 +141,31 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -138,28 +141,31 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
138 | @Autowired | 141 | @Autowired |
139 | private DbCallbackExecutorService dbCallbackExecutorService; | 142 | private DbCallbackExecutorService dbCallbackExecutorService; |
140 | 143 | ||
144 | + @Autowired | ||
145 | + private TbClusterService tbClusterService; | ||
146 | + | ||
141 | @Override | 147 | @Override |
142 | public void sync(Edge edge) { | 148 | public void sync(Edge edge) { |
143 | log.trace("[{}] staring sync process for edge [{}]", edge.getTenantId(), edge.getName()); | 149 | log.trace("[{}] staring sync process for edge [{}]", edge.getTenantId(), edge.getName()); |
144 | try { | 150 | try { |
145 | syncWidgetsBundleAndWidgetTypes(edge); | 151 | syncWidgetsBundleAndWidgetTypes(edge); |
146 | syncAdminSettings(edge); | 152 | syncAdminSettings(edge); |
147 | - syncRuleChains(edge); | 153 | + syncRuleChains(edge, new TimePageLink(DEFAULT_LIMIT)); |
148 | syncUsers(edge); | 154 | syncUsers(edge); |
149 | - syncDevices(edge); | ||
150 | - syncAssets(edge); | ||
151 | - syncEntityViews(edge); | ||
152 | - syncDashboards(edge); | 155 | + syncDevices(edge, new TimePageLink(DEFAULT_LIMIT)); |
156 | + syncAssets(edge, new TimePageLink(DEFAULT_LIMIT)); | ||
157 | + syncEntityViews(edge, new TimePageLink(DEFAULT_LIMIT)); | ||
158 | + syncDashboards(edge, new TimePageLink(DEFAULT_LIMIT)); | ||
153 | } catch (Exception e) { | 159 | } catch (Exception e) { |
154 | log.error("Exception during sync process", e); | 160 | log.error("Exception during sync process", e); |
155 | } | 161 | } |
156 | } | 162 | } |
157 | 163 | ||
158 | - private void syncRuleChains(Edge edge) { | ||
159 | - log.trace("[{}] syncRuleChains [{}]", edge.getTenantId(), edge.getName()); | 164 | + private void syncRuleChains(Edge edge, TimePageLink pageLink) { |
165 | + log.trace("[{}] syncRuleChains [{}] [{}]", edge.getTenantId(), edge.getName(), pageLink); | ||
160 | try { | 166 | try { |
161 | ListenableFuture<TimePageData<RuleChain>> future = | 167 | ListenableFuture<TimePageData<RuleChain>> future = |
162 | - ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); | 168 | + ruleChainService.findRuleChainsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink); |
163 | Futures.addCallback(future, new FutureCallback<TimePageData<RuleChain>>() { | 169 | Futures.addCallback(future, new FutureCallback<TimePageData<RuleChain>>() { |
164 | @Override | 170 | @Override |
165 | public void onSuccess(@Nullable TimePageData<RuleChain> pageData) { | 171 | public void onSuccess(@Nullable TimePageData<RuleChain> pageData) { |
@@ -168,6 +174,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -168,6 +174,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
168 | for (RuleChain ruleChain : pageData.getData()) { | 174 | for (RuleChain ruleChain : pageData.getData()) { |
169 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.ADDED, ruleChain.getId(), null); | 175 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.ADDED, ruleChain.getId(), null); |
170 | } | 176 | } |
177 | + if (pageData.hasNext()) { | ||
178 | + syncRuleChains(edge, pageData.getNextPageLink()); | ||
179 | + } | ||
171 | } | 180 | } |
172 | } | 181 | } |
173 | 182 | ||
@@ -181,11 +190,11 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -181,11 +190,11 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
181 | } | 190 | } |
182 | } | 191 | } |
183 | 192 | ||
184 | - private void syncDevices(Edge edge) { | 193 | + private void syncDevices(Edge edge, TimePageLink pageLink) { |
185 | log.trace("[{}] syncDevices [{}]", edge.getTenantId(), edge.getName()); | 194 | log.trace("[{}] syncDevices [{}]", edge.getTenantId(), edge.getName()); |
186 | try { | 195 | try { |
187 | ListenableFuture<TimePageData<Device>> future = | 196 | ListenableFuture<TimePageData<Device>> future = |
188 | - deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); | 197 | + deviceService.findDevicesByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink); |
189 | Futures.addCallback(future, new FutureCallback<TimePageData<Device>>() { | 198 | Futures.addCallback(future, new FutureCallback<TimePageData<Device>>() { |
190 | @Override | 199 | @Override |
191 | public void onSuccess(@Nullable TimePageData<Device> pageData) { | 200 | public void onSuccess(@Nullable TimePageData<Device> pageData) { |
@@ -194,6 +203,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -194,6 +203,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
194 | for (Device device : pageData.getData()) { | 203 | for (Device device : pageData.getData()) { |
195 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ADDED, device.getId(), null); | 204 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ADDED, device.getId(), null); |
196 | } | 205 | } |
206 | + if (pageData.hasNext()) { | ||
207 | + syncDevices(edge, pageData.getNextPageLink()); | ||
208 | + } | ||
197 | } | 209 | } |
198 | } | 210 | } |
199 | 211 | ||
@@ -207,10 +219,10 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -207,10 +219,10 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
207 | } | 219 | } |
208 | } | 220 | } |
209 | 221 | ||
210 | - private void syncAssets(Edge edge) { | 222 | + private void syncAssets(Edge edge, TimePageLink pageLink) { |
211 | log.trace("[{}] syncAssets [{}]", edge.getTenantId(), edge.getName()); | 223 | log.trace("[{}] syncAssets [{}]", edge.getTenantId(), edge.getName()); |
212 | try { | 224 | try { |
213 | - ListenableFuture<TimePageData<Asset>> future = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); | 225 | + ListenableFuture<TimePageData<Asset>> future = assetService.findAssetsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink); |
214 | Futures.addCallback(future, new FutureCallback<TimePageData<Asset>>() { | 226 | Futures.addCallback(future, new FutureCallback<TimePageData<Asset>>() { |
215 | @Override | 227 | @Override |
216 | public void onSuccess(@Nullable TimePageData<Asset> pageData) { | 228 | public void onSuccess(@Nullable TimePageData<Asset> pageData) { |
@@ -219,6 +231,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -219,6 +231,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
219 | for (Asset asset : pageData.getData()) { | 231 | for (Asset asset : pageData.getData()) { |
220 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ASSET, EdgeEventActionType.ADDED, asset.getId(), null); | 232 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ASSET, EdgeEventActionType.ADDED, asset.getId(), null); |
221 | } | 233 | } |
234 | + if (pageData.hasNext()) { | ||
235 | + syncAssets(edge, pageData.getNextPageLink()); | ||
236 | + } | ||
222 | } | 237 | } |
223 | } | 238 | } |
224 | 239 | ||
@@ -232,10 +247,10 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -232,10 +247,10 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
232 | } | 247 | } |
233 | } | 248 | } |
234 | 249 | ||
235 | - private void syncEntityViews(Edge edge) { | 250 | + private void syncEntityViews(Edge edge, TimePageLink pageLink) { |
236 | log.trace("[{}] syncEntityViews [{}]", edge.getTenantId(), edge.getName()); | 251 | log.trace("[{}] syncEntityViews [{}]", edge.getTenantId(), edge.getName()); |
237 | try { | 252 | try { |
238 | - ListenableFuture<TimePageData<EntityView>> future = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); | 253 | + ListenableFuture<TimePageData<EntityView>> future = entityViewService.findEntityViewsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink); |
239 | Futures.addCallback(future, new FutureCallback<TimePageData<EntityView>>() { | 254 | Futures.addCallback(future, new FutureCallback<TimePageData<EntityView>>() { |
240 | @Override | 255 | @Override |
241 | public void onSuccess(@Nullable TimePageData<EntityView> pageData) { | 256 | public void onSuccess(@Nullable TimePageData<EntityView> pageData) { |
@@ -244,6 +259,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -244,6 +259,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
244 | for (EntityView entityView : pageData.getData()) { | 259 | for (EntityView entityView : pageData.getData()) { |
245 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ENTITY_VIEW, EdgeEventActionType.ADDED, entityView.getId(), null); | 260 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ENTITY_VIEW, EdgeEventActionType.ADDED, entityView.getId(), null); |
246 | } | 261 | } |
262 | + if (pageData.hasNext()) { | ||
263 | + syncEntityViews(edge, pageData.getNextPageLink()); | ||
264 | + } | ||
247 | } | 265 | } |
248 | } | 266 | } |
249 | 267 | ||
@@ -257,10 +275,10 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -257,10 +275,10 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
257 | } | 275 | } |
258 | } | 276 | } |
259 | 277 | ||
260 | - private void syncDashboards(Edge edge) { | 278 | + private void syncDashboards(Edge edge, TimePageLink pageLink) { |
261 | log.trace("[{}] syncDashboards [{}]", edge.getTenantId(), edge.getName()); | 279 | log.trace("[{}] syncDashboards [{}]", edge.getTenantId(), edge.getName()); |
262 | try { | 280 | try { |
263 | - ListenableFuture<TimePageData<DashboardInfo>> future = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), new TimePageLink(Integer.MAX_VALUE)); | 281 | + ListenableFuture<TimePageData<DashboardInfo>> future = dashboardService.findDashboardsByTenantIdAndEdgeId(edge.getTenantId(), edge.getId(), pageLink); |
264 | Futures.addCallback(future, new FutureCallback<TimePageData<DashboardInfo>>() { | 282 | Futures.addCallback(future, new FutureCallback<TimePageData<DashboardInfo>>() { |
265 | @Override | 283 | @Override |
266 | public void onSuccess(@Nullable TimePageData<DashboardInfo> pageData) { | 284 | public void onSuccess(@Nullable TimePageData<DashboardInfo> pageData) { |
@@ -269,6 +287,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -269,6 +287,9 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
269 | for (DashboardInfo dashboardInfo : pageData.getData()) { | 287 | for (DashboardInfo dashboardInfo : pageData.getData()) { |
270 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DASHBOARD, EdgeEventActionType.ADDED, dashboardInfo.getId(), null); | 288 | saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DASHBOARD, EdgeEventActionType.ADDED, dashboardInfo.getId(), null); |
271 | } | 289 | } |
290 | + if (pageData.hasNext()) { | ||
291 | + syncDashboards(edge, pageData.getNextPageLink()); | ||
292 | + } | ||
272 | } | 293 | } |
273 | } | 294 | } |
274 | 295 | ||
@@ -285,18 +306,36 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -285,18 +306,36 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
285 | private void syncUsers(Edge edge) { | 306 | private void syncUsers(Edge edge) { |
286 | log.trace("[{}] syncUsers [{}]", edge.getTenantId(), edge.getName()); | 307 | log.trace("[{}] syncUsers [{}]", edge.getTenantId(), edge.getName()); |
287 | try { | 308 | try { |
288 | - TextPageData<User> pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE)); | ||
289 | - pushUsersToEdge(pageData, edge); | ||
290 | - if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { | ||
291 | - saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, edge.getCustomerId(), null); | ||
292 | - pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE)); | 309 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); |
310 | + TextPageData<User> pageData; | ||
311 | + do { | ||
312 | + pageData = userService.findTenantAdmins(edge.getTenantId(), pageLink); | ||
293 | pushUsersToEdge(pageData, edge); | 313 | pushUsersToEdge(pageData, edge); |
294 | - } | 314 | + syncCustomerUsers(edge); |
315 | + if (pageData != null && pageData.hasNext()) { | ||
316 | + pageLink = pageData.getNextPageLink(); | ||
317 | + } | ||
318 | + } while (pageData != null && pageData.hasNext()); | ||
295 | } catch (Exception e) { | 319 | } catch (Exception e) { |
296 | log.error("Exception during loading edge user(s) on sync!", e); | 320 | log.error("Exception during loading edge user(s) on sync!", e); |
297 | } | 321 | } |
298 | } | 322 | } |
299 | 323 | ||
324 | + private void syncCustomerUsers(Edge edge) { | ||
325 | + if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) { | ||
326 | + saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, edge.getCustomerId(), null); | ||
327 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); | ||
328 | + TextPageData<User> pageData; | ||
329 | + do { | ||
330 | + pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), pageLink); | ||
331 | + pushUsersToEdge(pageData, edge); | ||
332 | + if (pageData != null && pageData.hasNext()) { | ||
333 | + pageLink = pageData.getNextPageLink(); | ||
334 | + } | ||
335 | + } while (pageData != null && pageData.hasNext()); | ||
336 | + } | ||
337 | + } | ||
338 | + | ||
300 | private void syncWidgetsBundleAndWidgetTypes(Edge edge) { | 339 | private void syncWidgetsBundleAndWidgetTypes(Edge edge) { |
301 | log.trace("[{}] syncWidgetsBundleAndWidgetTypes [{}]", edge.getTenantId(), edge.getName()); | 340 | log.trace("[{}] syncWidgetsBundleAndWidgetTypes [{}]", edge.getTenantId(), edge.getName()); |
302 | List<WidgetsBundle> widgetsBundlesToPush = new ArrayList<>(); | 341 | List<WidgetsBundle> widgetsBundlesToPush = new ArrayList<>(); |
@@ -426,7 +465,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -426,7 +465,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
426 | final EdgeEventType type = getEdgeQueueTypeByEntityType(entityId.getEntityType()); | 465 | final EdgeEventType type = getEdgeQueueTypeByEntityType(entityId.getEntityType()); |
427 | if (type != null) { | 466 | if (type != null) { |
428 | SettableFuture<Void> futureToSet = SettableFuture.create(); | 467 | SettableFuture<Void> futureToSet = SettableFuture.create(); |
429 | - ListenableFuture<List<AttributeKvEntry>> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE); | 468 | + String scope = attributesRequestMsg.getScope(); |
469 | + ListenableFuture<List<AttributeKvEntry>> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, scope); | ||
430 | Futures.addCallback(ssAttrFuture, new FutureCallback<List<AttributeKvEntry>>() { | 470 | Futures.addCallback(ssAttrFuture, new FutureCallback<List<AttributeKvEntry>>() { |
431 | @Override | 471 | @Override |
432 | public void onSuccess(@Nullable List<AttributeKvEntry> ssAttributes) { | 472 | public void onSuccess(@Nullable List<AttributeKvEntry> ssAttributes) { |
@@ -446,7 +486,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -446,7 +486,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
446 | } | 486 | } |
447 | } | 487 | } |
448 | entityData.put("kv", attributes); | 488 | entityData.put("kv", attributes); |
449 | - entityData.put("scope", DataConstants.SERVER_SCOPE); | 489 | + entityData.put("scope", scope); |
450 | JsonNode body = mapper.valueToTree(entityData); | 490 | JsonNode body = mapper.valueToTree(entityData); |
451 | log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, body); | 491 | log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, body); |
452 | saveEdgeEvent(edge.getTenantId(), | 492 | saveEdgeEvent(edge.getTenantId(), |
@@ -459,6 +499,11 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -459,6 +499,11 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
459 | log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); | 499 | log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e); |
460 | throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e); | 500 | throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e); |
461 | } | 501 | } |
502 | + } else { | ||
503 | + log.trace("[{}][{}] No attributes found for entity {} [{}]", edge.getTenantId(), | ||
504 | + edge.getName(), | ||
505 | + entityId.getEntityType(), | ||
506 | + entityId.getId()); | ||
462 | } | 507 | } |
463 | futureToSet.set(null); | 508 | futureToSet.set(null); |
464 | } | 509 | } |
@@ -470,10 +515,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -470,10 +515,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
470 | } | 515 | } |
471 | }, dbCallbackExecutorService); | 516 | }, dbCallbackExecutorService); |
472 | return futureToSet; | 517 | return futureToSet; |
473 | - // TODO: voba - push shared attributes to edge? | ||
474 | - // ListenableFuture<List<AttributeKvEntry>> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE); | ||
475 | - // ListenableFuture<List<AttributeKvEntry>> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE); | ||
476 | } else { | 518 | } else { |
519 | + log.warn("[{}] Type doesn't supported {}", edge.getTenantId(), entityId.getEntityType()); | ||
477 | return Futures.immediateFuture(null); | 520 | return Futures.immediateFuture(null); |
478 | } | 521 | } |
479 | } | 522 | } |
@@ -585,11 +628,11 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -585,11 +628,11 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
585 | } | 628 | } |
586 | 629 | ||
587 | private ListenableFuture<EdgeEvent> saveEdgeEvent(TenantId tenantId, | 630 | private ListenableFuture<EdgeEvent> saveEdgeEvent(TenantId tenantId, |
588 | - EdgeId edgeId, | ||
589 | - EdgeEventType type, | ||
590 | - EdgeEventActionType action, | ||
591 | - EntityId entityId, | ||
592 | - JsonNode body) { | 631 | + EdgeId edgeId, |
632 | + EdgeEventType type, | ||
633 | + EdgeEventActionType action, | ||
634 | + EntityId entityId, | ||
635 | + JsonNode body) { | ||
593 | log.trace("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], type [{}], action[{}], entityId [{}], body [{}]", | 636 | log.trace("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], type [{}], action[{}], entityId [{}], body [{}]", |
594 | tenantId, edgeId, type, action, entityId, body); | 637 | tenantId, edgeId, type, action, entityId, body); |
595 | 638 | ||
@@ -602,6 +645,18 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | @@ -602,6 +645,18 @@ public class DefaultSyncEdgeService implements SyncEdgeService { | ||
602 | edgeEvent.setEntityId(entityId.getId()); | 645 | edgeEvent.setEntityId(entityId.getId()); |
603 | } | 646 | } |
604 | edgeEvent.setBody(body); | 647 | edgeEvent.setBody(body); |
605 | - return edgeEventService.saveAsync(edgeEvent); | 648 | + ListenableFuture<EdgeEvent> future = edgeEventService.saveAsync(edgeEvent); |
649 | + Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | ||
650 | + @Override | ||
651 | + public void onSuccess(@Nullable EdgeEvent result) { | ||
652 | + tbClusterService.onEdgeEventUpdate(tenantId, edgeId); | ||
653 | + } | ||
654 | + | ||
655 | + @Override | ||
656 | + public void onFailure(Throwable t) { | ||
657 | + log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | ||
658 | + } | ||
659 | + }, dbCallbackExecutorService); | ||
660 | + return future; | ||
606 | } | 661 | } |
607 | } | 662 | } |
@@ -17,8 +17,11 @@ package org.thingsboard.server.service.edge.rpc.processor; | @@ -17,8 +17,11 @@ package org.thingsboard.server.service.edge.rpc.processor; | ||
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | +import com.google.common.util.concurrent.FutureCallback; | ||
21 | +import com.google.common.util.concurrent.Futures; | ||
20 | import com.google.common.util.concurrent.ListenableFuture; | 22 | import com.google.common.util.concurrent.ListenableFuture; |
21 | import lombok.extern.slf4j.Slf4j; | 23 | import lombok.extern.slf4j.Slf4j; |
24 | +import org.checkerframework.checker.nullness.qual.Nullable; | ||
22 | import org.springframework.beans.factory.annotation.Autowired; | 25 | import org.springframework.beans.factory.annotation.Autowired; |
23 | import org.thingsboard.server.common.data.edge.EdgeEvent; | 26 | import org.thingsboard.server.common.data.edge.EdgeEvent; |
24 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; | 27 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
@@ -107,6 +110,18 @@ public abstract class BaseProcessor { | @@ -107,6 +110,18 @@ public abstract class BaseProcessor { | ||
107 | edgeEvent.setEntityId(entityId.getId()); | 110 | edgeEvent.setEntityId(entityId.getId()); |
108 | } | 111 | } |
109 | edgeEvent.setBody(body); | 112 | edgeEvent.setBody(body); |
110 | - return edgeEventService.saveAsync(edgeEvent); | 113 | + ListenableFuture<EdgeEvent> future = edgeEventService.saveAsync(edgeEvent); |
114 | + Futures.addCallback(future, new FutureCallback<EdgeEvent>() { | ||
115 | + @Override | ||
116 | + public void onSuccess(@Nullable EdgeEvent result) { | ||
117 | + tbClusterService.onEdgeEventUpdate(tenantId, edgeId); | ||
118 | + } | ||
119 | + | ||
120 | + @Override | ||
121 | + public void onFailure(Throwable t) { | ||
122 | + log.warn("[{}] Can't save edge event [{}] for edge [{}]", tenantId.getId(), edgeEvent, edgeId.getId(), t); | ||
123 | + } | ||
124 | + }, dbCallbackExecutorService); | ||
125 | + return future; | ||
111 | } | 126 | } |
112 | } | 127 | } |
@@ -22,10 +22,12 @@ import org.springframework.scheduling.annotation.Scheduled; | @@ -22,10 +22,12 @@ import org.springframework.scheduling.annotation.Scheduled; | ||
22 | import org.springframework.stereotype.Service; | 22 | import org.springframework.stereotype.Service; |
23 | import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; | 23 | import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; |
24 | import org.thingsboard.server.common.data.EntityType; | 24 | import org.thingsboard.server.common.data.EntityType; |
25 | +import org.thingsboard.server.common.data.id.EdgeId; | ||
25 | import org.thingsboard.server.common.data.id.EntityId; | 26 | import org.thingsboard.server.common.data.id.EntityId; |
26 | import org.thingsboard.server.common.data.id.TenantId; | 27 | import org.thingsboard.server.common.data.id.TenantId; |
27 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 28 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
28 | import org.thingsboard.server.common.msg.TbMsg; | 29 | import org.thingsboard.server.common.msg.TbMsg; |
30 | +import org.thingsboard.server.common.msg.edge.EdgeEventUpdateMsg; | ||
29 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 31 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
30 | import org.thingsboard.server.common.msg.queue.ServiceType; | 32 | import org.thingsboard.server.common.msg.queue.ServiceType; |
31 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 33 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
@@ -163,11 +165,31 @@ public class DefaultTbClusterService implements TbClusterService { | @@ -163,11 +165,31 @@ public class DefaultTbClusterService implements TbClusterService { | ||
163 | broadcast(new ComponentLifecycleMsg(tenantId, entityId, state)); | 165 | broadcast(new ComponentLifecycleMsg(tenantId, entityId, state)); |
164 | } | 166 | } |
165 | 167 | ||
168 | + @Override | ||
169 | + public void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId) { | ||
170 | + log.trace("[{}] Processing edge {} event update ", tenantId, edgeId); | ||
171 | + EdgeEventUpdateMsg msg = new EdgeEventUpdateMsg(tenantId, edgeId); | ||
172 | + byte[] msgBytes = encodingService.encode(msg); | ||
173 | + TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer(); | ||
174 | + Set<String> tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE); | ||
175 | + for (String serviceId : tbCoreServices) { | ||
176 | + TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_CORE, serviceId); | ||
177 | + ToCoreNotificationMsg toCoreMsg = ToCoreNotificationMsg.newBuilder().setEdgeEventUpdateMsg(ByteString.copyFrom(msgBytes)).build(); | ||
178 | + toCoreNfProducer.send(tpi, new TbProtoQueueMsg<>(msg.getEdgeId().getId(), toCoreMsg), null); | ||
179 | + toCoreNfs.incrementAndGet(); | ||
180 | + } | ||
181 | + } | ||
182 | + | ||
166 | private void broadcast(ComponentLifecycleMsg msg) { | 183 | private void broadcast(ComponentLifecycleMsg msg) { |
167 | byte[] msgBytes = encodingService.encode(msg); | 184 | byte[] msgBytes = encodingService.encode(msg); |
168 | TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer(); | 185 | TbQueueProducer<TbProtoQueueMsg<ToRuleEngineNotificationMsg>> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer(); |
169 | Set<String> tbRuleEngineServices = new HashSet<>(partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE)); | 186 | Set<String> tbRuleEngineServices = new HashSet<>(partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE)); |
170 | - if (msg.getEntityId().getEntityType().equals(EntityType.TENANT)) { | 187 | + boolean toCore = msg.getEntityId().getEntityType().equals(EntityType.TENANT) || |
188 | + msg.getEntityId().getEntityType().equals(EntityType.EDGE); | ||
189 | + | ||
190 | + boolean toRuleEngine = !msg.getEntityId().getEntityType().equals(EntityType.EDGE); | ||
191 | + | ||
192 | + if (toCore) { | ||
171 | TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer(); | 193 | TbQueueProducer<TbProtoQueueMsg<ToCoreNotificationMsg>> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer(); |
172 | Set<String> tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE); | 194 | Set<String> tbCoreServices = partitionService.getAllServiceIds(ServiceType.TB_CORE); |
173 | for (String serviceId : tbCoreServices) { | 195 | for (String serviceId : tbCoreServices) { |
@@ -179,11 +201,13 @@ public class DefaultTbClusterService implements TbClusterService { | @@ -179,11 +201,13 @@ public class DefaultTbClusterService implements TbClusterService { | ||
179 | // No need to push notifications twice | 201 | // No need to push notifications twice |
180 | tbRuleEngineServices.removeAll(tbCoreServices); | 202 | tbRuleEngineServices.removeAll(tbCoreServices); |
181 | } | 203 | } |
182 | - for (String serviceId : tbRuleEngineServices) { | ||
183 | - TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceId); | ||
184 | - ToRuleEngineNotificationMsg toRuleEngineMsg = ToRuleEngineNotificationMsg.newBuilder().setComponentLifecycleMsg(ByteString.copyFrom(msgBytes)).build(); | ||
185 | - toRuleEngineProducer.send(tpi, new TbProtoQueueMsg<>(msg.getEntityId().getId(), toRuleEngineMsg), null); | ||
186 | - toRuleEngineNfs.incrementAndGet(); | 204 | + if (toRuleEngine) { |
205 | + for (String serviceId : tbRuleEngineServices) { | ||
206 | + TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceId); | ||
207 | + ToRuleEngineNotificationMsg toRuleEngineMsg = ToRuleEngineNotificationMsg.newBuilder().setComponentLifecycleMsg(ByteString.copyFrom(msgBytes)).build(); | ||
208 | + toRuleEngineProducer.send(tpi, new TbProtoQueueMsg<>(msg.getEntityId().getId(), toRuleEngineMsg), null); | ||
209 | + toRuleEngineNfs.incrementAndGet(); | ||
210 | + } | ||
187 | } | 211 | } |
188 | } | 212 | } |
189 | 213 |
@@ -203,18 +203,24 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | @@ -203,18 +203,24 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore | ||
203 | log.trace("[{}] Forwarding message to RPC service {}", id, toCoreNotification.getFromDeviceRpcResponse()); | 203 | log.trace("[{}] Forwarding message to RPC service {}", id, toCoreNotification.getFromDeviceRpcResponse()); |
204 | forwardToCoreRpcService(toCoreNotification.getFromDeviceRpcResponse(), callback); | 204 | forwardToCoreRpcService(toCoreNotification.getFromDeviceRpcResponse(), callback); |
205 | } else if (toCoreNotification.getComponentLifecycleMsg() != null && !toCoreNotification.getComponentLifecycleMsg().isEmpty()) { | 205 | } else if (toCoreNotification.getComponentLifecycleMsg() != null && !toCoreNotification.getComponentLifecycleMsg().isEmpty()) { |
206 | - Optional<TbActorMsg> actorMsg = encodingService.decode(toCoreNotification.getComponentLifecycleMsg().toByteArray()); | ||
207 | - if (actorMsg.isPresent()) { | ||
208 | - log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); | ||
209 | - actorContext.tellWithHighPriority(actorMsg.get()); | ||
210 | - } | ||
211 | - callback.onSuccess(); | 206 | + forwardToAppActor(id, toCoreNotification.getComponentLifecycleMsg().toByteArray(), callback); |
207 | + } else if (toCoreNotification.getEdgeEventUpdateMsg() != null && !toCoreNotification.getEdgeEventUpdateMsg().isEmpty()) { | ||
208 | + forwardToAppActor(id, toCoreNotification.getEdgeEventUpdateMsg().toByteArray(), callback); | ||
212 | } | 209 | } |
213 | if (statsEnabled) { | 210 | if (statsEnabled) { |
214 | stats.log(toCoreNotification); | 211 | stats.log(toCoreNotification); |
215 | } | 212 | } |
216 | } | 213 | } |
217 | 214 | ||
215 | + private void forwardToAppActor(UUID id, byte[] msgBytes, TbCallback callback) { | ||
216 | + Optional<TbActorMsg> actorMsg = encodingService.decode(msgBytes); | ||
217 | + if (actorMsg.isPresent()) { | ||
218 | + log.trace("[{}] Forwarding message to App Actor {}", id, actorMsg.get()); | ||
219 | + actorContext.tellWithHighPriority(actorMsg.get()); | ||
220 | + } | ||
221 | + callback.onSuccess(); | ||
222 | + } | ||
223 | + | ||
218 | private void forwardToCoreRpcService(FromDeviceRPCResponseProto proto, TbCallback callback) { | 224 | private void forwardToCoreRpcService(FromDeviceRPCResponseProto proto, TbCallback callback) { |
219 | RpcError error = proto.getError() > 0 ? RpcError.values()[proto.getError()] : null; | 225 | RpcError error = proto.getError() > 0 ? RpcError.values()[proto.getError()] : null; |
220 | FromDeviceRpcResponse response = new FromDeviceRpcResponse(new UUID(proto.getRequestIdMSB(), proto.getRequestIdLSB()) | 226 | FromDeviceRpcResponse response = new FromDeviceRpcResponse(new UUID(proto.getRequestIdMSB(), proto.getRequestIdLSB()) |
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | package org.thingsboard.server.service.queue; | 16 | package org.thingsboard.server.service.queue; |
17 | 17 | ||
18 | import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; | 18 | import org.thingsboard.rule.engine.api.msg.ToDeviceActorNotificationMsg; |
19 | +import org.thingsboard.server.common.data.id.EdgeId; | ||
19 | import org.thingsboard.server.common.data.id.EntityId; | 20 | import org.thingsboard.server.common.data.id.EntityId; |
20 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
21 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 22 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
@@ -49,4 +50,6 @@ public interface TbClusterService { | @@ -49,4 +50,6 @@ public interface TbClusterService { | ||
49 | 50 | ||
50 | void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state); | 51 | void onEntityStateChange(TenantId tenantId, EntityId entityId, ComponentLifecycleEvent state); |
51 | 52 | ||
53 | + void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId); | ||
54 | + | ||
52 | } | 55 | } |
@@ -52,7 +52,6 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi | @@ -52,7 +52,6 @@ public class DefaultTbRuleEngineRpcService implements TbRuleEngineDeviceRpcServi | ||
52 | private final TbClusterService clusterService; | 52 | private final TbClusterService clusterService; |
53 | private final TbServiceInfoProvider serviceInfoProvider; | 53 | private final TbServiceInfoProvider serviceInfoProvider; |
54 | 54 | ||
55 | - | ||
56 | private final ConcurrentMap<UUID, Consumer<FromDeviceRpcResponse>> toDeviceRpcRequests = new ConcurrentHashMap<>(); | 55 | private final ConcurrentMap<UUID, Consumer<FromDeviceRpcResponse>> toDeviceRpcRequests = new ConcurrentHashMap<>(); |
57 | 56 | ||
58 | private Optional<TbCoreDeviceRpcService> tbCoreRpcService; | 57 | private Optional<TbCoreDeviceRpcService> tbCoreRpcService; |
@@ -98,6 +98,7 @@ import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; | @@ -98,6 +98,7 @@ import org.thingsboard.server.gen.edge.UserCredentialsUpdateMsg; | ||
98 | import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; | 98 | import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg; |
99 | import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; | 99 | import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg; |
100 | import org.thingsboard.server.gen.transport.TransportProtos; | 100 | import org.thingsboard.server.gen.transport.TransportProtos; |
101 | +import org.thingsboard.server.service.queue.TbClusterService; | ||
101 | 102 | ||
102 | import java.util.ArrayList; | 103 | import java.util.ArrayList; |
103 | import java.util.List; | 104 | import java.util.List; |
@@ -122,6 +123,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -122,6 +123,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
122 | @Autowired | 123 | @Autowired |
123 | private EdgeEventService edgeEventService; | 124 | private EdgeEventService edgeEventService; |
124 | 125 | ||
126 | + @Autowired | ||
127 | + private TbClusterService clusterService; | ||
128 | + | ||
125 | @Before | 129 | @Before |
126 | public void beforeTest() throws Exception { | 130 | public void beforeTest() throws Exception { |
127 | loginSysAdmin(); | 131 | loginSysAdmin(); |
@@ -227,6 +231,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -227,6 +231,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
227 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.RPC_CALL, device.getId().getId(), EdgeEventType.DEVICE, body); | 231 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.RPC_CALL, device.getId().getId(), EdgeEventType.DEVICE, body); |
228 | edgeImitator.expectMessageAmount(1); | 232 | edgeImitator.expectMessageAmount(1); |
229 | edgeEventService.saveAsync(edgeEvent); | 233 | edgeEventService.saveAsync(edgeEvent); |
234 | + clusterService.onEdgeEventUpdate(tenantId, edge.getId()); | ||
230 | edgeImitator.waitForMessages(); | 235 | edgeImitator.waitForMessages(); |
231 | 236 | ||
232 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); | 237 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); |
@@ -847,6 +852,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -847,6 +852,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
847 | EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData); | 852 | EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.TIMESERIES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, timeseriesEntityData); |
848 | edgeImitator.expectMessageAmount(1); | 853 | edgeImitator.expectMessageAmount(1); |
849 | edgeEventService.saveAsync(edgeEvent1); | 854 | edgeEventService.saveAsync(edgeEvent1); |
855 | + clusterService.onEdgeEventUpdate(tenantId, edge.getId()); | ||
850 | edgeImitator.waitForMessages(); | 856 | edgeImitator.waitForMessages(); |
851 | 857 | ||
852 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); | 858 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); |
@@ -885,6 +891,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -885,6 +891,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
885 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_DELETED, device.getId().getId(), EdgeEventType.DEVICE, deleteAttributesEntityData); | 891 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_DELETED, device.getId().getId(), EdgeEventType.DEVICE, deleteAttributesEntityData); |
886 | edgeImitator.expectMessageAmount(1); | 892 | edgeImitator.expectMessageAmount(1); |
887 | edgeEventService.saveAsync(edgeEvent); | 893 | edgeEventService.saveAsync(edgeEvent); |
894 | + clusterService.onEdgeEventUpdate(tenantId, edge.getId()); | ||
888 | edgeImitator.waitForMessages(); | 895 | edgeImitator.waitForMessages(); |
889 | 896 | ||
890 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); | 897 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); |
@@ -910,6 +917,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -910,6 +917,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
910 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.POST_ATTRIBUTES, device.getId().getId(), EdgeEventType.DEVICE, postAttributesEntityData); | 917 | EdgeEvent edgeEvent = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.POST_ATTRIBUTES, device.getId().getId(), EdgeEventType.DEVICE, postAttributesEntityData); |
911 | edgeImitator.expectMessageAmount(1); | 918 | edgeImitator.expectMessageAmount(1); |
912 | edgeEventService.saveAsync(edgeEvent); | 919 | edgeEventService.saveAsync(edgeEvent); |
920 | + clusterService.onEdgeEventUpdate(tenantId, edge.getId()); | ||
913 | edgeImitator.waitForMessages(); | 921 | edgeImitator.waitForMessages(); |
914 | 922 | ||
915 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); | 923 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); |
@@ -934,6 +942,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -934,6 +942,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
934 | EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); | 942 | EdgeEvent edgeEvent1 = constructEdgeEvent(tenantId, edge.getId(), EdgeEventActionType.ATTRIBUTES_UPDATED, device.getId().getId(), EdgeEventType.DEVICE, attributesEntityData); |
935 | edgeImitator.expectMessageAmount(1); | 943 | edgeImitator.expectMessageAmount(1); |
936 | edgeEventService.saveAsync(edgeEvent1); | 944 | edgeEventService.saveAsync(edgeEvent1); |
945 | + clusterService.onEdgeEventUpdate(tenantId, edge.getId()); | ||
937 | edgeImitator.waitForMessages(); | 946 | edgeImitator.waitForMessages(); |
938 | 947 | ||
939 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); | 948 | AbstractMessage latestMessage = edgeImitator.getLatestMessage(); |
@@ -1160,6 +1169,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -1160,6 +1169,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
1160 | edgeImitator.sendUplinkMsg(uplinkMsgBuilder2.build()); | 1169 | edgeImitator.sendUplinkMsg(uplinkMsgBuilder2.build()); |
1161 | edgeImitator.waitForResponses(); | 1170 | edgeImitator.waitForResponses(); |
1162 | 1171 | ||
1172 | + // Wait before device attributes saved to database before requesting them from controller | ||
1163 | Thread.sleep(1000); | 1173 | Thread.sleep(1000); |
1164 | Map<String, List<Map<String, String>>> timeseries = doGetAsync("/api/plugins/telemetry/DEVICE/" + device.getUuidId() + "/values/timeseries?keys=" + timeseriesKey, Map.class); | 1174 | Map<String, List<Map<String, String>>> timeseries = doGetAsync("/api/plugins/telemetry/DEVICE/" + device.getUuidId() + "/values/timeseries?keys=" + timeseriesKey, Map.class); |
1165 | Assert.assertTrue(timeseries.containsKey(timeseriesKey)); | 1175 | Assert.assertTrue(timeseries.containsKey(timeseriesKey)); |
@@ -1302,18 +1312,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -1302,18 +1312,25 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
1302 | 1312 | ||
1303 | private void sendAttributesRequest() throws Exception { | 1313 | private void sendAttributesRequest() throws Exception { |
1304 | Device device = findDeviceByName("Edge Device 1"); | 1314 | Device device = findDeviceByName("Edge Device 1"); |
1315 | + sendAttributesRequest(device, DataConstants.SERVER_SCOPE, "{\"key1\":\"value1\"}", "key1", "value1"); | ||
1316 | + sendAttributesRequest(device, DataConstants.SHARED_SCOPE, "{\"key2\":\"value2\"}", "key2", "value2"); | ||
1317 | + } | ||
1305 | 1318 | ||
1306 | - String attributesDataStr = "{\"key1\":\"value1\"}"; | 1319 | + private void sendAttributesRequest(Device device, String scope, String attributesDataStr, String expectedKey, String expectedValue) throws Exception { |
1307 | JsonNode attributesData = mapper.readTree(attributesDataStr); | 1320 | JsonNode attributesData = mapper.readTree(attributesDataStr); |
1308 | 1321 | ||
1309 | - doPost("/api/plugins/telemetry/DEVICE/" + device.getId().getId().toString() + "/attributes/" + DataConstants.SERVER_SCOPE, | 1322 | + doPost("/api/plugins/telemetry/DEVICE/" + device.getId().getId().toString() + "/attributes/" + scope, |
1310 | attributesData); | 1323 | attributesData); |
1311 | 1324 | ||
1325 | + // Wait before device attributes saved to database before requesting them from edge | ||
1326 | + Thread.sleep(1000); | ||
1327 | + | ||
1312 | UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder(); | 1328 | UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder(); |
1313 | AttributesRequestMsg.Builder attributesRequestMsgBuilder = AttributesRequestMsg.newBuilder(); | 1329 | AttributesRequestMsg.Builder attributesRequestMsgBuilder = AttributesRequestMsg.newBuilder(); |
1314 | attributesRequestMsgBuilder.setEntityIdMSB(device.getUuidId().getMostSignificantBits()); | 1330 | attributesRequestMsgBuilder.setEntityIdMSB(device.getUuidId().getMostSignificantBits()); |
1315 | attributesRequestMsgBuilder.setEntityIdLSB(device.getUuidId().getLeastSignificantBits()); | 1331 | attributesRequestMsgBuilder.setEntityIdLSB(device.getUuidId().getLeastSignificantBits()); |
1316 | attributesRequestMsgBuilder.setEntityType(EntityType.DEVICE.name()); | 1332 | attributesRequestMsgBuilder.setEntityType(EntityType.DEVICE.name()); |
1333 | + attributesRequestMsgBuilder.setScope(scope); | ||
1317 | testAutoGeneratedCodeByProtobuf(attributesRequestMsgBuilder); | 1334 | testAutoGeneratedCodeByProtobuf(attributesRequestMsgBuilder); |
1318 | uplinkMsgBuilder.addAttributesRequestMsg(attributesRequestMsgBuilder.build()); | 1335 | uplinkMsgBuilder.addAttributesRequestMsg(attributesRequestMsgBuilder.build()); |
1319 | testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder); | 1336 | testAutoGeneratedCodeByProtobuf(uplinkMsgBuilder); |
@@ -1330,14 +1347,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | @@ -1330,14 +1347,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest { | ||
1330 | Assert.assertEquals(device.getUuidId().getMostSignificantBits(), latestEntityDataMsg.getEntityIdMSB()); | 1347 | Assert.assertEquals(device.getUuidId().getMostSignificantBits(), latestEntityDataMsg.getEntityIdMSB()); |
1331 | Assert.assertEquals(device.getUuidId().getLeastSignificantBits(), latestEntityDataMsg.getEntityIdLSB()); | 1348 | Assert.assertEquals(device.getUuidId().getLeastSignificantBits(), latestEntityDataMsg.getEntityIdLSB()); |
1332 | Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); | 1349 | Assert.assertEquals(device.getId().getEntityType().name(), latestEntityDataMsg.getEntityType()); |
1333 | - Assert.assertEquals("SERVER_SCOPE", latestEntityDataMsg.getPostAttributeScope()); | 1350 | + Assert.assertEquals(scope, latestEntityDataMsg.getPostAttributeScope()); |
1334 | Assert.assertTrue(latestEntityDataMsg.hasAttributesUpdatedMsg()); | 1351 | Assert.assertTrue(latestEntityDataMsg.hasAttributesUpdatedMsg()); |
1335 | 1352 | ||
1336 | TransportProtos.PostAttributeMsg attributesUpdatedMsg = latestEntityDataMsg.getAttributesUpdatedMsg(); | 1353 | TransportProtos.PostAttributeMsg attributesUpdatedMsg = latestEntityDataMsg.getAttributesUpdatedMsg(); |
1337 | Assert.assertEquals(1, attributesUpdatedMsg.getKvCount()); | 1354 | Assert.assertEquals(1, attributesUpdatedMsg.getKvCount()); |
1338 | TransportProtos.KeyValueProto keyValueProto = attributesUpdatedMsg.getKv(0); | 1355 | TransportProtos.KeyValueProto keyValueProto = attributesUpdatedMsg.getKv(0); |
1339 | - Assert.assertEquals("key1", keyValueProto.getKey()); | ||
1340 | - Assert.assertEquals("value1", keyValueProto.getStringV()); | 1356 | + Assert.assertEquals(expectedKey, keyValueProto.getKey()); |
1357 | + Assert.assertEquals(expectedValue, keyValueProto.getStringV()); | ||
1341 | } | 1358 | } |
1342 | 1359 | ||
1343 | private void sendDeleteDeviceOnEdge() throws Exception { | 1360 | private void sendDeleteDeviceOnEdge() throws Exception { |
@@ -56,6 +56,8 @@ import java.util.Optional; | @@ -56,6 +56,8 @@ import java.util.Optional; | ||
56 | import java.util.UUID; | 56 | import java.util.UUID; |
57 | import java.util.concurrent.CountDownLatch; | 57 | import java.util.concurrent.CountDownLatch; |
58 | import java.util.concurrent.TimeUnit; | 58 | import java.util.concurrent.TimeUnit; |
59 | +import java.util.concurrent.locks.Lock; | ||
60 | +import java.util.concurrent.locks.ReentrantLock; | ||
59 | 61 | ||
60 | @Slf4j | 62 | @Slf4j |
61 | public class EdgeImitator { | 63 | public class EdgeImitator { |
@@ -65,6 +67,8 @@ public class EdgeImitator { | @@ -65,6 +67,8 @@ public class EdgeImitator { | ||
65 | 67 | ||
66 | private EdgeRpcClient edgeRpcClient; | 68 | private EdgeRpcClient edgeRpcClient; |
67 | 69 | ||
70 | + private final Lock lock = new ReentrantLock(); | ||
71 | + | ||
68 | private CountDownLatch messagesLatch; | 72 | private CountDownLatch messagesLatch; |
69 | private CountDownLatch responsesLatch; | 73 | private CountDownLatch responsesLatch; |
70 | private List<Class<? extends AbstractMessage>> ignoredTypes; | 74 | private List<Class<? extends AbstractMessage>> ignoredTypes; |
@@ -74,7 +78,7 @@ public class EdgeImitator { | @@ -74,7 +78,7 @@ public class EdgeImitator { | ||
74 | @Getter | 78 | @Getter |
75 | private UserId userId; | 79 | private UserId userId; |
76 | @Getter | 80 | @Getter |
77 | - private List<AbstractMessage> downlinkMsgs; | 81 | + private final List<AbstractMessage> downlinkMsgs; |
78 | 82 | ||
79 | public EdgeImitator(String host, int port, String routingKey, String routingSecret) throws NoSuchFieldException, IllegalAccessException { | 83 | public EdgeImitator(String host, int port, String routingKey, String routingSecret) throws NoSuchFieldException, IllegalAccessException { |
80 | edgeRpcClient = new EdgeGrpcClient(); | 84 | edgeRpcClient = new EdgeGrpcClient(); |
@@ -241,7 +245,12 @@ public class EdgeImitator { | @@ -241,7 +245,12 @@ public class EdgeImitator { | ||
241 | 245 | ||
242 | private ListenableFuture<Void> saveDownlinkMsg(AbstractMessage message) { | 246 | private ListenableFuture<Void> saveDownlinkMsg(AbstractMessage message) { |
243 | if (!ignoredTypes.contains(message.getClass())) { | 247 | if (!ignoredTypes.contains(message.getClass())) { |
244 | - downlinkMsgs.add(message); | 248 | + try { |
249 | + lock.lock(); | ||
250 | + downlinkMsgs.add(message); | ||
251 | + } finally { | ||
252 | + lock.unlock(); | ||
253 | + } | ||
245 | messagesLatch.countDown(); | 254 | messagesLatch.countDown(); |
246 | } | 255 | } |
247 | return Futures.immediateFuture(null); | 256 | return Futures.immediateFuture(null); |
@@ -262,7 +271,14 @@ public class EdgeImitator { | @@ -262,7 +271,14 @@ public class EdgeImitator { | ||
262 | } | 271 | } |
263 | 272 | ||
264 | public <T> Optional<T> findMessageByType(Class<T> tClass) { | 273 | public <T> Optional<T> findMessageByType(Class<T> tClass) { |
265 | - return (Optional<T>) downlinkMsgs.stream().filter(downlinkMsg -> downlinkMsg.getClass().isAssignableFrom(tClass)).findAny(); | 274 | + Optional<T> result; |
275 | + try { | ||
276 | + lock.lock(); | ||
277 | + result = (Optional<T>) downlinkMsgs.stream().filter(downlinkMsg -> downlinkMsg.getClass().isAssignableFrom(tClass)).findAny(); | ||
278 | + } finally { | ||
279 | + lock.unlock(); | ||
280 | + } | ||
281 | + return result; | ||
266 | } | 282 | } |
267 | 283 | ||
268 | public AbstractMessage getLatestMessage() { | 284 | public AbstractMessage getLatestMessage() { |
@@ -315,6 +315,7 @@ message AttributesRequestMsg { | @@ -315,6 +315,7 @@ message AttributesRequestMsg { | ||
315 | int64 entityIdMSB = 1; | 315 | int64 entityIdMSB = 1; |
316 | int64 entityIdLSB = 2; | 316 | int64 entityIdLSB = 2; |
317 | string entityType = 3; | 317 | string entityType = 3; |
318 | + string scope = 4; | ||
318 | } | 319 | } |
319 | 320 | ||
320 | message RelationRequestMsg { | 321 | message RelationRequestMsg { |
@@ -105,6 +105,11 @@ public enum MsgType { | @@ -105,6 +105,11 @@ public enum MsgType { | ||
105 | /** | 105 | /** |
106 | * Message that is sent by TransportRuleEngineService to Device Actor. Represents messages from the device itself. | 106 | * Message that is sent by TransportRuleEngineService to Device Actor. Represents messages from the device itself. |
107 | */ | 107 | */ |
108 | - TRANSPORT_TO_DEVICE_ACTOR_MSG; | 108 | + TRANSPORT_TO_DEVICE_ACTOR_MSG, |
109 | + | ||
110 | + /** | ||
111 | + * Message that is sent on Edge Event to Edge Session | ||
112 | + */ | ||
113 | + EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG; | ||
109 | 114 | ||
110 | } | 115 | } |
common/message/src/main/java/org/thingsboard/server/common/msg/edge/EdgeEventUpdateMsg.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.edge; | ||
17 | + | ||
18 | +import lombok.Getter; | ||
19 | +import lombok.ToString; | ||
20 | +import org.thingsboard.server.common.data.id.EdgeId; | ||
21 | +import org.thingsboard.server.common.data.id.TenantId; | ||
22 | +import org.thingsboard.server.common.msg.MsgType; | ||
23 | +import org.thingsboard.server.common.msg.aware.TenantAwareMsg; | ||
24 | +import org.thingsboard.server.common.msg.cluster.ToAllNodesMsg; | ||
25 | + | ||
26 | +@ToString | ||
27 | +public class EdgeEventUpdateMsg implements TenantAwareMsg, ToAllNodesMsg { | ||
28 | + @Getter | ||
29 | + private final TenantId tenantId; | ||
30 | + @Getter | ||
31 | + private final EdgeId edgeId; | ||
32 | + | ||
33 | + public EdgeEventUpdateMsg(TenantId tenantId, EdgeId edgeId) { | ||
34 | + this.tenantId = tenantId; | ||
35 | + this.edgeId = edgeId; | ||
36 | + } | ||
37 | + | ||
38 | + @Override | ||
39 | + public MsgType getMsgType() { | ||
40 | + return MsgType.EDGE_EVENT_UPDATE_TO_EDGE_SESSION_MSG; | ||
41 | + } | ||
42 | +} |
@@ -400,6 +400,7 @@ message ToCoreNotificationMsg { | @@ -400,6 +400,7 @@ message ToCoreNotificationMsg { | ||
400 | LocalSubscriptionServiceMsgProto toLocalSubscriptionServiceMsg = 1; | 400 | LocalSubscriptionServiceMsgProto toLocalSubscriptionServiceMsg = 1; |
401 | FromDeviceRPCResponseProto fromDeviceRpcResponse = 2; | 401 | FromDeviceRPCResponseProto fromDeviceRpcResponse = 2; |
402 | bytes componentLifecycleMsg = 3; | 402 | bytes componentLifecycleMsg = 3; |
403 | + bytes edgeEventUpdateMsg = 4; | ||
403 | } | 404 | } |
404 | 405 | ||
405 | /* Messages that are handled by ThingsBoard RuleEngine Service */ | 406 | /* Messages that are handled by ThingsBoard RuleEngine Service */ |
@@ -98,6 +98,8 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | @@ -98,6 +98,8 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | ||
98 | public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; | 98 | public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; |
99 | public static final String INCORRECT_EDGE_ID = "Incorrect edgeId "; | 99 | public static final String INCORRECT_EDGE_ID = "Incorrect edgeId "; |
100 | 100 | ||
101 | + private static final int DEFAULT_LIMIT = 100; | ||
102 | + | ||
101 | private RestTemplate restTemplate; | 103 | private RestTemplate restTemplate; |
102 | 104 | ||
103 | private static final String EDGE_LICENSE_SERVER_ENDPOINT = "https://license.thingsboard.io"; | 105 | private static final String EDGE_LICENSE_SERVER_ENDPOINT = "https://license.thingsboard.io"; |
@@ -460,8 +462,21 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | @@ -460,8 +462,21 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | ||
460 | public ListenableFuture<List<EdgeId>> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { | 462 | public ListenableFuture<List<EdgeId>> findRelatedEdgeIdsByEntityId(TenantId tenantId, EntityId entityId) { |
461 | log.trace("[{}] Executing findRelatedEdgeIdsByEntityId [{}]", tenantId, entityId); | 463 | log.trace("[{}] Executing findRelatedEdgeIdsByEntityId [{}]", tenantId, entityId); |
462 | if (EntityType.TENANT.equals(entityId.getEntityType())) { | 464 | if (EntityType.TENANT.equals(entityId.getEntityType())) { |
463 | - TextPageData<Edge> edgesByTenantId = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); | ||
464 | - return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList())); | 465 | + List<EdgeId> result = new ArrayList<>(); |
466 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); | ||
467 | + TextPageData<Edge> pageData; | ||
468 | + do { | ||
469 | + pageData = findEdgesByTenantId(tenantId, pageLink); | ||
470 | + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
471 | + for (Edge edge : pageData.getData()) { | ||
472 | + result.add(edge.getId()); | ||
473 | + } | ||
474 | + if (pageData.hasNext()) { | ||
475 | + pageLink = pageData.getNextPageLink(); | ||
476 | + } | ||
477 | + } | ||
478 | + } while (pageData != null && pageData.hasNext()); | ||
479 | + return Futures.immediateFuture(result); | ||
465 | } else { | 480 | } else { |
466 | switch (entityId.getEntityType()) { | 481 | switch (entityId.getEntityType()) { |
467 | case DEVICE: | 482 | case DEVICE: |
@@ -486,13 +501,23 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | @@ -486,13 +501,23 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic | ||
486 | if (userById == null) { | 501 | if (userById == null) { |
487 | return Futures.immediateFuture(Collections.emptyList()); | 502 | return Futures.immediateFuture(Collections.emptyList()); |
488 | } | 503 | } |
489 | - TextPageData<Edge> edges; | ||
490 | - if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { | ||
491 | - edges = findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE)); | ||
492 | - } else { | ||
493 | - edges = findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), new TextPageLink(Integer.MAX_VALUE)); | ||
494 | - } | ||
495 | - return convertToEdgeIds(Futures.immediateFuture(edges.getData())); | 504 | + List<Edge> result = new ArrayList<>(); |
505 | + TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); | ||
506 | + TextPageData<Edge> pageData; | ||
507 | + do { | ||
508 | + if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) { | ||
509 | + pageData = findEdgesByTenantId(tenantId, pageLink); | ||
510 | + } else { | ||
511 | + pageData = findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), pageLink); | ||
512 | + } | ||
513 | + if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { | ||
514 | + result.addAll(pageData.getData()); | ||
515 | + if (pageData.hasNext()) { | ||
516 | + pageLink = pageData.getNextPageLink(); | ||
517 | + } | ||
518 | + } | ||
519 | + } while (pageData != null && pageData.hasNext()); | ||
520 | + return convertToEdgeIds(Futures.immediateFuture(result)); | ||
496 | default: | 521 | default: |
497 | return Futures.immediateFuture(Collections.emptyList()); | 522 | return Futures.immediateFuture(Collections.emptyList()); |
498 | } | 523 | } |
@@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.Customer; | @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.Customer; | ||
23 | import org.thingsboard.server.common.data.Device; | 23 | import org.thingsboard.server.common.data.Device; |
24 | import org.thingsboard.server.common.data.alarm.Alarm; | 24 | import org.thingsboard.server.common.data.alarm.Alarm; |
25 | import org.thingsboard.server.common.data.asset.Asset; | 25 | import org.thingsboard.server.common.data.asset.Asset; |
26 | +import org.thingsboard.server.common.data.id.EdgeId; | ||
26 | import org.thingsboard.server.common.data.id.EntityId; | 27 | import org.thingsboard.server.common.data.id.EntityId; |
27 | import org.thingsboard.server.common.data.id.RuleNodeId; | 28 | import org.thingsboard.server.common.data.id.RuleNodeId; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 29 | import org.thingsboard.server.common.data.id.TenantId; |
@@ -145,6 +146,8 @@ public interface TbContext { | @@ -145,6 +146,8 @@ public interface TbContext { | ||
145 | // TODO: Does this changes the message? | 146 | // TODO: Does this changes the message? |
146 | TbMsg alarmActionMsg(Alarm alarm, RuleNodeId ruleNodeId, String action); | 147 | TbMsg alarmActionMsg(Alarm alarm, RuleNodeId ruleNodeId, String action); |
147 | 148 | ||
149 | + void onEdgeEventUpdate(TenantId tenantId, EdgeId edgeId); | ||
150 | + | ||
148 | /* | 151 | /* |
149 | * | 152 | * |
150 | * METHODS TO PROCESS THE MESSAGES | 153 | * METHODS TO PROCESS THE MESSAGES |
@@ -115,11 +115,12 @@ public class TbMsgPushToEdgeNode implements TbNode { | @@ -115,11 +115,12 @@ public class TbMsgPushToEdgeNode implements TbNode { | ||
115 | @Override | 115 | @Override |
116 | public void onSuccess(@Nullable EdgeEvent event) { | 116 | public void onSuccess(@Nullable EdgeEvent event) { |
117 | ctx.tellNext(msg, SUCCESS); | 117 | ctx.tellNext(msg, SUCCESS); |
118 | + ctx.onEdgeEventUpdate(ctx.getTenantId(), edgeId); | ||
118 | } | 119 | } |
119 | 120 | ||
120 | @Override | 121 | @Override |
121 | public void onFailure(Throwable th) { | 122 | public void onFailure(Throwable th) { |
122 | - log.error("Could not save edge event", th); | 123 | + log.warn("[{}] Can't save edge event [{}] for edge [{}]", ctx.getTenantId().getId(), edgeEvent, edgeId.getId(), th); |
123 | ctx.tellFailure(msg, th); | 124 | ctx.tellFailure(msg, th); |
124 | } | 125 | } |
125 | }, ctx.getDbCallbackExecutor()); | 126 | }, ctx.getDbCallbackExecutor()); |