Added proper handling of edge event save methods - clients aware of failures

This commit is contained in:
Volodymyr Babak 2022-04-21 21:47:38 +03:00
parent d3eda0c473
commit bb588ac238
12 changed files with 395 additions and 373 deletions

View File

@ -107,6 +107,7 @@ import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -200,8 +201,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
boolean sent = false; boolean sent = false;
if (systemContext.isEdgesEnabled() && edgeId != null) { if (systemContext.isEdgesEnabled() && edgeId != null) {
log.debug("[{}][{}] device is related to edge [{}]. Saving RPC request to edge queue", tenantId, deviceId, edgeId.getId()); log.debug("[{}][{}] device is related to edge [{}]. Saving RPC request to edge queue", tenantId, deviceId, edgeId.getId());
saveRpcRequestToEdgeQueue(request, rpcRequest.getRequestId()); try {
saveRpcRequestToEdgeQueue(request, rpcRequest.getRequestId()).get();
sent = true; sent = true;
} catch (InterruptedException | ExecutionException e) {
String errMsg = String.format("[%s][%s][%s] Failed to save rpc request to edge queue %s", tenantId, deviceId, edgeId.getId(), request);
log.error(errMsg, e);
}
} else if (isSendNewRpcAvailable()) { } else if (isSendNewRpcAvailable()) {
sent = rpcSubscriptions.size() > 0; sent = rpcSubscriptions.size() > 0;
Set<UUID> syncSessionSet = new HashSet<>(); Set<UUID> syncSessionSet = new HashSet<>();
@ -810,7 +816,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
systemContext.getTbCoreToTransportService().process(nodeId, msg); systemContext.getTbCoreToTransportService().process(nodeId, msg);
} }
private void saveRpcRequestToEdgeQueue(ToDeviceRpcRequest msg, Integer requestId) { private ListenableFuture<Void> saveRpcRequestToEdgeQueue(ToDeviceRpcRequest msg, Integer requestId) {
ObjectNode body = mapper.createObjectNode(); ObjectNode body = mapper.createObjectNode();
body.put("requestId", requestId); body.put("requestId", requestId);
body.put("requestUUID", msg.getId().toString()); body.put("requestUUID", msg.getId().toString());
@ -821,17 +827,9 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, EdgeEventType.DEVICE, EdgeEventActionType.RPC_CALL, deviceId, body); EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, EdgeEventType.DEVICE, EdgeEventActionType.RPC_CALL, deviceId, body);
Futures.addCallback(systemContext.getEdgeEventService().saveAsync(edgeEvent), new FutureCallback<>() { return Futures.transform(systemContext.getEdgeEventService().saveAsync(edgeEvent), unused -> {
@Override
public void onSuccess(Void unused) {
systemContext.getClusterService().onEdgeEventUpdate(tenantId, edgeId); systemContext.getClusterService().onEdgeEventUpdate(tenantId, edgeId);
} return null;
@Override
public void onFailure(Throwable t) {
String errMsg = String.format("Failed to save edge event. msg [%s], edge event [%s]", msg, edgeEvent);
log.warn(errMsg, t);
}
}, systemContext.getDbCallbackExecutor()); }, systemContext.getDbCallbackExecutor());
} }

View File

@ -180,7 +180,7 @@ public class EdgeController extends BaseController {
} }
} }
private void onEdgeCreatedOrUpdated(TenantId tenantId, Edge edge, RuleChain edgeTemplateRootRuleChain, boolean updated, SecurityUser user) throws IOException, ThingsboardException { private void onEdgeCreatedOrUpdated(TenantId tenantId, Edge edge, RuleChain edgeTemplateRootRuleChain, boolean updated, SecurityUser user) throws Exception {
if (!updated) { if (!updated) {
ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), edge.getId()); ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), edge.getId());
edgeNotificationService.setEdgeRootRuleChain(tenantId, edge, edgeTemplateRootRuleChain.getId()); edgeNotificationService.setEdgeRootRuleChain(tenantId, edge, edgeTemplateRootRuleChain.getId());

View File

@ -18,6 +18,7 @@ package org.thingsboard.server.service.edge;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -46,7 +47,6 @@ import org.thingsboard.server.service.edge.rpc.processor.RelationEdgeProcessor;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -95,14 +95,14 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
} }
@Override @Override
public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException { public Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws Exception {
edge.setRootRuleChainId(ruleChainId); edge.setRootRuleChainId(ruleChainId);
Edge savedEdge = edgeService.saveEdge(edge); Edge savedEdge = edgeService.saveEdge(edge);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.UPDATED, ruleChainId, null); saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.RULE_CHAIN, EdgeEventActionType.UPDATED, ruleChainId, null).get();
return savedEdge; return savedEdge;
} }
private void saveEdgeEvent(TenantId tenantId, private ListenableFuture<Void> saveEdgeEvent(TenantId tenantId,
EdgeId edgeId, EdgeId edgeId,
EdgeEventType type, EdgeEventType type,
EdgeEventActionType action, EdgeEventActionType action,
@ -113,17 +113,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body); EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body);
Futures.addCallback(edgeEventService.saveAsync(edgeEvent), new FutureCallback<>() { return Futures.transform(edgeEventService.saveAsync(edgeEvent), unused -> {
@Override
public void onSuccess(@Nullable Void unused) {
clusterService.onEdgeEventUpdate(tenantId, edgeId); clusterService.onEdgeEventUpdate(tenantId, edgeId);
} return null;
@Override
public void onFailure(Throwable t) {
String errMsg = String.format("Failed to save edge event. edge event [%s]", edgeEvent);
log.warn(errMsg, t);
}
}, dbCallBackExecutor); }, dbCallBackExecutor);
} }
@ -133,9 +125,10 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
try { try {
TenantId tenantId = TenantId.fromUUID(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB())); TenantId tenantId = TenantId.fromUUID(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB()));
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
ListenableFuture<Void> future;
switch (type) { switch (type) {
case EDGE: case EDGE:
edgeProcessor.processEdgeNotification(tenantId, edgeNotificationMsg); future = edgeProcessor.processEdgeNotification(tenantId, edgeNotificationMsg);
break; break;
case USER: case USER:
case ASSET: case ASSET:
@ -144,31 +137,45 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
case ENTITY_VIEW: case ENTITY_VIEW:
case DASHBOARD: case DASHBOARD:
case RULE_CHAIN: case RULE_CHAIN:
entityProcessor.processEntityNotification(tenantId, edgeNotificationMsg); future = entityProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break; break;
case CUSTOMER: case CUSTOMER:
customerProcessor.processCustomerNotification(tenantId, edgeNotificationMsg); future = customerProcessor.processCustomerNotification(tenantId, edgeNotificationMsg);
break; break;
case WIDGETS_BUNDLE: case WIDGETS_BUNDLE:
case WIDGET_TYPE: case WIDGET_TYPE:
entityProcessor.processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg); future = entityProcessor.processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
break; break;
case ALARM: case ALARM:
alarmProcessor.processAlarmNotification(tenantId, edgeNotificationMsg); future = alarmProcessor.processAlarmNotification(tenantId, edgeNotificationMsg);
break; break;
case RELATION: case RELATION:
relationProcessor.processRelationNotification(tenantId, edgeNotificationMsg); future = relationProcessor.processRelationNotification(tenantId, edgeNotificationMsg);
break; break;
default: default:
log.warn("Edge event type [{}] is not designed to be pushed to edge", type); log.warn("Edge event type [{}] is not designed to be pushed to edge", type);
future = Futures.immediateFuture(null);
} }
} catch (Exception e) { Futures.addCallback(future, new FutureCallback<>() {
callback.onFailure(e); @Override
String errMsg = String.format("Can't push to edge updates, edgeNotificationMsg [%s]", edgeNotificationMsg); public void onSuccess(@Nullable Void unused) {
log.error(errMsg, e);
} finally {
callback.onSuccess(); callback.onSuccess();
} }
@Override
public void onFailure(Throwable throwable) {
callBackFailure(edgeNotificationMsg, callback, throwable);
}
}, dbCallBackExecutor);
} catch (Exception e) {
callBackFailure(edgeNotificationMsg, callback, e);
}
}
private void callBackFailure(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback, Throwable throwable) {
String errMsg = String.format("Can't push to edge updates, edgeNotificationMsg [%s]", edgeNotificationMsg);
log.error(errMsg, throwable);
callback.onFailure(throwable);
} }
} }

View File

@ -21,11 +21,9 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import java.io.IOException;
public interface EdgeNotificationService { public interface EdgeNotificationService {
Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws IOException; Edge setEdgeRootRuleChain(TenantId tenantId, Edge edge, RuleChainId ruleChainId) throws Exception;
void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback); void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback);
} }

View File

@ -16,11 +16,9 @@
package org.thingsboard.server.service.edge.rpc.processor; package org.thingsboard.server.service.edge.rpc.processor;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
@ -43,6 +41,8 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Component @Component
@ -148,49 +148,44 @@ public class AlarmEdgeProcessor extends BaseEdgeProcessor {
return downlinkMsg; return downlinkMsg;
} }
public void processAlarmNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException { public ListenableFuture<Void> processAlarmNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException {
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
switch (actionType) { switch (actionType) {
case DELETED: case DELETED:
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
Alarm alarm = mapper.readValue(edgeNotificationMsg.getBody(), Alarm.class); Alarm deletedAlarm = mapper.readValue(edgeNotificationMsg.getBody(), Alarm.class);
saveEdgeEvent(tenantId, edgeId, EdgeEventType.ALARM, actionType, alarmId, mapper.valueToTree(alarm)); return saveEdgeEvent(tenantId, edgeId, EdgeEventType.ALARM, actionType, alarmId, mapper.valueToTree(deletedAlarm));
break;
default: default:
ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId); ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId);
Futures.addCallback(alarmFuture, new FutureCallback<Alarm>() { return Futures.transformAsync(alarmFuture, alarm -> {
@Override if (alarm == null) {
public void onSuccess(@Nullable Alarm alarm) { return Futures.immediateFuture(null);
if (alarm != null) { }
EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(alarm.getOriginator().getEntityType()); EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(alarm.getOriginator().getEntityType());
if (type != null) { if (type == null) {
return Futures.immediateFuture(null);
}
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<EdgeId> pageData; PageData<EdgeId> pageData;
List<ListenableFuture<Void>> futures = new ArrayList<>();
do { do {
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), pageLink); pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), pageLink);
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
for (EdgeId edgeId : pageData.getData()) { for (EdgeId relatedEdgeId : pageData.getData()) {
saveEdgeEvent(tenantId, futures.add(saveEdgeEvent(tenantId,
edgeId, relatedEdgeId,
EdgeEventType.ALARM, EdgeEventType.ALARM,
EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()), EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()),
alarmId, alarmId,
null); null));
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
} }
} }
} while (pageData != null && pageData.hasNext()); } while (pageData != null && pageData.hasNext());
} return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
}
}
@Override
public void onFailure(Throwable t) {
log.warn("[{}] can't find alarm by id [{}] {}", tenantId.getId(), alarmId.getId(), t);
}
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
} }
} }

View File

@ -17,10 +17,9 @@ package org.thingsboard.server.service.edge.rpc.processor;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
@ -71,6 +70,9 @@ import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.service.profile.TbDeviceProfileCache; import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.state.DeviceStateService; import org.thingsboard.server.service.state.DeviceStateService;
import java.util.ArrayList;
import java.util.List;
@Slf4j @Slf4j
public abstract class BaseEdgeProcessor { public abstract class BaseEdgeProcessor {
@ -183,7 +185,7 @@ public abstract class BaseEdgeProcessor {
@Autowired @Autowired
protected DbCallbackExecutorService dbCallbackExecutorService; protected DbCallbackExecutorService dbCallbackExecutorService;
protected void saveEdgeEvent(TenantId tenantId, protected ListenableFuture<Void> saveEdgeEvent(TenantId tenantId,
EdgeId edgeId, EdgeId edgeId,
EdgeEventType type, EdgeEventType type,
EdgeEventActionType action, EdgeEventActionType action,
@ -195,17 +197,9 @@ public abstract class BaseEdgeProcessor {
EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body); EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body);
Futures.addCallback(edgeEventService.saveAsync(edgeEvent), new FutureCallback<>() { return Futures.transform(edgeEventService.saveAsync(edgeEvent), unused -> {
@Override
public void onSuccess(@Nullable Void unused) {
tbClusterService.onEdgeEventUpdate(tenantId, edgeId); tbClusterService.onEdgeEventUpdate(tenantId, edgeId);
} return null;
@Override
public void onFailure(Throwable t) {
String errMsg = String.format("Failed to save edge event. edge event [%s]", edgeEvent);
log.warn(errMsg, t);
}
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
} }
@ -217,19 +211,21 @@ public abstract class BaseEdgeProcessor {
} }
} }
protected void processActionForAllEdges(TenantId tenantId, EdgeEventType type, EdgeEventActionType actionType, EntityId entityId) { protected ListenableFuture<Void> processActionForAllEdges(TenantId tenantId, EdgeEventType type, EdgeEventActionType actionType, EntityId entityId) {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<Edge> pageData; PageData<Edge> pageData;
List<ListenableFuture<Void>> futures = new ArrayList<>();
do { do {
pageData = edgeService.findEdgesByTenantId(tenantId, pageLink); pageData = edgeService.findEdgesByTenantId(tenantId, pageLink);
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
for (Edge edge : pageData.getData()) { for (Edge edge : pageData.getData()) {
saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null); futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, null));
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
} }
} }
} while (pageData != null && pageData.hasNext()); } while (pageData != null && pageData.hasNext());
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
} }
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.thingsboard.server.service.edge.rpc.processor; package org.thingsboard.server.service.edge.rpc.processor;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
@ -35,6 +37,8 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Component @Component
@ -70,7 +74,7 @@ public class CustomerEdgeProcessor extends BaseEdgeProcessor {
return downlinkMsg; return downlinkMsg;
} }
public void processCustomerNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { public ListenableFuture<Void> processCustomerNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
UUID uuid = new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()); UUID uuid = new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB());
@ -79,22 +83,24 @@ public class CustomerEdgeProcessor extends BaseEdgeProcessor {
case UPDATED: case UPDATED:
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<Edge> pageData; PageData<Edge> pageData;
List<ListenableFuture<Void>> futures = new ArrayList<>();
do { do {
pageData = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink); pageData = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink);
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
for (Edge edge : pageData.getData()) { for (Edge edge : pageData.getData()) {
saveEdgeEvent(tenantId, edge.getId(), type, actionType, customerId, null); futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, customerId, null));
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
} }
} }
} while (pageData != null && pageData.hasNext()); } while (pageData != null && pageData.hasNext());
break; return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
case DELETED: case DELETED:
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
saveEdgeEvent(tenantId, edgeId, type, actionType, customerId, null); return saveEdgeEvent(tenantId, edgeId, type, actionType, customerId, null);
break; default:
return Futures.immediateFuture(null);
} }
} }

View File

@ -84,7 +84,7 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
if (deviceAlreadyExistsForThisEdge) { if (deviceAlreadyExistsForThisEdge) {
log.info("[{}] Device with name '{}' already exists on the cloud, and related to this edge [{}]. " + log.info("[{}] Device with name '{}' already exists on the cloud, and related to this edge [{}]. " +
"deviceUpdateMsg [{}], Updating device", tenantId, deviceName, edge.getId(), deviceUpdateMsg); "deviceUpdateMsg [{}], Updating device", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
updateDevice(tenantId, edge, deviceUpdateMsg); return updateDevice(tenantId, edge, deviceUpdateMsg);
} else { } else {
log.info("[{}] Device with name '{}' already exists on the cloud, but not related to this edge [{}]. deviceUpdateMsg [{}]." + log.info("[{}] Device with name '{}' already exists on the cloud, but not related to this edge [{}]. deviceUpdateMsg [{}]." +
"Creating a new device with random prefix and relate to this edge", tenantId, deviceName, edge.getId(), deviceUpdateMsg); "Creating a new device with random prefix and relate to this edge", tenantId, deviceName, edge.getId(), deviceUpdateMsg);
@ -99,8 +99,10 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
} }
ObjectNode body = mapper.createObjectNode(); ObjectNode body = mapper.createObjectNode();
body.put("conflictName", deviceName); body.put("conflictName", deviceName);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, newDevice.getId(), body); ListenableFuture<Void> input = saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ENTITY_MERGE_REQUEST, newDevice.getId(), body);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, newDevice.getId(), null); return Futures.transformAsync(input, unused ->
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, newDevice.getId(), null),
dbCallbackExecutorService);
} }
} else { } else {
log.info("[{}] Creating new device and replacing device entity on the edge [{}]", tenantId, deviceUpdateMsg); log.info("[{}] Creating new device and replacing device entity on the edge [{}]", tenantId, deviceUpdateMsg);
@ -111,24 +113,22 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
log.error(errMsg, e); log.error(errMsg, e);
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
} }
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, device.getId(), null); return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, device.getId(), null);
} }
break;
case ENTITY_UPDATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE:
updateDevice(tenantId, edge, deviceUpdateMsg); return updateDevice(tenantId, edge, deviceUpdateMsg);
break;
case ENTITY_DELETED_RPC_MESSAGE: case ENTITY_DELETED_RPC_MESSAGE:
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
Device deviceToDelete = deviceService.findDeviceById(tenantId, deviceId); Device deviceToDelete = deviceService.findDeviceById(tenantId, deviceId);
if (deviceToDelete != null) { if (deviceToDelete != null) {
deviceService.unassignDeviceFromEdge(tenantId, deviceId, edge.getId()); deviceService.unassignDeviceFromEdge(tenantId, deviceId, edge.getId());
} }
break; return Futures.immediateFuture(null);
case UNRECOGNIZED: case UNRECOGNIZED:
default:
log.error("Unsupported msg type {}", deviceUpdateMsg.getMsgType()); log.error("Unsupported msg type {}", deviceUpdateMsg.getMsgType());
return Futures.immediateFailedFuture(new RuntimeException("Unsupported msg type " + deviceUpdateMsg.getMsgType())); return Futures.immediateFailedFuture(new RuntimeException("Unsupported msg type " + deviceUpdateMsg.getMsgType()));
} }
return Futures.immediateFuture(null);
} }
private boolean isDeviceAlreadyExistsOnCloudForThisEdge(TenantId tenantId, Edge edge, Device device) { private boolean isDeviceAlreadyExistsOnCloudForThisEdge(TenantId tenantId, Edge edge, Device device) {
@ -174,7 +174,7 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
} }
private void updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) { private ListenableFuture<Void> updateDevice(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB())); DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
Device device = deviceService.findDeviceById(tenantId, deviceId); Device device = deviceService.findDeviceById(tenantId, deviceId);
if (device != null) { if (device != null) {
@ -194,9 +194,11 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
} }
Device savedDevice = deviceService.saveDevice(device); Device savedDevice = deviceService.saveDevice(device);
tbClusterService.onDeviceUpdated(savedDevice, device); tbClusterService.onDeviceUpdated(savedDevice, device);
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null); return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
} else { } else {
log.warn("[{}] can't find device [{}], edge [{}]", tenantId, deviceUpdateMsg, edge.getId()); String errMsg = String.format("[%s] can't find device [%s], edge [%s]", tenantId, deviceUpdateMsg, edge.getId());
log.warn(errMsg);
return Futures.immediateFailedFuture(new RuntimeException(errMsg));
} }
} }

View File

@ -15,11 +15,9 @@
*/ */
package org.thingsboard.server.service.edge.rpc.processor; package org.thingsboard.server.service.edge.rpc.processor;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.Edge;
@ -33,6 +31,8 @@ import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Component @Component
@ -40,7 +40,7 @@ import java.util.UUID;
@TbCoreComponent @TbCoreComponent
public class EdgeProcessor extends BaseEdgeProcessor { public class EdgeProcessor extends BaseEdgeProcessor {
public void processEdgeNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { public ListenableFuture<Void> processEdgeNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
try { try {
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
@ -49,11 +49,12 @@ public class EdgeProcessor extends BaseEdgeProcessor {
case ASSIGNED_TO_CUSTOMER: case ASSIGNED_TO_CUSTOMER:
CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class);
edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId);
Futures.addCallback(edgeFuture, new FutureCallback<Edge>() { return Futures.transformAsync(edgeFuture, edge -> {
@Override if (edge == null || customerId.isNullUid()) {
public void onSuccess(@Nullable Edge edge) { return Futures.immediateFuture(null);
if (edge != null && !customerId.isNullUid()) { }
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null); List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null));
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<User> pageData; PageData<User> pageData;
do { do {
@ -61,42 +62,30 @@ public class EdgeProcessor extends BaseEdgeProcessor {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] user(s) are going to be added to edge.", edge.getId(), pageData.getData().size()); log.trace("[{}] [{}] user(s) are going to be added to edge.", edge.getId(), pageData.getData().size());
for (User user : pageData.getData()) { for (User user : pageData.getData()) {
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, EdgeEventActionType.ADDED, user.getId(), null); futures.add(saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, EdgeEventActionType.ADDED, user.getId(), null));
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
} }
} }
} while (pageData != null && pageData.hasNext()); } while (pageData != null && pageData.hasNext());
} return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
}
@Override
public void onFailure(Throwable t) {
log.error("Can't find edge by id [{}]", edgeNotificationMsg, t);
}
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
break;
case UNASSIGNED_FROM_CUSTOMER: case UNASSIGNED_FROM_CUSTOMER:
CustomerId customerIdToDelete = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); CustomerId customerIdToDelete = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class);
edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId); edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId);
Futures.addCallback(edgeFuture, new FutureCallback<Edge>() { return Futures.transformAsync(edgeFuture, edge -> {
@Override if (edge == null || customerIdToDelete.isNullUid()) {
public void onSuccess(@Nullable Edge edge) { return Futures.immediateFuture(null);
if (edge != null && !customerIdToDelete.isNullUid()) {
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.DELETED, customerIdToDelete, null);
}
}
@Override
public void onFailure(Throwable t) {
log.error("Can't find edge by id [{}]", edgeNotificationMsg, t);
} }
return saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.DELETED, customerIdToDelete, null);
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
break; default:
return Futures.immediateFuture(null);
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Exception during processing edge event", e); log.error("Exception during processing edge event", e);
return Futures.immediateFailedFuture(e);
} }
} }
} }

View File

@ -15,11 +15,9 @@
*/ */
package org.thingsboard.server.service.edge.rpc.processor; package org.thingsboard.server.service.edge.rpc.processor;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EdgeUtils;
@ -45,6 +43,7 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -89,25 +88,49 @@ public class EntityEdgeProcessor extends BaseEdgeProcessor {
return downlinkMsg; return downlinkMsg;
} }
public void processEntityNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { public ListenableFuture<Void> processEntityNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type,
new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
EdgeId edgeId = null; EdgeId edgeId = safeGetEdgeId(edgeNotificationMsg);
if (edgeNotificationMsg.getEdgeIdMSB() != 0 && edgeNotificationMsg.getEdgeIdLSB() != 0) {
edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
}
switch (actionType) { switch (actionType) {
case ADDED: // used only for USER entity case ADDED: // used only for USER entity
case UPDATED: case UPDATED:
case CREDENTIALS_UPDATED: case CREDENTIALS_UPDATED:
pushNotificationToAllRelatedEdges(tenantId, entityId, type, actionType); return pushNotificationToAllRelatedEdges(tenantId, entityId, type, actionType);
break;
case ASSIGNED_TO_CUSTOMER: case ASSIGNED_TO_CUSTOMER:
case UNASSIGNED_FROM_CUSTOMER: case UNASSIGNED_FROM_CUSTOMER:
return pushNotificationToAllRelatedCustomerEdges(tenantId, edgeNotificationMsg, entityId, actionType, type);
case DELETED:
if (edgeId != null) {
return saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null);
} else {
return pushNotificationToAllRelatedEdges(tenantId, entityId, type, actionType);
}
case ASSIGNED_TO_EDGE:
case UNASSIGNED_FROM_EDGE:
ListenableFuture<Void> future = saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null);
return Futures.transformAsync(future, unused -> {
if (type.equals(EdgeEventType.RULE_CHAIN)) {
return updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId);
} else {
return Futures.immediateFuture(null);
}
}, dbCallbackExecutorService);
default:
return Futures.immediateFuture(null);
}
}
private ListenableFuture<Void> pushNotificationToAllRelatedCustomerEdges(TenantId tenantId,
TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg,
EntityId entityId,
EdgeEventActionType actionType,
EdgeEventType type) {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<EdgeId> pageData; PageData<EdgeId> pageData;
List<ListenableFuture<Void>> futures = new ArrayList<>();
do { do {
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, pageLink); pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, pageLink);
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
@ -115,22 +138,17 @@ public class EntityEdgeProcessor extends BaseEdgeProcessor {
try { try {
CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class); CustomerId customerId = mapper.readValue(edgeNotificationMsg.getBody(), CustomerId.class);
ListenableFuture<Edge> future = edgeService.findEdgeByIdAsync(tenantId, relatedEdgeId); ListenableFuture<Edge> future = edgeService.findEdgeByIdAsync(tenantId, relatedEdgeId);
Futures.addCallback(future, new FutureCallback<>() { futures.add(Futures.transformAsync(future, edge -> {
@Override
public void onSuccess(@Nullable Edge edge) {
if (edge != null && edge.getCustomerId() != null && if (edge != null && edge.getCustomerId() != null &&
!edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(customerId)) { !edge.getCustomerId().isNullUid() && edge.getCustomerId().equals(customerId)) {
saveEdgeEvent(tenantId, relatedEdgeId, type, actionType, entityId, null); return saveEdgeEvent(tenantId, relatedEdgeId, type, actionType, entityId, null);
} else {
return Futures.immediateFuture(null);
} }
} }, dbCallbackExecutorService));
@Override
public void onFailure(Throwable t) {
log.error("Failed to find edge by id [{}] {}", edgeNotificationMsg, t);
}
}, dbCallbackExecutorService);
} catch (Exception e) { } catch (Exception e) {
log.error("Can't parse customer id from entity body [{}]", edgeNotificationMsg, e); log.error("Can't parse customer id from entity body [{}]", edgeNotificationMsg, e);
return Futures.immediateFailedFuture(e);
} }
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
@ -138,43 +156,39 @@ public class EntityEdgeProcessor extends BaseEdgeProcessor {
} }
} }
} while (pageData != null && pageData.hasNext()); } while (pageData != null && pageData.hasNext());
break; return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
case DELETED: }
if (edgeId != null) {
saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null); private EdgeId safeGetEdgeId(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
if (edgeNotificationMsg.getEdgeIdMSB() != 0 && edgeNotificationMsg.getEdgeIdLSB() != 0) {
return new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
} else { } else {
pushNotificationToAllRelatedEdges(tenantId, entityId, type, actionType); return null;
}
break;
case ASSIGNED_TO_EDGE:
case UNASSIGNED_FROM_EDGE:
saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, null);
if (type.equals(EdgeEventType.RULE_CHAIN)) {
updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId);
}
break;
} }
} }
private void pushNotificationToAllRelatedEdges(TenantId tenantId, EntityId entityId, EdgeEventType type, EdgeEventActionType actionType) { private ListenableFuture<Void> pushNotificationToAllRelatedEdges(TenantId tenantId, EntityId entityId, EdgeEventType type, EdgeEventActionType actionType) {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<EdgeId> pageData; PageData<EdgeId> pageData;
List<ListenableFuture<Void>> futures = new ArrayList<>();
do { do {
pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, pageLink); pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, entityId, pageLink);
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
for (EdgeId relatedEdgeId : pageData.getData()) { for (EdgeId relatedEdgeId : pageData.getData()) {
saveEdgeEvent(tenantId, relatedEdgeId, type, actionType, entityId, null); futures.add(saveEdgeEvent(tenantId, relatedEdgeId, type, actionType, entityId, null));
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
} }
} }
} while (pageData != null && pageData.hasNext()); } while (pageData != null && pageData.hasNext());
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
} }
private void updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) { private ListenableFuture<Void> updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<RuleChain> pageData; PageData<RuleChain> pageData;
List<ListenableFuture<Void>> futures = new ArrayList<>();
do { do {
pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink);
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
@ -185,12 +199,12 @@ public class EntityEdgeProcessor extends BaseEdgeProcessor {
if (connectionInfos != null && !connectionInfos.isEmpty()) { if (connectionInfos != null && !connectionInfos.isEmpty()) {
for (RuleChainConnectionInfo connectionInfo : connectionInfos) { for (RuleChainConnectionInfo connectionInfo : connectionInfos) {
if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) { if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) {
saveEdgeEvent(tenantId, futures.add(saveEdgeEvent(tenantId,
edgeId, edgeId,
EdgeEventType.RULE_CHAIN_METADATA, EdgeEventType.RULE_CHAIN_METADATA,
EdgeEventActionType.UPDATED, EdgeEventActionType.UPDATED,
ruleChain.getId(), ruleChain.getId(),
null); null));
} }
} }
} }
@ -201,9 +215,10 @@ public class EntityEdgeProcessor extends BaseEdgeProcessor {
} }
} }
} while (pageData != null && pageData.hasNext()); } while (pageData != null && pageData.hasNext());
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
} }
public void processEntityNotificationForAllEdges(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) { public ListenableFuture<Void> processEntityNotificationForAllEdges(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
@ -211,8 +226,9 @@ public class EntityEdgeProcessor extends BaseEdgeProcessor {
case ADDED: case ADDED:
case UPDATED: case UPDATED:
case DELETED: case DELETED:
processActionForAllEdges(tenantId, type, actionType, entityId); return processActionForAllEdges(tenantId, type, actionType, entityId);
break; default:
return Futures.immediateFuture(null);
} }
} }
} }

View File

@ -126,24 +126,29 @@ public class RelationEdgeProcessor extends BaseEdgeProcessor {
.build(); .build();
} }
public void processRelationNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException { public ListenableFuture<Void> processRelationNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) throws JsonProcessingException {
EntityRelation relation = mapper.readValue(edgeNotificationMsg.getBody(), EntityRelation.class); EntityRelation relation = mapper.readValue(edgeNotificationMsg.getBody(), EntityRelation.class);
if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && if (relation.getFrom().getEntityType().equals(EntityType.EDGE) ||
!relation.getTo().getEntityType().equals(EntityType.EDGE)) { relation.getTo().getEntityType().equals(EntityType.EDGE)) {
return Futures.immediateFuture(null);
}
Set<EdgeId> uniqueEdgeIds = new HashSet<>(); Set<EdgeId> uniqueEdgeIds = new HashSet<>();
uniqueEdgeIds.addAll(findRelatedEdgeIds(tenantId, relation.getTo())); uniqueEdgeIds.addAll(findRelatedEdgeIds(tenantId, relation.getTo()));
uniqueEdgeIds.addAll(findRelatedEdgeIds(tenantId, relation.getFrom())); uniqueEdgeIds.addAll(findRelatedEdgeIds(tenantId, relation.getFrom()));
if (!uniqueEdgeIds.isEmpty()) { if (uniqueEdgeIds.isEmpty()) {
return Futures.immediateFuture(null);
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
for (EdgeId edgeId : uniqueEdgeIds) { for (EdgeId edgeId : uniqueEdgeIds) {
saveEdgeEvent(tenantId, futures.add(saveEdgeEvent(tenantId,
edgeId, edgeId,
EdgeEventType.RELATION, EdgeEventType.RELATION,
EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()), EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()),
null, null,
mapper.valueToTree(relation)); mapper.valueToTree(relation)));
}
}
} }
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
} }
private List<EdgeId> findRelatedEdgeIds(TenantId tenantId, EntityId entityId) { private List<EdgeId> findRelatedEdgeIds(TenantId tenantId, EntityId entityId) {

View File

@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EdgeUtils;
@ -72,7 +73,6 @@ import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg;
import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg; import org.thingsboard.server.gen.edge.v1.UserCredentialsRequestMsg;
import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg; import org.thingsboard.server.gen.edge.v1.WidgetBundleTypesRequestMsg;
import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.cluster.TbClusterService;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -121,14 +121,14 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
@Override @Override
public ListenableFuture<Void> processRuleChainMetadataRequestMsg(TenantId tenantId, Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) { public ListenableFuture<Void> processRuleChainMetadataRequestMsg(TenantId tenantId, Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) {
log.trace("[{}] processRuleChainMetadataRequestMsg [{}][{}]", tenantId, edge.getName(), ruleChainMetadataRequestMsg); log.trace("[{}] processRuleChainMetadataRequestMsg [{}][{}]", tenantId, edge.getName(), ruleChainMetadataRequestMsg);
if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) { if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() == 0 || ruleChainMetadataRequestMsg.getRuleChainIdLSB() == 0) {
return Futures.immediateFuture(null);
}
RuleChainId ruleChainId = RuleChainId ruleChainId =
new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB())); new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB()));
saveEdgeEvent(tenantId, edge.getId(), return saveEdgeEvent(tenantId, edge.getId(),
EdgeEventType.RULE_CHAIN_METADATA, EdgeEventActionType.ADDED, ruleChainId, null); EdgeEventType.RULE_CHAIN_METADATA, EdgeEventActionType.ADDED, ruleChainId, null);
} }
return Futures.immediateFuture(null);
}
@Override @Override
public ListenableFuture<Void> processAttributesRequestMsg(TenantId tenantId, Edge edge, AttributesRequestMsg attributesRequestMsg) { public ListenableFuture<Void> processAttributesRequestMsg(TenantId tenantId, Edge edge, AttributesRequestMsg attributesRequestMsg) {
@ -137,14 +137,25 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
EntityType.valueOf(attributesRequestMsg.getEntityType()), EntityType.valueOf(attributesRequestMsg.getEntityType()),
new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB())); new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB()));
final EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType()); final EdgeEventType type = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType());
if (type != null) { if (type == null) {
log.warn("[{}] Type doesn't supported {}", tenantId, entityId.getEntityType());
return Futures.immediateFuture(null);
}
SettableFuture<Void> futureToSet = SettableFuture.create(); SettableFuture<Void> futureToSet = SettableFuture.create();
String scope = attributesRequestMsg.getScope(); String scope = attributesRequestMsg.getScope();
ListenableFuture<List<AttributeKvEntry>> findAttrFuture = attributesService.findAll(tenantId, entityId, scope); ListenableFuture<List<AttributeKvEntry>> findAttrFuture = attributesService.findAll(tenantId, entityId, scope);
Futures.addCallback(findAttrFuture, new FutureCallback<List<AttributeKvEntry>>() { Futures.addCallback(findAttrFuture, new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable List<AttributeKvEntry> ssAttributes) { public void onSuccess(@Nullable List<AttributeKvEntry> ssAttributes) {
if (ssAttributes != null && !ssAttributes.isEmpty()) { if (ssAttributes == null || ssAttributes.isEmpty()) {
log.trace("[{}][{}] No attributes found for entity {} [{}]", tenantId,
edge.getName(),
entityId.getEntityType(),
entityId.getId());
futureToSet.set(null);
return;
}
try { try {
Map<String, Object> entityData = new HashMap<>(); Map<String, Object> entityData = new HashMap<>();
ObjectNode attributes = mapper.createObjectNode(); ObjectNode attributes = mapper.createObjectNode();
@ -163,37 +174,35 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
entityData.put("scope", scope); entityData.put("scope", scope);
JsonNode body = mapper.valueToTree(entityData); JsonNode body = mapper.valueToTree(entityData);
log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, body); log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, body);
saveEdgeEvent(tenantId, ListenableFuture<Void> future = saveEdgeEvent(tenantId, edge.getId(), type, EdgeEventActionType.ATTRIBUTES_UPDATED, entityId, body);
edge.getId(), Futures.addCallback(future, new FutureCallback<>() {
type, @Override
EdgeEventActionType.ATTRIBUTES_UPDATED, public void onSuccess(@Nullable Void unused) {
entityId,
body);
} catch (Exception e) {
log.error("[{}] Failed to save attribute updates to the edge", edge.getName(), e);
futureToSet.setException(new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e));
return;
}
} else {
log.trace("[{}][{}] No attributes found for entity {} [{}]", tenantId,
edge.getName(),
entityId.getEntityType(),
entityId.getId());
}
futureToSet.set(null); futureToSet.set(null);
} }
@Override
public void onFailure(Throwable throwable) {
String errMsg = String.format("[%s] Failed to save edge event [%s]", edge.getId(), attributesRequestMsg);
log.error(errMsg, throwable);
futureToSet.setException(new RuntimeException(errMsg, throwable));
}
}, dbCallbackExecutorService);
} catch (Exception e) {
String errMsg = String.format("[%s] Failed to save attribute updates to the edge [%s]", edge.getId(), attributesRequestMsg);
log.error(errMsg, e);
futureToSet.setException(new RuntimeException(errMsg, e));
}
}
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
log.error("Can't find attributes [{}]", attributesRequestMsg, t); String errMsg = String.format("[%s] Can't find attributes [%s]", edge.getId(), attributesRequestMsg);
futureToSet.setException(t); log.error(errMsg, t);
futureToSet.setException(new RuntimeException(errMsg, t));
} }
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
return futureToSet; return futureToSet;
} else {
log.warn("[{}] Type doesn't supported {}", tenantId, entityId.getEntityType());
return Futures.immediateFuture(null);
}
} }
@Override @Override
@ -208,33 +217,49 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
futures.add(findRelationByQuery(tenantId, edge, entityId, EntitySearchDirection.TO)); futures.add(findRelationByQuery(tenantId, edge, entityId, EntitySearchDirection.TO));
ListenableFuture<List<List<EntityRelation>>> relationsListFuture = Futures.allAsList(futures); ListenableFuture<List<List<EntityRelation>>> relationsListFuture = Futures.allAsList(futures);
SettableFuture<Void> futureToSet = SettableFuture.create(); SettableFuture<Void> futureToSet = SettableFuture.create();
Futures.addCallback(relationsListFuture, new FutureCallback<List<List<EntityRelation>>>() { Futures.addCallback(relationsListFuture, new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable List<List<EntityRelation>> relationsList) { public void onSuccess(@Nullable List<List<EntityRelation>> relationsList) {
try { try {
if (relationsList != null && !relationsList.isEmpty()) { if (relationsList != null && !relationsList.isEmpty()) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
for (List<EntityRelation> entityRelations : relationsList) { for (List<EntityRelation> entityRelations : relationsList) {
log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size()); log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size());
for (EntityRelation relation : entityRelations) { for (EntityRelation relation : entityRelations) {
try { try {
if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) &&
!relation.getTo().getEntityType().equals(EntityType.EDGE)) { !relation.getTo().getEntityType().equals(EntityType.EDGE)) {
saveEdgeEvent(tenantId, futures.add(saveEdgeEvent(tenantId,
edge.getId(), edge.getId(),
EdgeEventType.RELATION, EdgeEventType.RELATION,
EdgeEventActionType.ADDED, EdgeEventActionType.ADDED,
null, null,
mapper.valueToTree(relation)); mapper.valueToTree(relation)));
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Exception during loading relation [{}] to edge on sync!", relation, e); String errMsg = String.format("[%s] Exception during loading relation [%s] to edge on sync!", edge.getId(), relation);
futureToSet.setException(e); log.error(errMsg, e);
futureToSet.setException(new RuntimeException(errMsg, e));
return; return;
} }
} }
} }
} Futures.addCallback(Futures.allAsList(futures), new FutureCallback<>() {
@Override
public void onSuccess(@Nullable List<Void> voids) {
futureToSet.set(null); futureToSet.set(null);
}
@Override
public void onFailure(Throwable throwable) {
String errMsg = String.format("[%s] Exception during saving edge events [%s]!", edge.getId(), relationRequestMsg);
log.error(errMsg, throwable);
futureToSet.setException(new RuntimeException(errMsg, throwable));
}
}, dbCallbackExecutorService);
} else {
futureToSet.set(null);
}
} catch (Exception e) { } catch (Exception e) {
log.error("Exception during loading relation(s) to edge on sync!", e); log.error("Exception during loading relation(s) to edge on sync!", e);
futureToSet.setException(e); futureToSet.setException(e);
@ -243,8 +268,9 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
log.error("[{}] Can't find relation by query. Entity id [{}]", tenantId, entityId, t); String errMsg = String.format("[%s] Can't find relation by query. Entity id [%s]!", tenantId, entityId);
futureToSet.setException(t); log.error(errMsg, t);
futureToSet.setException(new RuntimeException(errMsg, t));
} }
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
return futureToSet; return futureToSet;
@ -260,40 +286,42 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
@Override @Override
public ListenableFuture<Void> processDeviceCredentialsRequestMsg(TenantId tenantId, Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) { public ListenableFuture<Void> processDeviceCredentialsRequestMsg(TenantId tenantId, Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) {
log.trace("[{}] processDeviceCredentialsRequestMsg [{}][{}]", tenantId, edge.getName(), deviceCredentialsRequestMsg); log.trace("[{}] processDeviceCredentialsRequestMsg [{}][{}]", tenantId, edge.getName(), deviceCredentialsRequestMsg);
if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) { if (deviceCredentialsRequestMsg.getDeviceIdMSB() == 0 || deviceCredentialsRequestMsg.getDeviceIdLSB() == 0) {
DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB()));
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE,
EdgeEventActionType.CREDENTIALS_UPDATED, deviceId, null);
}
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
} }
DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB()));
return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE,
EdgeEventActionType.CREDENTIALS_UPDATED, deviceId, null);
}
@Override @Override
public ListenableFuture<Void> processUserCredentialsRequestMsg(TenantId tenantId, Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) { public ListenableFuture<Void> processUserCredentialsRequestMsg(TenantId tenantId, Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) {
log.trace("[{}] processUserCredentialsRequestMsg [{}][{}]", tenantId, edge.getName(), userCredentialsRequestMsg); log.trace("[{}] processUserCredentialsRequestMsg [{}][{}]", tenantId, edge.getName(), userCredentialsRequestMsg);
if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) { if (userCredentialsRequestMsg.getUserIdMSB() == 0 || userCredentialsRequestMsg.getUserIdLSB() == 0) {
UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB()));
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.USER,
EdgeEventActionType.CREDENTIALS_UPDATED, userId, null);
}
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
} }
UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB()));
return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.USER,
EdgeEventActionType.CREDENTIALS_UPDATED, userId, null);
}
@Override @Override
public ListenableFuture<Void> processDeviceProfileDevicesRequestMsg(TenantId tenantId, Edge edge, DeviceProfileDevicesRequestMsg deviceProfileDevicesRequestMsg) { public ListenableFuture<Void> processDeviceProfileDevicesRequestMsg(TenantId tenantId, Edge edge, DeviceProfileDevicesRequestMsg deviceProfileDevicesRequestMsg) {
log.trace("[{}] processDeviceProfileDevicesRequestMsg [{}][{}]", tenantId, edge.getName(), deviceProfileDevicesRequestMsg); log.trace("[{}] processDeviceProfileDevicesRequestMsg [{}][{}]", tenantId, edge.getName(), deviceProfileDevicesRequestMsg);
if (deviceProfileDevicesRequestMsg.getDeviceProfileIdMSB() != 0 && deviceProfileDevicesRequestMsg.getDeviceProfileIdLSB() != 0) { if (deviceProfileDevicesRequestMsg.getDeviceProfileIdMSB() == 0 || deviceProfileDevicesRequestMsg.getDeviceProfileIdLSB() == 0) {
DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(deviceProfileDevicesRequestMsg.getDeviceProfileIdMSB(), deviceProfileDevicesRequestMsg.getDeviceProfileIdLSB()));
DeviceProfile deviceProfileById = deviceProfileService.findDeviceProfileById(tenantId, deviceProfileId);
if (deviceProfileById != null) {
syncDevices(tenantId, edge, deviceProfileById.getName());
}
}
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
} }
DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(deviceProfileDevicesRequestMsg.getDeviceProfileIdMSB(), deviceProfileDevicesRequestMsg.getDeviceProfileIdLSB()));
DeviceProfile deviceProfileById = deviceProfileService.findDeviceProfileById(tenantId, deviceProfileId);
if (deviceProfileById == null) {
return Futures.immediateFuture(null);
}
return syncDevices(tenantId, edge, deviceProfileById.getName());
}
private void syncDevices(TenantId tenantId, Edge edge, String deviceType) { private ListenableFuture<Void> syncDevices(TenantId tenantId, Edge edge, String deviceType) {
log.trace("[{}] syncDevices [{}][{}]", tenantId, edge.getName(), deviceType); log.trace("[{}] syncDevices [{}][{}]", tenantId, edge.getName(), deviceType);
List<ListenableFuture<Void>> futures = new ArrayList<>();
try { try {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData<Device> pageData; PageData<Device> pageData;
@ -302,7 +330,7 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size()); log.trace("[{}] [{}] device(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
for (Device device : pageData.getData()) { for (Device device : pageData.getData()) {
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ADDED, device.getId(), null); futures.add(saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.ADDED, device.getId(), null));
} }
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
@ -312,25 +340,26 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
} catch (Exception e) { } catch (Exception e) {
log.error("Exception during loading edge device(s) on sync!", e); log.error("Exception during loading edge device(s) on sync!", e);
} }
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
} }
@Override @Override
public ListenableFuture<Void> processWidgetBundleTypesRequestMsg(TenantId tenantId, Edge edge, public ListenableFuture<Void> processWidgetBundleTypesRequestMsg(TenantId tenantId, Edge edge,
WidgetBundleTypesRequestMsg widgetBundleTypesRequestMsg) { WidgetBundleTypesRequestMsg widgetBundleTypesRequestMsg) {
log.trace("[{}] processWidgetBundleTypesRequestMsg [{}][{}]", tenantId, edge.getName(), widgetBundleTypesRequestMsg); log.trace("[{}] processWidgetBundleTypesRequestMsg [{}][{}]", tenantId, edge.getName(), widgetBundleTypesRequestMsg);
List<ListenableFuture<Void>> futures = new ArrayList<>();
if (widgetBundleTypesRequestMsg.getWidgetBundleIdMSB() != 0 && widgetBundleTypesRequestMsg.getWidgetBundleIdLSB() != 0) { if (widgetBundleTypesRequestMsg.getWidgetBundleIdMSB() != 0 && widgetBundleTypesRequestMsg.getWidgetBundleIdLSB() != 0) {
WidgetsBundleId widgetsBundleId = new WidgetsBundleId(new UUID(widgetBundleTypesRequestMsg.getWidgetBundleIdMSB(), widgetBundleTypesRequestMsg.getWidgetBundleIdLSB())); WidgetsBundleId widgetsBundleId = new WidgetsBundleId(new UUID(widgetBundleTypesRequestMsg.getWidgetBundleIdMSB(), widgetBundleTypesRequestMsg.getWidgetBundleIdLSB()));
WidgetsBundle widgetsBundleById = widgetsBundleService.findWidgetsBundleById(tenantId, widgetsBundleId); WidgetsBundle widgetsBundleById = widgetsBundleService.findWidgetsBundleById(tenantId, widgetsBundleId);
if (widgetsBundleById != null) { if (widgetsBundleById != null) {
List<WidgetType> widgetTypesToPush = List<WidgetType> widgetTypesToPush =
widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(widgetsBundleById.getTenantId(), widgetsBundleById.getAlias()); widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(widgetsBundleById.getTenantId(), widgetsBundleById.getAlias());
for (WidgetType widgetType : widgetTypesToPush) { for (WidgetType widgetType : widgetTypesToPush) {
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.WIDGET_TYPE, EdgeEventActionType.ADDED, widgetType.getId(), null); futures.add(saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.WIDGET_TYPE, EdgeEventActionType.ADDED, widgetType.getId(), null));
} }
} }
} }
return Futures.immediateFuture(null); return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
} }
@Override @Override
@ -343,46 +372,35 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
Futures.addCallback(entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId), new FutureCallback<>() { Futures.addCallback(entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId), new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable List<EntityView> entityViews) { public void onSuccess(@Nullable List<EntityView> entityViews) {
try { if (entityViews == null || entityViews.isEmpty()) {
if (entityViews != null && !entityViews.isEmpty()) { futureToSet.set(null);
List<ListenableFuture<Boolean>> futures = new ArrayList<>(); return;
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
for (EntityView entityView : entityViews) { for (EntityView entityView : entityViews) {
ListenableFuture<Boolean> future = relationService.checkRelation(tenantId, edge.getId(), entityView.getId(), ListenableFuture<Boolean> future = relationService.checkRelation(tenantId, edge.getId(), entityView.getId(),
EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE); EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
futures.add(future); futures.add(Futures.transformAsync(future, result -> {
Futures.addCallback(future, new FutureCallback<>() {
@Override
public void onSuccess(@Nullable Boolean result) {
if (Boolean.TRUE.equals(result)) { if (Boolean.TRUE.equals(result)) {
saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.ENTITY_VIEW, return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.ENTITY_VIEW,
EdgeEventActionType.ADDED, entityView.getId(), null); EdgeEventActionType.ADDED, entityView.getId(), null);
} else {
return Futures.immediateFuture(null);
} }
} }, dbCallbackExecutorService));
@Override
public void onFailure(Throwable t) {
// Do nothing - error handles in allAsList
}
}, dbCallbackExecutorService);
} }
Futures.addCallback(Futures.allAsList(futures), new FutureCallback<>() { Futures.addCallback(Futures.allAsList(futures), new FutureCallback<>() {
@Override @Override
public void onSuccess(@Nullable List<Boolean> result) { public void onSuccess(@Nullable List<Void> result) {
futureToSet.set(null); futureToSet.set(null);
} }
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
log.error("Exception during loading relation [{}] to edge on sync!", t, t); log.error("Exception during loading relation to edge on sync!", t);
futureToSet.setException(t); futureToSet.setException(t);
} }
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
} else {
futureToSet.set(null);
}
} catch (Exception e) {
log.error("Exception during loading relation(s) to edge on sync!", e);
futureToSet.setException(e);
}
} }
@Override @Override
@ -394,7 +412,7 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
return futureToSet; return futureToSet;
} }
private void saveEdgeEvent(TenantId tenantId, private ListenableFuture<Void> saveEdgeEvent(TenantId tenantId,
EdgeId edgeId, EdgeId edgeId,
EdgeEventType type, EdgeEventType type,
EdgeEventActionType action, EdgeEventActionType action,
@ -405,17 +423,9 @@ public class DefaultEdgeRequestsService implements EdgeRequestsService {
EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body); EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body);
Futures.addCallback(edgeEventService.saveAsync(edgeEvent), new FutureCallback<>() { return Futures.transform(edgeEventService.saveAsync(edgeEvent), unused -> {
@Override
public void onSuccess(@Nullable Void unused) {
tbClusterService.onEdgeEventUpdate(tenantId, edgeId); tbClusterService.onEdgeEventUpdate(tenantId, edgeId);
} return null;
@Override
public void onFailure(Throwable t) {
String errMsg = String.format("Failed to save edge event. edge event [%s]", edgeEvent);
log.warn(errMsg, t);
}
}, dbCallbackExecutorService); }, dbCallbackExecutorService);
} }