Commit 600c9ec565fe803e7405b3f6ea9a1c2e6896c23c

Authored by Volodymyr Babak
1 parent e8afd976

Refactoring of notification to edge. Added EdgeNotificationService and queue msg proto

  1 +package org.thingsboard.server.service.edge;
  2 +
  3 +import com.fasterxml.jackson.databind.ObjectMapper;
  4 +import com.google.common.util.concurrent.FutureCallback;
  5 +import com.google.common.util.concurrent.Futures;
  6 +import com.google.common.util.concurrent.ListenableFuture;
  7 +import com.google.common.util.concurrent.MoreExecutors;
  8 +import lombok.extern.slf4j.Slf4j;
  9 +import org.apache.commons.codec.binary.Base64;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Service;
  12 +import org.thingsboard.server.common.data.Dashboard;
  13 +import org.thingsboard.server.common.data.DataConstants;
  14 +import org.thingsboard.server.common.data.Device;
  15 +import org.thingsboard.server.common.data.EntityType;
  16 +import org.thingsboard.server.common.data.EntityView;
  17 +import org.thingsboard.server.common.data.Event;
  18 +import org.thingsboard.server.common.data.alarm.Alarm;
  19 +import org.thingsboard.server.common.data.asset.Asset;
  20 +import org.thingsboard.server.common.data.edge.Edge;
  21 +import org.thingsboard.server.common.data.edge.EdgeQueueEntityType;
  22 +import org.thingsboard.server.common.data.edge.EdgeQueueEntry;
  23 +import org.thingsboard.server.common.data.id.EdgeId;
  24 +import org.thingsboard.server.common.data.id.EntityId;
  25 +import org.thingsboard.server.common.data.id.RuleChainId;
  26 +import org.thingsboard.server.common.data.id.TenantId;
  27 +import org.thingsboard.server.common.data.page.TimePageData;
  28 +import org.thingsboard.server.common.data.page.TimePageLink;
  29 +import org.thingsboard.server.common.data.relation.EntityRelation;
  30 +import org.thingsboard.server.common.data.relation.RelationTypeGroup;
  31 +import org.thingsboard.server.common.data.rule.RuleChain;
  32 +import org.thingsboard.server.common.data.rule.RuleChainMetaData;
  33 +import org.thingsboard.server.common.data.rule.RuleChainType;
  34 +import org.thingsboard.server.common.msg.TbMsg;
  35 +import org.thingsboard.server.common.msg.queue.TbCallback;
  36 +import org.thingsboard.server.common.msg.session.SessionMsgType;
  37 +import org.thingsboard.server.dao.asset.AssetService;
  38 +import org.thingsboard.server.dao.device.DeviceService;
  39 +import org.thingsboard.server.dao.edge.EdgeService;
  40 +import org.thingsboard.server.dao.entityview.EntityViewService;
  41 +import org.thingsboard.server.dao.event.EventService;
  42 +import org.thingsboard.server.dao.relation.RelationService;
  43 +import org.thingsboard.server.dao.rule.RuleChainService;
  44 +import org.thingsboard.server.gen.transport.TransportProtos;
  45 +import org.thingsboard.server.queue.util.TbCoreComponent;
  46 +
  47 +import javax.annotation.Nullable;
  48 +import javax.annotation.PostConstruct;
  49 +import javax.annotation.PreDestroy;
  50 +import java.io.IOException;
  51 +import java.util.List;
  52 +import java.util.UUID;
  53 +import java.util.concurrent.ExecutorService;
  54 +import java.util.concurrent.Executors;
  55 +
  56 +@Service
  57 +@TbCoreComponent
  58 +@Slf4j
  59 +public class DefaultEdgeNotificationService implements EdgeNotificationService {
  60 +
  61 + private static final ObjectMapper mapper = new ObjectMapper();
  62 +
  63 + @Autowired
  64 + private EdgeService edgeService;
  65 +
  66 + @Autowired
  67 + private DeviceService deviceService;
  68 +
  69 + @Autowired
  70 + private AssetService assetService;
  71 +
  72 + @Autowired
  73 + private EntityViewService entityViewService;
  74 +
  75 + @Autowired
  76 + private RuleChainService ruleChainService;
  77 +
  78 + @Autowired
  79 + private RelationService relationService;
  80 +
  81 + @Autowired
  82 + private EventService eventService;
  83 +
  84 + private ExecutorService tsCallBackExecutor;
  85 +
  86 + @PostConstruct
  87 + public void initExecutor() {
  88 + tsCallBackExecutor = Executors.newSingleThreadExecutor();
  89 + }
  90 +
  91 + @PreDestroy
  92 + public void shutdownExecutor() {
  93 + if (tsCallBackExecutor != null) {
  94 + tsCallBackExecutor.shutdownNow();
  95 + }
  96 + }
  97 +
  98 + @Override
  99 + public TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
  100 + return eventService.findEvents(tenantId, edgeId, DataConstants.EDGE_QUEUE_EVENT_TYPE, pageLink);
  101 + }
  102 +
  103 + @Override
  104 + public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException {
  105 + edge.setRootRuleChainId(ruleChainId);
  106 + Edge savedEdge = edgeService.saveEdge(edge);
  107 + RuleChain ruleChain = ruleChainService.findRuleChainById(tenantId, ruleChainId);
  108 + saveEventToEdgeQueue(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, DataConstants.ENTITY_UPDATED, mapper.writeValueAsString(ruleChain), new FutureCallback<Void>() {
  109 + @Override
  110 + public void onSuccess(@Nullable Void aVoid) {
  111 + log.debug("Event saved successfully!");
  112 + }
  113 +
  114 + @Override
  115 + public void onFailure(Throwable t) {
  116 + log.debug("Failure during event save", t);
  117 + }
  118 + });
  119 + return savedEdge;
  120 + }
  121 +
  122 + private void saveEventToEdgeQueue(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, String type, String data, FutureCallback<Void> callback) throws IOException {
  123 + log.debug("Pushing single event to edge queue. tenantId [{}], edgeId [{}], entityType [{}], type[{}], data [{}]", tenantId, edgeId, entityType, type, data);
  124 +
  125 + EdgeQueueEntry queueEntry = new EdgeQueueEntry();
  126 + queueEntry.setEntityType(entityType);
  127 + queueEntry.setType(type);
  128 + queueEntry.setData(data);
  129 +
  130 + Event event = new Event();
  131 + event.setEntityId(edgeId);
  132 + event.setTenantId(tenantId);
  133 + event.setType(DataConstants.EDGE_QUEUE_EVENT_TYPE);
  134 + event.setBody(mapper.valueToTree(queueEntry));
  135 + ListenableFuture<Event> saveFuture = eventService.saveAsync(event);
  136 +
  137 + addMainCallback(saveFuture, callback);
  138 + }
  139 +
  140 + private void addMainCallback(ListenableFuture<Event> saveFuture, final FutureCallback<Void> callback) {
  141 + Futures.addCallback(saveFuture, new FutureCallback<Event>() {
  142 + @Override
  143 + public void onSuccess(@Nullable Event result) {
  144 + callback.onSuccess(null);
  145 + }
  146 +
  147 + @Override
  148 + public void onFailure(Throwable t) {
  149 + callback.onFailure(t);
  150 + }
  151 + }, tsCallBackExecutor);
  152 + }
  153 +
  154 + @Override
  155 + public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) {
  156 + if (tbMsg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) ||
  157 + tbMsg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||
  158 + tbMsg.getType().equals(DataConstants.ATTRIBUTES_UPDATED) ||
  159 + tbMsg.getType().equals(DataConstants.ATTRIBUTES_DELETED)) {
  160 + processCustomTbMsg(tenantId, tbMsg, callback);
  161 + } else {
  162 + try {
  163 + switch (tbMsg.getOriginator().getEntityType()) {
  164 + case EDGE:
  165 + processEdge(tenantId, tbMsg, callback);
  166 + break;
  167 + case ASSET:
  168 + processAsset(tenantId, tbMsg, callback);
  169 + break;
  170 + case DEVICE:
  171 + processDevice(tenantId, tbMsg, callback);
  172 + break;
  173 + case DASHBOARD:
  174 + processDashboard(tenantId, tbMsg, callback);
  175 + break;
  176 + case RULE_CHAIN:
  177 + processRuleChain(tenantId, tbMsg, callback);
  178 + break;
  179 + case ENTITY_VIEW:
  180 + processEntityView(tenantId, tbMsg, callback);
  181 + break;
  182 + case ALARM:
  183 + processAlarm(tenantId, tbMsg, callback);
  184 + break;
  185 + default:
  186 + log.debug("Entity type [{}] is not designed to be pushed to edge", tbMsg.getOriginator().getEntityType());
  187 + }
  188 + } catch (IOException e) {
  189 + log.error("Can't push to edge updates, entity type [{}], data [{}]", tbMsg.getOriginator().getEntityType(), tbMsg.getData(), e);
  190 + }
  191 + }
  192 + }
  193 +
  194 +
  195 + private void processCustomTbMsg(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) {
  196 + ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, tbMsg.getOriginator());
  197 + Futures.transform(edgeIdFuture, edgeId -> {
  198 + EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(tbMsg.getOriginator().getEntityType());
  199 + if (edgeId != null && edgeQueueEntityType != null) {
  200 + try {
  201 + saveEventToEdgeQueue(tenantId, edgeId, edgeQueueEntityType, tbMsg.getType(), Base64.encodeBase64String(TbMsg.toByteArray(tbMsg)), callback);
  202 + } catch (IOException e) {
  203 + log.error("Error while saving custom tbMsg into Edge Queue", e);
  204 + }
  205 + }
  206 + return null;
  207 + }, MoreExecutors.directExecutor());
  208 + }
  209 +
  210 + private void processDevice(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  211 + switch (tbMsg.getType()) {
  212 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  213 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  214 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DEVICE, callback);
  215 + break;
  216 + case DataConstants.ENTITY_DELETED:
  217 + case DataConstants.ENTITY_CREATED:
  218 + case DataConstants.ENTITY_UPDATED:
  219 + Device device = mapper.readValue(tbMsg.getData(), Device.class);
  220 + pushEventToEdge(tenantId, device.getId(), EdgeQueueEntityType.DEVICE, tbMsg, callback);
  221 + break;
  222 + default:
  223 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  224 + }
  225 + }
  226 +
  227 + private void processEdge(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  228 + switch (tbMsg.getType()) {
  229 + case DataConstants.ENTITY_DELETED:
  230 + case DataConstants.ENTITY_CREATED:
  231 + case DataConstants.ENTITY_UPDATED:
  232 + // TODO: voba - handle properly edge creation
  233 + break;
  234 + default:
  235 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  236 + }
  237 + }
  238 +
  239 + private void processAsset(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  240 + switch (tbMsg.getType()) {
  241 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  242 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  243 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ASSET, callback);
  244 + break;
  245 + case DataConstants.ENTITY_DELETED:
  246 + case DataConstants.ENTITY_CREATED:
  247 + case DataConstants.ENTITY_UPDATED:
  248 + Asset asset = mapper.readValue(tbMsg.getData(), Asset.class);
  249 + pushEventToEdge(tenantId, asset.getId(), EdgeQueueEntityType.ASSET, tbMsg, callback);
  250 + break;
  251 + default:
  252 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  253 + }
  254 + }
  255 +
  256 + private void processEntityView(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  257 + switch (tbMsg.getType()) {
  258 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  259 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  260 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ENTITY_VIEW, callback);
  261 + break;
  262 + case DataConstants.ENTITY_DELETED:
  263 + case DataConstants.ENTITY_CREATED:
  264 + case DataConstants.ENTITY_UPDATED:
  265 + EntityView entityView = mapper.readValue(tbMsg.getData(), EntityView.class);
  266 + pushEventToEdge(tenantId, entityView.getId(), EdgeQueueEntityType.ENTITY_VIEW, tbMsg, callback);
  267 + break;
  268 + default:
  269 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  270 + }
  271 + }
  272 +
  273 + private void processAlarm(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  274 + switch (tbMsg.getType()) {
  275 + case DataConstants.ENTITY_DELETED:
  276 + case DataConstants.ENTITY_CREATED:
  277 + case DataConstants.ENTITY_UPDATED:
  278 + case DataConstants.ALARM_ACK:
  279 + case DataConstants.ALARM_CLEAR:
  280 + Alarm alarm = mapper.readValue(tbMsg.getData(), Alarm.class);
  281 + EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType());
  282 + if (edgeQueueEntityType != null) {
  283 + pushEventToEdge(tenantId, alarm.getOriginator(), EdgeQueueEntityType.ALARM, tbMsg, callback);
  284 + }
  285 + break;
  286 + default:
  287 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  288 + }
  289 + }
  290 +
  291 + private void processDashboard(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  292 + switch (tbMsg.getType()) {
  293 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  294 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  295 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DASHBOARD, callback);
  296 + break;
  297 + case DataConstants.ENTITY_DELETED:
  298 + case DataConstants.ENTITY_CREATED:
  299 + case DataConstants.ENTITY_UPDATED:
  300 + Dashboard dashboard = mapper.readValue(tbMsg.getData(), Dashboard.class);
  301 + ListenableFuture<TimePageData<Edge>> future = edgeService.findEdgesByTenantIdAndDashboardId(tenantId, dashboard.getId(), new TimePageLink(Integer.MAX_VALUE));
  302 + Futures.transform(future, edges -> {
  303 + if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {
  304 + try {
  305 + for (Edge edge : edges.getData()) {
  306 + pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.DASHBOARD, tbMsg, callback);
  307 + }
  308 + } catch (IOException e) {
  309 + log.error("Can't push event to edge", e);
  310 + }
  311 + }
  312 + return null;
  313 + }, MoreExecutors.directExecutor());
  314 + break;
  315 + default:
  316 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  317 + }
  318 + }
  319 +
  320 + private void processRuleChain(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  321 + switch (tbMsg.getType()) {
  322 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  323 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  324 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.RULE_CHAIN, callback);
  325 + break;
  326 + case DataConstants.ENTITY_DELETED:
  327 + case DataConstants.ENTITY_CREATED:
  328 + case DataConstants.ENTITY_UPDATED:
  329 + RuleChain ruleChain = mapper.readValue(tbMsg.getData(), RuleChain.class);
  330 + if (RuleChainType.EDGE.equals(ruleChain.getType())) {
  331 + ListenableFuture<TimePageData<Edge>> future = edgeService.findEdgesByTenantIdAndRuleChainId(tenantId, ruleChain.getId(), new TimePageLink(Integer.MAX_VALUE));
  332 + Futures.transform(future, edges -> {
  333 + if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {
  334 + try {
  335 + for (Edge edge : edges.getData()) {
  336 + pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, tbMsg, callback);
  337 + }
  338 + } catch (IOException e) {
  339 + log.error("Can't push event to edge", e);
  340 + }
  341 + }
  342 + return null;
  343 + }, MoreExecutors.directExecutor());
  344 + }
  345 + break;
  346 + default:
  347 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  348 + }
  349 + }
  350 +
  351 +
  352 + private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EdgeQueueEntityType entityType, FutureCallback<Void> callback) throws IOException {
  353 + EdgeId edgeId;
  354 + switch (tbMsg.getType()) {
  355 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  356 + edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("assignedEdgeId")));
  357 + pushEventToEdge(tenantId, edgeId, entityType, tbMsg, callback);
  358 + break;
  359 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  360 + edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("unassignedEdgeId")));
  361 + pushEventToEdge(tenantId, edgeId, entityType, tbMsg, callback);
  362 + break;
  363 +
  364 + }
  365 + }
  366 +
  367 +
  368 + private void pushEventToEdge(TenantId tenantId, EntityId originatorId, EdgeQueueEntityType edgeQueueEntityType, TbMsg tbMsg, FutureCallback<Void> callback) {
  369 + ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, originatorId);
  370 + Futures.transform(edgeIdFuture, edgeId -> {
  371 + if (edgeId != null) {
  372 + try {
  373 + pushEventToEdge(tenantId, edgeId, edgeQueueEntityType, tbMsg, callback);
  374 + } catch (Exception e) {
  375 + log.error("Failed to push event to edge, edgeId [{}], tbMsg [{}]", edgeId, tbMsg, e);
  376 + }
  377 + }
  378 + return null;
  379 + },
  380 + MoreExecutors.directExecutor());
  381 + }
  382 +
  383 +
  384 + private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TenantId tenantId, EntityId originatorId) {
  385 + List<EntityRelation> originatorEdgeRelations = relationService.findByToAndType(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
  386 + if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) {
  387 + return Futures.immediateFuture(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId()));
  388 + } else {
  389 + return Futures.immediateFuture(null);
  390 + }
  391 + }
  392 +
  393 +
  394 + private void pushEventToEdge(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  395 + log.debug("Pushing event(s) to edge queue. tenantId [{}], edgeId [{}], entityType [{}], tbMsg [{}]", tenantId, edgeId, entityType, tbMsg);
  396 +
  397 + saveEventToEdgeQueue(tenantId, edgeId, entityType, tbMsg.getType(), tbMsg.getData(), callback);
  398 +
  399 + if (entityType.equals(EdgeQueueEntityType.RULE_CHAIN)) {
  400 + pushRuleChainMetadataToEdge(tenantId, edgeId, tbMsg, callback);
  401 + }
  402 + }
  403 +
  404 + private void pushRuleChainMetadataToEdge(TenantId tenantId, EdgeId edgeId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {
  405 + RuleChain ruleChain = mapper.readValue(tbMsg.getData(), RuleChain.class);
  406 + switch (tbMsg.getType()) {
  407 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  408 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  409 + case DataConstants.ENTITY_UPDATED:
  410 + RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, ruleChain.getId());
  411 + saveEventToEdgeQueue(tenantId, edgeId, EdgeQueueEntityType.RULE_CHAIN_METADATA, tbMsg.getType(), mapper.writeValueAsString(ruleChainMetaData), callback);
  412 + break;
  413 + default:
  414 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  415 + }
  416 + }
  417 +
  418 +
  419 + private EdgeQueueEntityType getEdgeQueueTypeByEntityType(EntityType entityType) {
  420 + switch (entityType) {
  421 + case DEVICE:
  422 + return EdgeQueueEntityType.DEVICE;
  423 + case ASSET:
  424 + return EdgeQueueEntityType.ASSET;
  425 + case ENTITY_VIEW:
  426 + return EdgeQueueEntityType.ENTITY_VIEW;
  427 + default:
  428 + log.info("Unsupported entity type: [{}]", entityType);
  429 + return null;
  430 + }
  431 + }
  432 +}
  433 +
@@ -55,6 +55,10 @@ public class EdgeContextComponent { @@ -55,6 +55,10 @@ public class EdgeContextComponent {
55 55
56 @Lazy 56 @Lazy
57 @Autowired 57 @Autowired
  58 + private EdgeNotificationService edgeNotificationService;
  59 +
  60 + @Lazy
  61 + @Autowired
58 private AssetService assetService; 62 private AssetService assetService;
59 63
60 @Lazy 64 @Lazy
  1 +package org.thingsboard.server.service.edge;
  2 +
  3 +import org.thingsboard.server.common.data.Event;
  4 +import org.thingsboard.server.common.data.edge.Edge;
  5 +import org.thingsboard.server.common.data.id.EdgeId;
  6 +import org.thingsboard.server.common.data.id.RuleChainId;
  7 +import org.thingsboard.server.common.data.id.TenantId;
  8 +import org.thingsboard.server.common.data.page.TimePageData;
  9 +import org.thingsboard.server.common.data.page.TimePageLink;
  10 +import org.thingsboard.server.common.msg.queue.TbCallback;
  11 +import org.thingsboard.server.gen.transport.TransportProtos;
  12 +
  13 +import java.io.IOException;
  14 +
  15 +public interface EdgeNotificationService {
  16 +
  17 + TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);
  18 +
  19 + Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException;
  20 +
  21 + void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback);
  22 +}
@@ -172,7 +172,7 @@ public final class EdgeGrpcSession implements Closeable { @@ -172,7 +172,7 @@ public final class EdgeGrpcSession implements Closeable {
172 TimePageData<Event> pageData; 172 TimePageData<Event> pageData;
173 UUID ifOffset = null; 173 UUID ifOffset = null;
174 do { 174 do {
175 - pageData = ctx.getEdgeService().findQueueEvents(edge.getTenantId(), edge.getId(), pageLink); 175 + pageData = ctx.getEdgeNotificationService().findQueueEvents(edge.getTenantId(), edge.getId(), pageLink);
176 if (isConnected() && !pageData.getData().isEmpty()) { 176 if (isConnected() && !pageData.getData().isEmpty()) {
177 log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size()); 177 log.trace("[{}] [{}] event(s) are going to be processed.", this.sessionId, pageData.getData().size());
178 for (Event event : pageData.getData()) { 178 for (Event event : pageData.getData()) {
@@ -28,6 +28,7 @@ import org.thingsboard.server.common.msg.TbActorMsg; @@ -28,6 +28,7 @@ import org.thingsboard.server.common.msg.TbActorMsg;
28 import org.thingsboard.server.common.msg.queue.ServiceType; 28 import org.thingsboard.server.common.msg.queue.ServiceType;
29 import org.thingsboard.server.common.msg.queue.TbCallback; 29 import org.thingsboard.server.common.msg.queue.TbCallback;
30 import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; 30 import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto;
  31 +import org.thingsboard.server.gen.transport.TransportProtos.EdgeNotificationMsgProto;
31 import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto; 32 import org.thingsboard.server.gen.transport.TransportProtos.FromDeviceRPCResponseProto;
32 import org.thingsboard.server.gen.transport.TransportProtos.LocalSubscriptionServiceMsgProto; 33 import org.thingsboard.server.gen.transport.TransportProtos.LocalSubscriptionServiceMsgProto;
33 import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionMgrMsgProto; 34 import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionMgrMsgProto;
@@ -42,6 +43,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; @@ -42,6 +43,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg;
42 import org.thingsboard.server.queue.discovery.PartitionChangeEvent; 43 import org.thingsboard.server.queue.discovery.PartitionChangeEvent;
43 import org.thingsboard.server.queue.provider.TbCoreQueueFactory; 44 import org.thingsboard.server.queue.provider.TbCoreQueueFactory;
44 import org.thingsboard.server.queue.util.TbCoreComponent; 45 import org.thingsboard.server.queue.util.TbCoreComponent;
  46 +import org.thingsboard.server.service.edge.EdgeNotificationService;
45 import org.thingsboard.server.service.encoding.DataDecodingEncodingService; 47 import org.thingsboard.server.service.encoding.DataDecodingEncodingService;
46 import org.thingsboard.server.service.queue.processing.AbstractConsumerService; 48 import org.thingsboard.server.service.queue.processing.AbstractConsumerService;
47 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse; 49 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
@@ -82,18 +84,20 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -82,18 +84,20 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
82 private final TbLocalSubscriptionService localSubscriptionService; 84 private final TbLocalSubscriptionService localSubscriptionService;
83 private final SubscriptionManagerService subscriptionManagerService; 85 private final SubscriptionManagerService subscriptionManagerService;
84 private final TbCoreDeviceRpcService tbCoreDeviceRpcService; 86 private final TbCoreDeviceRpcService tbCoreDeviceRpcService;
  87 + private final EdgeNotificationService edgeNotificationService;
85 private final TbCoreConsumerStats stats = new TbCoreConsumerStats(); 88 private final TbCoreConsumerStats stats = new TbCoreConsumerStats();
86 89
87 public DefaultTbCoreConsumerService(TbCoreQueueFactory tbCoreQueueFactory, ActorSystemContext actorContext, 90 public DefaultTbCoreConsumerService(TbCoreQueueFactory tbCoreQueueFactory, ActorSystemContext actorContext,
88 DeviceStateService stateService, TbLocalSubscriptionService localSubscriptionService, 91 DeviceStateService stateService, TbLocalSubscriptionService localSubscriptionService,
89 SubscriptionManagerService subscriptionManagerService, DataDecodingEncodingService encodingService, 92 SubscriptionManagerService subscriptionManagerService, DataDecodingEncodingService encodingService,
90 - TbCoreDeviceRpcService tbCoreDeviceRpcService) { 93 + TbCoreDeviceRpcService tbCoreDeviceRpcService, EdgeNotificationService edgeNotificationService) {
91 super(actorContext, encodingService, tbCoreQueueFactory.createToCoreNotificationsMsgConsumer()); 94 super(actorContext, encodingService, tbCoreQueueFactory.createToCoreNotificationsMsgConsumer());
92 this.mainConsumer = tbCoreQueueFactory.createToCoreMsgConsumer(); 95 this.mainConsumer = tbCoreQueueFactory.createToCoreMsgConsumer();
93 this.stateService = stateService; 96 this.stateService = stateService;
94 this.localSubscriptionService = localSubscriptionService; 97 this.localSubscriptionService = localSubscriptionService;
95 this.subscriptionManagerService = subscriptionManagerService; 98 this.subscriptionManagerService = subscriptionManagerService;
96 this.tbCoreDeviceRpcService = tbCoreDeviceRpcService; 99 this.tbCoreDeviceRpcService = tbCoreDeviceRpcService;
  100 + this.edgeNotificationService = edgeNotificationService;
97 } 101 }
98 102
99 @PostConstruct 103 @PostConstruct
@@ -142,6 +146,9 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -142,6 +146,9 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
142 } else if (toCoreMsg.hasDeviceStateServiceMsg()) { 146 } else if (toCoreMsg.hasDeviceStateServiceMsg()) {
143 log.trace("[{}] Forwarding message to state service {}", id, toCoreMsg.getDeviceStateServiceMsg()); 147 log.trace("[{}] Forwarding message to state service {}", id, toCoreMsg.getDeviceStateServiceMsg());
144 forwardToStateService(toCoreMsg.getDeviceStateServiceMsg(), callback); 148 forwardToStateService(toCoreMsg.getDeviceStateServiceMsg(), callback);
  149 + } else if (toCoreMsg.hasEdgeNotificationMsg()) {
  150 + log.trace("[{}] Forwarding message to edge service {}", id, toCoreMsg.getEdgeNotificationMsg());
  151 + forwardToEdgeNotificationService(toCoreMsg.getEdgeNotificationMsg(), callback);
145 } else if (toCoreMsg.getToDeviceActorNotificationMsg() != null && !toCoreMsg.getToDeviceActorNotificationMsg().isEmpty()) { 152 } else if (toCoreMsg.getToDeviceActorNotificationMsg() != null && !toCoreMsg.getToDeviceActorNotificationMsg().isEmpty()) {
146 Optional<TbActorMsg> actorMsg = encodingService.decode(toCoreMsg.getToDeviceActorNotificationMsg().toByteArray()); 153 Optional<TbActorMsg> actorMsg = encodingService.decode(toCoreMsg.getToDeviceActorNotificationMsg().toByteArray());
147 if (actorMsg.isPresent()) { 154 if (actorMsg.isPresent()) {
@@ -275,6 +282,13 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore @@ -275,6 +282,13 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
275 stateService.onQueueMsg(deviceStateServiceMsg, callback); 282 stateService.onQueueMsg(deviceStateServiceMsg, callback);
276 } 283 }
277 284
  285 + private void forwardToEdgeNotificationService(EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) {
  286 + if (statsEnabled) {
  287 + stats.log(edgeNotificationMsg);
  288 + }
  289 + edgeNotificationService.pushNotificationToEdge(edgeNotificationMsg, callback);
  290 + }
  291 +
278 private void forwardToDeviceActor(TransportToDeviceActorMsg toDeviceActorMsg, TbCallback callback) { 292 private void forwardToDeviceActor(TransportToDeviceActorMsg toDeviceActorMsg, TbCallback callback) {
279 if (statsEnabled) { 293 if (statsEnabled) {
280 stats.log(toDeviceActorMsg); 294 stats.log(toDeviceActorMsg);
@@ -33,6 +33,7 @@ public class TbCoreConsumerStats { @@ -33,6 +33,7 @@ public class TbCoreConsumerStats {
33 private final AtomicInteger claimDeviceCounter = new AtomicInteger(0); 33 private final AtomicInteger claimDeviceCounter = new AtomicInteger(0);
34 34
35 private final AtomicInteger deviceStateCounter = new AtomicInteger(0); 35 private final AtomicInteger deviceStateCounter = new AtomicInteger(0);
  36 + private final AtomicInteger edgeNotificationCounter = new AtomicInteger(0);
36 private final AtomicInteger subscriptionMsgCounter = new AtomicInteger(0); 37 private final AtomicInteger subscriptionMsgCounter = new AtomicInteger(0);
37 private final AtomicInteger toCoreNotificationsCounter = new AtomicInteger(0); 38 private final AtomicInteger toCoreNotificationsCounter = new AtomicInteger(0);
38 39
@@ -66,6 +67,11 @@ public class TbCoreConsumerStats { @@ -66,6 +67,11 @@ public class TbCoreConsumerStats {
66 deviceStateCounter.incrementAndGet(); 67 deviceStateCounter.incrementAndGet();
67 } 68 }
68 69
  70 + public void log(TransportProtos.EdgeNotificationMsgProto msg) {
  71 + totalCounter.incrementAndGet();
  72 + edgeNotificationCounter.incrementAndGet();
  73 + }
  74 +
69 public void log(TransportProtos.SubscriptionMgrMsgProto msg) { 75 public void log(TransportProtos.SubscriptionMgrMsgProto msg) {
70 totalCounter.incrementAndGet(); 76 totalCounter.incrementAndGet();
71 subscriptionMsgCounter.incrementAndGet(); 77 subscriptionMsgCounter.incrementAndGet();
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at 6 * You may obtain a copy of the License at
7 * 7 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 + * http://www.apache.org/licenses/LICENSE-2.0
9 * 9 *
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,10 +15,8 @@ @@ -15,10 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.dao.edge; 16 package org.thingsboard.server.dao.edge;
17 17
18 -import com.google.common.util.concurrent.FutureCallback;  
19 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
20 import org.thingsboard.server.common.data.EntitySubtype; 19 import org.thingsboard.server.common.data.EntitySubtype;
21 -import org.thingsboard.server.common.data.Event;  
22 import org.thingsboard.server.common.data.edge.Edge; 20 import org.thingsboard.server.common.data.edge.Edge;
23 import org.thingsboard.server.common.data.edge.EdgeSearchQuery; 21 import org.thingsboard.server.common.data.edge.EdgeSearchQuery;
24 import org.thingsboard.server.common.data.id.CustomerId; 22 import org.thingsboard.server.common.data.id.CustomerId;
@@ -30,13 +28,9 @@ import org.thingsboard.server.common.data.page.TextPageData; @@ -30,13 +28,9 @@ import org.thingsboard.server.common.data.page.TextPageData;
30 import org.thingsboard.server.common.data.page.TextPageLink; 28 import org.thingsboard.server.common.data.page.TextPageLink;
31 import org.thingsboard.server.common.data.page.TimePageData; 29 import org.thingsboard.server.common.data.page.TimePageData;
32 import org.thingsboard.server.common.data.page.TimePageLink; 30 import org.thingsboard.server.common.data.page.TimePageLink;
33 -import org.thingsboard.server.common.data.rule.RuleChain;  
34 -import org.thingsboard.server.common.msg.TbMsg;  
35 31
36 -import java.io.IOException;  
37 import java.util.List; 32 import java.util.List;
38 import java.util.Optional; 33 import java.util.Optional;
39 -import java.util.UUID;  
40 34
41 public interface EdgeService { 35 public interface EdgeService {
42 36
@@ -76,11 +70,6 @@ public interface EdgeService { @@ -76,11 +70,6 @@ public interface EdgeService {
76 70
77 ListenableFuture<List<EntitySubtype>> findEdgeTypesByTenantId(TenantId tenantId); 71 ListenableFuture<List<EntitySubtype>> findEdgeTypesByTenantId(TenantId tenantId);
78 72
79 - void pushEventToEdge(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback);  
80 -  
81 - TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink);  
82 -  
83 - Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException;  
84 73
85 void assignDefaultRuleChainsToEdge(TenantId tenantId, EdgeId edgeId); 74 void assignDefaultRuleChainsToEdge(TenantId tenantId, EdgeId edgeId);
86 75
@@ -352,6 +352,12 @@ message FromDeviceRPCResponseProto { @@ -352,6 +352,12 @@ message FromDeviceRPCResponseProto {
352 string response = 3; 352 string response = 3;
353 int32 error = 4; 353 int32 error = 4;
354 } 354 }
  355 +
  356 +message EdgeNotificationMsgProto {
  357 + int64 tenantIdMSB = 1;
  358 + int64 tenantIdLSB = 2;
  359 +}
  360 +
355 /** 361 /**
356 * Main messages; 362 * Main messages;
357 */ 363 */
@@ -377,6 +383,7 @@ message ToCoreMsg { @@ -377,6 +383,7 @@ message ToCoreMsg {
377 DeviceStateServiceMsgProto deviceStateServiceMsg = 2; 383 DeviceStateServiceMsgProto deviceStateServiceMsg = 2;
378 SubscriptionMgrMsgProto toSubscriptionMgrMsg = 3; 384 SubscriptionMgrMsgProto toSubscriptionMgrMsg = 3;
379 bytes toDeviceActorNotificationMsg = 4; 385 bytes toDeviceActorNotificationMsg = 4;
  386 + EdgeNotificationMsgProto edgeNotificationMsg = 5;
380 } 387 }
381 388
382 /* High priority messages with low latency are handled by ThingsBoard Core Service separately */ 389 /* High priority messages with low latency are handled by ThingsBoard Core Service separately */
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at 6 * You may obtain a copy of the License at
7 * 7 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 8 + * http://www.apache.org/licenses/LICENSE-2.0
9 * 9 *
10 * Unless required by applicable law or agreed to in writing, software 10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, 11 * distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,14 +15,11 @@ @@ -15,14 +15,11 @@
15 */ 15 */
16 package org.thingsboard.server.dao.edge; 16 package org.thingsboard.server.dao.edge;
17 17
18 -import com.fasterxml.jackson.databind.ObjectMapper;  
19 import com.google.common.base.Function; 18 import com.google.common.base.Function;
20 -import com.google.common.util.concurrent.FutureCallback;  
21 import com.google.common.util.concurrent.Futures; 19 import com.google.common.util.concurrent.Futures;
22 import com.google.common.util.concurrent.ListenableFuture; 20 import com.google.common.util.concurrent.ListenableFuture;
23 import com.google.common.util.concurrent.MoreExecutors; 21 import com.google.common.util.concurrent.MoreExecutors;
24 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
25 -import org.apache.commons.codec.binary.Base64;  
26 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.cache.Cache; 24 import org.springframework.cache.Cache;
28 import org.springframework.cache.CacheManager; 25 import org.springframework.cache.CacheManager;
@@ -31,19 +28,10 @@ import org.springframework.cache.annotation.Cacheable; @@ -31,19 +28,10 @@ import org.springframework.cache.annotation.Cacheable;
31 import org.springframework.stereotype.Service; 28 import org.springframework.stereotype.Service;
32 import org.springframework.util.StringUtils; 29 import org.springframework.util.StringUtils;
33 import org.thingsboard.server.common.data.Customer; 30 import org.thingsboard.server.common.data.Customer;
34 -import org.thingsboard.server.common.data.Dashboard;  
35 -import org.thingsboard.server.common.data.DataConstants;  
36 -import org.thingsboard.server.common.data.Device;  
37 import org.thingsboard.server.common.data.EntitySubtype; 31 import org.thingsboard.server.common.data.EntitySubtype;
38 import org.thingsboard.server.common.data.EntityType; 32 import org.thingsboard.server.common.data.EntityType;
39 -import org.thingsboard.server.common.data.EntityView;  
40 -import org.thingsboard.server.common.data.Event;  
41 import org.thingsboard.server.common.data.Tenant; 33 import org.thingsboard.server.common.data.Tenant;
42 -import org.thingsboard.server.common.data.alarm.Alarm;  
43 -import org.thingsboard.server.common.data.asset.Asset;  
44 import org.thingsboard.server.common.data.edge.Edge; 34 import org.thingsboard.server.common.data.edge.Edge;
45 -import org.thingsboard.server.common.data.edge.EdgeQueueEntityType;  
46 -import org.thingsboard.server.common.data.edge.EdgeQueueEntry;  
47 import org.thingsboard.server.common.data.edge.EdgeSearchQuery; 35 import org.thingsboard.server.common.data.edge.EdgeSearchQuery;
48 import org.thingsboard.server.common.data.id.CustomerId; 36 import org.thingsboard.server.common.data.id.CustomerId;
49 import org.thingsboard.server.common.data.id.DashboardId; 37 import org.thingsboard.server.common.data.id.DashboardId;
@@ -57,19 +45,10 @@ import org.thingsboard.server.common.data.page.TimePageData; @@ -57,19 +45,10 @@ import org.thingsboard.server.common.data.page.TimePageData;
57 import org.thingsboard.server.common.data.page.TimePageLink; 45 import org.thingsboard.server.common.data.page.TimePageLink;
58 import org.thingsboard.server.common.data.relation.EntityRelation; 46 import org.thingsboard.server.common.data.relation.EntityRelation;
59 import org.thingsboard.server.common.data.relation.EntitySearchDirection; 47 import org.thingsboard.server.common.data.relation.EntitySearchDirection;
60 -import org.thingsboard.server.common.data.relation.RelationTypeGroup;  
61 import org.thingsboard.server.common.data.rule.RuleChain; 48 import org.thingsboard.server.common.data.rule.RuleChain;
62 -import org.thingsboard.server.common.data.rule.RuleChainMetaData;  
63 -import org.thingsboard.server.common.data.rule.RuleChainType;  
64 -import org.thingsboard.server.common.msg.TbMsg;  
65 -import org.thingsboard.server.common.msg.session.SessionMsgType;  
66 -import org.thingsboard.server.dao.asset.AssetService;  
67 import org.thingsboard.server.dao.customer.CustomerDao; 49 import org.thingsboard.server.dao.customer.CustomerDao;
68 import org.thingsboard.server.dao.dashboard.DashboardService; 50 import org.thingsboard.server.dao.dashboard.DashboardService;
69 -import org.thingsboard.server.dao.device.DeviceService;  
70 import org.thingsboard.server.dao.entity.AbstractEntityService; 51 import org.thingsboard.server.dao.entity.AbstractEntityService;
71 -import org.thingsboard.server.dao.entityview.EntityViewService;  
72 -import org.thingsboard.server.dao.event.EventService;  
73 import org.thingsboard.server.dao.exception.DataValidationException; 52 import org.thingsboard.server.dao.exception.DataValidationException;
74 import org.thingsboard.server.dao.relation.RelationService; 53 import org.thingsboard.server.dao.relation.RelationService;
75 import org.thingsboard.server.dao.rule.RuleChainService; 54 import org.thingsboard.server.dao.rule.RuleChainService;
@@ -79,17 +58,11 @@ import org.thingsboard.server.dao.service.Validator; @@ -79,17 +58,11 @@ import org.thingsboard.server.dao.service.Validator;
79 import org.thingsboard.server.dao.tenant.TenantDao; 58 import org.thingsboard.server.dao.tenant.TenantDao;
80 59
81 import javax.annotation.Nullable; 60 import javax.annotation.Nullable;
82 -import javax.annotation.PostConstruct;  
83 -import javax.annotation.PreDestroy;  
84 -import java.io.IOException;  
85 import java.util.ArrayList; 61 import java.util.ArrayList;
86 import java.util.Collections; 62 import java.util.Collections;
87 import java.util.Comparator; 63 import java.util.Comparator;
88 import java.util.List; 64 import java.util.List;
89 import java.util.Optional; 65 import java.util.Optional;
90 -import java.util.UUID;  
91 -import java.util.concurrent.ExecutorService;  
92 -import java.util.concurrent.Executors;  
93 import java.util.stream.Collectors; 66 import java.util.stream.Collectors;
94 67
95 import static org.thingsboard.server.common.data.CacheConstants.EDGE_CACHE; 68 import static org.thingsboard.server.common.data.CacheConstants.EDGE_CACHE;
@@ -104,8 +77,6 @@ import static org.thingsboard.server.dao.service.Validator.validateString; @@ -104,8 +77,6 @@ import static org.thingsboard.server.dao.service.Validator.validateString;
104 @Slf4j 77 @Slf4j
105 public class EdgeServiceImpl extends AbstractEntityService implements EdgeService { 78 public class EdgeServiceImpl extends AbstractEntityService implements EdgeService {
106 79
107 - private static final ObjectMapper mapper = new ObjectMapper();  
108 -  
109 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId "; 80 public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
110 public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; 81 public static final String INCORRECT_PAGE_LINK = "Incorrect page link ";
111 public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; 82 public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId ";
@@ -124,40 +95,14 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @@ -124,40 +95,14 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
124 private CacheManager cacheManager; 95 private CacheManager cacheManager;
125 96
126 @Autowired 97 @Autowired
127 - private EventService eventService;  
128 -  
129 - @Autowired  
130 private DashboardService dashboardService; 98 private DashboardService dashboardService;
131 99
132 @Autowired 100 @Autowired
133 private RuleChainService ruleChainService; 101 private RuleChainService ruleChainService;
134 102
135 @Autowired 103 @Autowired
136 - private DeviceService deviceService;  
137 -  
138 - @Autowired  
139 - private AssetService assetService;  
140 -  
141 - @Autowired  
142 - private EntityViewService entityViewService;  
143 -  
144 - @Autowired  
145 private RelationService relationService; 104 private RelationService relationService;
146 105
147 - private ExecutorService tsCallBackExecutor;  
148 -  
149 - @PostConstruct  
150 - public void initExecutor() {  
151 - tsCallBackExecutor = Executors.newSingleThreadExecutor();  
152 - }  
153 -  
154 - @PreDestroy  
155 - public void shutdownExecutor() {  
156 - if (tsCallBackExecutor != null) {  
157 - tsCallBackExecutor.shutdownNow();  
158 - }  
159 - }  
160 -  
161 @Override 106 @Override
162 public Edge findEdgeById(TenantId tenantId, EdgeId edgeId) { 107 public Edge findEdgeById(TenantId tenantId, EdgeId edgeId) {
163 log.trace("Executing findEdgeById [{}]", edgeId); 108 log.trace("Executing findEdgeById [{}]", edgeId);
@@ -259,7 +204,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @@ -259,7 +204,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
259 return edgeDao.findEdgesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(edgeIds)); 204 return edgeDao.findEdgesByTenantIdAndIdsAsync(tenantId.getId(), toUUIDs(edgeIds));
260 } 205 }
261 206
262 -  
263 @Override 207 @Override
264 public void deleteEdgesByTenantId(TenantId tenantId) { 208 public void deleteEdgesByTenantId(TenantId tenantId) {
265 log.trace("Executing deleteEdgesByTenantId, tenantId [{}]", tenantId); 209 log.trace("Executing deleteEdgesByTenantId, tenantId [{}]", tenantId);
@@ -345,327 +289,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @@ -345,327 +289,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
345 } 289 }
346 290
347 @Override 291 @Override
348 - public void pushEventToEdge(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) {  
349 - if (tbMsg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name()) ||  
350 - tbMsg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||  
351 - tbMsg.getType().equals(DataConstants.ATTRIBUTES_UPDATED) ||  
352 - tbMsg.getType().equals(DataConstants.ATTRIBUTES_DELETED)) {  
353 - processCustomTbMsg(tenantId, tbMsg, callback);  
354 - } else {  
355 - try {  
356 - switch (tbMsg.getOriginator().getEntityType()) {  
357 - case EDGE:  
358 - processEdge(tenantId, tbMsg, callback);  
359 - break;  
360 - case ASSET:  
361 - processAsset(tenantId, tbMsg, callback);  
362 - break;  
363 - case DEVICE:  
364 - processDevice(tenantId, tbMsg, callback);  
365 - break;  
366 - case DASHBOARD:  
367 - processDashboard(tenantId, tbMsg, callback);  
368 - break;  
369 - case RULE_CHAIN:  
370 - processRuleChain(tenantId, tbMsg, callback);  
371 - break;  
372 - case ENTITY_VIEW:  
373 - processEntityView(tenantId, tbMsg, callback);  
374 - break;  
375 - case ALARM:  
376 - processAlarm(tenantId, tbMsg, callback);  
377 - break;  
378 - default:  
379 - log.debug("Entity type [{}] is not designed to be pushed to edge", tbMsg.getOriginator().getEntityType());  
380 - }  
381 - } catch (IOException e) {  
382 - log.error("Can't push to edge updates, entity type [{}], data [{}]", tbMsg.getOriginator().getEntityType(), tbMsg.getData(), e);  
383 - }  
384 - }  
385 - }  
386 -  
387 - private void processCustomTbMsg(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) {  
388 - ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, tbMsg.getOriginator());  
389 - Futures.transform(edgeIdFuture, edgeId -> {  
390 - EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(tbMsg.getOriginator().getEntityType());  
391 - if (edgeId != null && edgeQueueEntityType != null) {  
392 - try {  
393 - saveEventToEdgeQueue(tenantId, edgeId, edgeQueueEntityType, tbMsg.getType(), Base64.encodeBase64String(TbMsg.toByteArray(tbMsg)), callback);  
394 - } catch (IOException e) {  
395 - log.error("Error while saving custom tbMsg into Edge Queue", e);  
396 - }  
397 - }  
398 - return null;  
399 - }, MoreExecutors.directExecutor());  
400 - }  
401 -  
402 - private EdgeQueueEntityType getEdgeQueueTypeByEntityType(EntityType entityType) {  
403 - switch (entityType) {  
404 - case DEVICE:  
405 - return EdgeQueueEntityType.DEVICE;  
406 - case ASSET:  
407 - return EdgeQueueEntityType.ASSET;  
408 - case ENTITY_VIEW:  
409 - return EdgeQueueEntityType.ENTITY_VIEW;  
410 - default:  
411 - log.info("Unsupported entity type: [{}]", entityType);  
412 - return null;  
413 - }  
414 - }  
415 -  
416 - private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TenantId tenantId, EntityId originatorId) {  
417 - List<EntityRelation> originatorEdgeRelations = relationService.findByToAndType(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);  
418 - if (originatorEdgeRelations != null && originatorEdgeRelations.size() > 0) {  
419 - return Futures.immediateFuture(new EdgeId(originatorEdgeRelations.get(0).getFrom().getId()));  
420 - } else {  
421 - return Futures.immediateFuture(null);  
422 - }  
423 - }  
424 -  
425 - private void pushEventToEdge(TenantId tenantId, EntityId originatorId, EdgeQueueEntityType edgeQueueEntityType, TbMsg tbMsg, FutureCallback<Void> callback) {  
426 - ListenableFuture<EdgeId> edgeIdFuture = getEdgeIdByOriginatorId(tenantId, originatorId);  
427 - Futures.transform(edgeIdFuture, edgeId -> {  
428 - if (edgeId != null) {  
429 - try {  
430 - pushEventToEdge(tenantId, edgeId, edgeQueueEntityType, tbMsg, callback);  
431 - } catch (Exception e) {  
432 - log.error("Failed to push event to edge, edgeId [{}], tbMsg [{}]", edgeId, tbMsg, e);  
433 - }  
434 - }  
435 - return null;  
436 - },  
437 - MoreExecutors.directExecutor());  
438 - }  
439 -  
440 - private void processDevice(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
441 - switch (tbMsg.getType()) {  
442 - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:  
443 - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:  
444 - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DEVICE, callback);  
445 - break;  
446 - case DataConstants.ENTITY_DELETED:  
447 - case DataConstants.ENTITY_CREATED:  
448 - case DataConstants.ENTITY_UPDATED:  
449 - Device device = mapper.readValue(tbMsg.getData(), Device.class);  
450 - pushEventToEdge(tenantId, device.getId(), EdgeQueueEntityType.DEVICE, tbMsg, callback);  
451 - break;  
452 - default:  
453 - log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);  
454 - }  
455 - }  
456 -  
457 - private void processEdge(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
458 - switch (tbMsg.getType()) {  
459 - case DataConstants.ENTITY_DELETED:  
460 - case DataConstants.ENTITY_CREATED:  
461 - case DataConstants.ENTITY_UPDATED:  
462 - // TODO: voba - handle properly edge creation  
463 - break;  
464 - default:  
465 - log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);  
466 - }  
467 - }  
468 -  
469 - private void processAsset(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
470 - switch (tbMsg.getType()) {  
471 - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:  
472 - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:  
473 - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ASSET, callback);  
474 - break;  
475 - case DataConstants.ENTITY_DELETED:  
476 - case DataConstants.ENTITY_CREATED:  
477 - case DataConstants.ENTITY_UPDATED:  
478 - Asset asset = mapper.readValue(tbMsg.getData(), Asset.class);  
479 - pushEventToEdge(tenantId, asset.getId(), EdgeQueueEntityType.ASSET, tbMsg, callback);  
480 - break;  
481 - default:  
482 - log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);  
483 - }  
484 - }  
485 -  
486 - private void processEntityView(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
487 - switch (tbMsg.getType()) {  
488 - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:  
489 - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:  
490 - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ENTITY_VIEW, callback);  
491 - break;  
492 - case DataConstants.ENTITY_DELETED:  
493 - case DataConstants.ENTITY_CREATED:  
494 - case DataConstants.ENTITY_UPDATED:  
495 - EntityView entityView = mapper.readValue(tbMsg.getData(), EntityView.class);  
496 - pushEventToEdge(tenantId, entityView.getId(), EdgeQueueEntityType.ENTITY_VIEW, tbMsg, callback);  
497 - break;  
498 - default:  
499 - log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);  
500 - }  
501 - }  
502 -  
503 - private void processAlarm(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
504 - switch (tbMsg.getType()) {  
505 - case DataConstants.ENTITY_DELETED:  
506 - case DataConstants.ENTITY_CREATED:  
507 - case DataConstants.ENTITY_UPDATED:  
508 - case DataConstants.ALARM_ACK:  
509 - case DataConstants.ALARM_CLEAR:  
510 - Alarm alarm = mapper.readValue(tbMsg.getData(), Alarm.class);  
511 - EdgeQueueEntityType edgeQueueEntityType = getEdgeQueueTypeByEntityType(alarm.getOriginator().getEntityType());  
512 - if (edgeQueueEntityType != null) {  
513 - pushEventToEdge(tenantId, alarm.getOriginator(), EdgeQueueEntityType.ALARM, tbMsg, callback);  
514 - }  
515 - break;  
516 - default:  
517 - log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);  
518 - }  
519 - }  
520 -  
521 - private void processDashboard(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
522 - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DASHBOARD, callback);  
523 - }  
524 -  
525 - private void processRuleChain(TenantId tenantId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
526 - switch (tbMsg.getType()) {  
527 - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:  
528 - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:  
529 - processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.RULE_CHAIN, callback);  
530 - break;  
531 - case DataConstants.ENTITY_DELETED:  
532 - case DataConstants.ENTITY_CREATED:  
533 - case DataConstants.ENTITY_UPDATED:  
534 - RuleChain ruleChain = mapper.readValue(tbMsg.getData(), RuleChain.class);  
535 - if (RuleChainType.EDGE.equals(ruleChain.getType())) {  
536 - ListenableFuture<TimePageData<Edge>> future = findEdgesByTenantIdAndRuleChainId(tenantId, ruleChain.getId(), new TimePageLink(Integer.MAX_VALUE));  
537 - Futures.transform(future, edges -> {  
538 - if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {  
539 - try {  
540 - for (Edge edge : edges.getData()) {  
541 - pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, tbMsg, callback);  
542 - }  
543 - } catch (IOException e) {  
544 - log.error("Can't push event to edge", e);  
545 - }  
546 - }  
547 - return null;  
548 - }, MoreExecutors.directExecutor());  
549 - }  
550 - break;  
551 - default:  
552 - log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);  
553 - }  
554 - }  
555 -  
556 - private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EdgeQueueEntityType entityType, FutureCallback<Void> callback) throws IOException {  
557 - EdgeId edgeId;  
558 - switch (tbMsg.getType()) {  
559 - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:  
560 - edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("assignedEdgeId")));  
561 - pushEventToEdge(tenantId, edgeId, entityType, tbMsg, callback);  
562 - break;  
563 - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:  
564 - edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("unassignedEdgeId")));  
565 - pushEventToEdge(tenantId, edgeId, entityType, tbMsg, callback);  
566 - break;  
567 - case DataConstants.ENTITY_DELETED:  
568 - case DataConstants.ENTITY_CREATED:  
569 - case DataConstants.ENTITY_UPDATED:  
570 - Dashboard dashboard = mapper.readValue(tbMsg.getData(), Dashboard.class);  
571 - ListenableFuture<TimePageData<Edge>> future = findEdgesByTenantIdAndDashboardId(tenantId, dashboard.getId(), new TimePageLink(Integer.MAX_VALUE));  
572 - Futures.transform(future, edges -> {  
573 - if (edges != null && edges.getData() != null && !edges.getData().isEmpty()) {  
574 - try {  
575 - for (Edge edge : edges.getData()) {  
576 - pushEventToEdge(tenantId, edge.getId(), EdgeQueueEntityType.DASHBOARD, tbMsg, callback);  
577 - }  
578 - } catch (IOException e) {  
579 - log.error("Can't push event to edge", e);  
580 - }  
581 - }  
582 - return null;  
583 - }, MoreExecutors.directExecutor());  
584 - break;  
585 - }  
586 - }  
587 -  
588 - private void pushEventToEdge(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
589 - log.debug("Pushing event(s) to edge queue. tenantId [{}], edgeId [{}], entityType [{}], tbMsg [{}]", tenantId, edgeId, entityType, tbMsg);  
590 -  
591 - saveEventToEdgeQueue(tenantId, edgeId, entityType, tbMsg.getType(), tbMsg.getData(), callback);  
592 -  
593 - if (entityType.equals(EdgeQueueEntityType.RULE_CHAIN)) {  
594 - pushRuleChainMetadataToEdge(tenantId, edgeId, tbMsg, callback);  
595 - }  
596 - }  
597 -  
598 - private void saveEventToEdgeQueue(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, String type, String data, FutureCallback<Void> callback) throws IOException {  
599 - log.debug("Pushing single event to edge queue. tenantId [{}], edgeId [{}], entityType [{}], type[{}], data [{}]", tenantId, edgeId, entityType, type, data);  
600 -  
601 - EdgeQueueEntry queueEntry = new EdgeQueueEntry();  
602 - queueEntry.setEntityType(entityType);  
603 - queueEntry.setType(type);  
604 - queueEntry.setData(data);  
605 -  
606 - Event event = new Event();  
607 - event.setEntityId(edgeId);  
608 - event.setTenantId(tenantId);  
609 - event.setType(DataConstants.EDGE_QUEUE_EVENT_TYPE);  
610 - event.setBody(mapper.valueToTree(queueEntry));  
611 - ListenableFuture<Event> saveFuture = eventService.saveAsync(event);  
612 -  
613 - addMainCallback(saveFuture, callback);  
614 - }  
615 -  
616 - private void addMainCallback(ListenableFuture<Event> saveFuture, final FutureCallback<Void> callback) {  
617 - Futures.addCallback(saveFuture, new FutureCallback<Event>() {  
618 - @Override  
619 - public void onSuccess(@Nullable Event result) {  
620 - callback.onSuccess(null);  
621 - }  
622 -  
623 - @Override  
624 - public void onFailure(Throwable t) {  
625 - callback.onFailure(t);  
626 - }  
627 - }, tsCallBackExecutor);  
628 - }  
629 -  
630 - private void pushRuleChainMetadataToEdge(TenantId tenantId, EdgeId edgeId, TbMsg tbMsg, FutureCallback<Void> callback) throws IOException {  
631 - RuleChain ruleChain = mapper.readValue(tbMsg.getData(), RuleChain.class);  
632 - switch (tbMsg.getType()) {  
633 - case DataConstants.ENTITY_ASSIGNED_TO_EDGE:  
634 - case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:  
635 - case DataConstants.ENTITY_UPDATED:  
636 - RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, ruleChain.getId());  
637 - saveEventToEdgeQueue(tenantId, edgeId, EdgeQueueEntityType.RULE_CHAIN_METADATA, tbMsg.getType(), mapper.writeValueAsString(ruleChainMetaData), callback);  
638 - break;  
639 - default:  
640 - log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);  
641 - }  
642 - }  
643 -  
644 - @Override  
645 - public TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {  
646 - return eventService.findEvents(tenantId, edgeId, DataConstants.EDGE_QUEUE_EVENT_TYPE, pageLink);  
647 - }  
648 -  
649 - @Override  
650 - public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException {  
651 - edge.setRootRuleChainId(ruleChainId);  
652 - Edge savedEdge = saveEdge(edge);  
653 - RuleChain ruleChain = ruleChainService.findRuleChainById(tenantId, ruleChainId);  
654 - saveEventToEdgeQueue(tenantId, edge.getId(), EdgeQueueEntityType.RULE_CHAIN, DataConstants.ENTITY_UPDATED, mapper.writeValueAsString(ruleChain), new FutureCallback<Void>() {  
655 - @Override  
656 - public void onSuccess(@Nullable Void aVoid) {  
657 - log.debug("Event saved successfully!");  
658 - }  
659 -  
660 - @Override  
661 - public void onFailure(Throwable t) {  
662 - log.debug("Failure during event save", t);  
663 - }  
664 - });  
665 - return savedEdge;  
666 - }  
667 -  
668 - @Override  
669 public void assignDefaultRuleChainsToEdge(TenantId tenantId, EdgeId edgeId) { 292 public void assignDefaultRuleChainsToEdge(TenantId tenantId, EdgeId edgeId) {
670 log.trace("Executing assignDefaultRuleChainsToEdge, tenantId [{}], edgeId [{}]", tenantId, edgeId); 293 log.trace("Executing assignDefaultRuleChainsToEdge, tenantId [{}], edgeId [{}]", tenantId, edgeId);
671 ListenableFuture<List<RuleChain>> future = ruleChainService.findDefaultEdgeRuleChainsByTenantId(tenantId); 294 ListenableFuture<List<RuleChain>> future = ruleChainService.findDefaultEdgeRuleChainsByTenantId(tenantId);
@@ -713,7 +336,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic @@ -713,7 +336,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
713 }, MoreExecutors.directExecutor()); 336 }, MoreExecutors.directExecutor());
714 } 337 }
715 338
716 -  
717 private DataValidator<Edge> edgeValidator = 339 private DataValidator<Edge> edgeValidator =
718 new DataValidator<Edge>() { 340 new DataValidator<Edge>() {
719 341