saveEdgeEvent(TenantId tenantId,
- EdgeId edgeId,
- EdgeEventType type,
- EdgeEventActionType action,
- EntityId entityId,
- JsonNode body) {
- log.debug("Pushing edge event to edge queue. tenantId [{}], edgeId [{}], type [{}], action[{}], entityId [{}], body [{}]",
- tenantId, edgeId, type, action, entityId, body);
-
- EdgeEvent edgeEvent = EdgeUtils.constructEdgeEvent(tenantId, edgeId, type, action, entityId, body);
-
- return Futures.transform(edgeEventService.saveAsync(edgeEvent), unused -> {
- clusterService.onEdgeEventUpdate(tenantId, edgeId);
- return null;
- }, dbCallBackExecutor);
- }
-
@Override
public void pushNotificationToEdge(TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg, TbCallback callback) {
log.debug("Pushing notification to edge {}", edgeNotificationMsg);
@@ -181,43 +157,43 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
future = edgeProcessor.processEdgeNotification(tenantId, edgeNotificationMsg);
break;
case ASSET:
- future = assetProcessor.processAssetNotification(tenantId, edgeNotificationMsg);
+ future = assetProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case DEVICE:
- future = deviceProcessor.processDeviceNotification(tenantId, edgeNotificationMsg);
+ future = deviceProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case ENTITY_VIEW:
- future = entityViewProcessor.processEntityViewNotification(tenantId, edgeNotificationMsg);
+ future = entityViewProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case DASHBOARD:
- future = dashboardProcessor.processDashboardNotification(tenantId, edgeNotificationMsg);
+ future = dashboardProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case RULE_CHAIN:
- future = ruleChainProcessor.processRuleChainNotification(tenantId, edgeNotificationMsg);
+ future = ruleChainProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case USER:
- future = userProcessor.processUserNotification(tenantId, edgeNotificationMsg);
+ future = userProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case CUSTOMER:
future = customerProcessor.processCustomerNotification(tenantId, edgeNotificationMsg);
break;
case DEVICE_PROFILE:
- future = deviceProfileProcessor.processDeviceProfileNotification(tenantId, edgeNotificationMsg);
+ future = deviceProfileProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case ASSET_PROFILE:
- future = assetProfileProcessor.processAssetProfileNotification(tenantId, edgeNotificationMsg);
+ future = assetProfileProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case OTA_PACKAGE:
- future = otaPackageProcessor.processOtaPackageNotification(tenantId, edgeNotificationMsg);
+ future = otaPackageProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case WIDGETS_BUNDLE:
- future = widgetBundleProcessor.processWidgetsBundleNotification(tenantId, edgeNotificationMsg);
+ future = widgetBundleProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case WIDGET_TYPE:
- future = widgetTypeProcessor.processWidgetTypeNotification(tenantId, edgeNotificationMsg);
+ future = widgetTypeProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case QUEUE:
- future = queueProcessor.processQueueNotification(tenantId, edgeNotificationMsg);
+ future = queueProcessor.processEntityNotification(tenantId, edgeNotificationMsg);
break;
case ALARM:
future = alarmProcessor.processAlarmNotification(tenantId, edgeNotificationMsg);
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java
new file mode 100644
index 0000000000..43b05094a4
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java
@@ -0,0 +1,158 @@
+/**
+ * Copyright © 2016-2023 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.service.edge;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.event.TransactionalEventListener;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.cluster.TbClusterService;
+import org.thingsboard.server.common.data.OtaPackageInfo;
+import org.thingsboard.server.common.data.User;
+import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
+import org.thingsboard.server.common.data.edge.EdgeEventActionType;
+import org.thingsboard.server.common.data.edge.EdgeEventType;
+import org.thingsboard.server.common.data.relation.EntityRelation;
+import org.thingsboard.server.common.data.relation.RelationTypeGroup;
+import org.thingsboard.server.common.data.rule.RuleChain;
+import org.thingsboard.server.common.data.rule.RuleChainType;
+import org.thingsboard.server.common.data.security.Authority;
+import org.thingsboard.server.dao.edge.EdgeSynchronizationManager;
+import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent;
+import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
+import org.thingsboard.server.dao.eventsourcing.RelationActionEvent;
+import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
+
+import javax.annotation.PostConstruct;
+
+import static org.thingsboard.server.service.entitiy.DefaultTbNotificationEntityService.edgeTypeByActionType;
+
+
+/**
+ * This event listener does not support async event processing because relay on ThreadLocal
+ * Another possible approach is to implement a special annotation and a bunch of classes similar to TransactionalApplicationListener
+ * This class is the simplest approach to maintain edge synchronization within the single class.
+ *
+ * For async event publishers, you have to decide whether publish event on creating async task in the same thread where dao method called
+ * @Autowired
+ * EdgeEventSynchronizationManager edgeSynchronizationManager
+ * ...
+ * //some async write action make future
+ * if (!edgeSynchronizationManager.isSync()) {
+ * future.addCallback(eventPublisher.publishEvent(...))
+ * }
+ * */
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class EdgeEventSourcingListener {
+
+ private final TbClusterService tbClusterService;
+ private final EdgeSynchronizationManager edgeSynchronizationManager;
+
+ @PostConstruct
+ public void init() {
+ log.info("EdgeEventSourcingListener initiated");
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(SaveEntityEvent> event) {
+ if (edgeSynchronizationManager.isSync()) {
+ return;
+ }
+ try {
+ if (!isValidEdgeEventEntity(event.getEntity())) {
+ return;
+ }
+ log.trace("[{}] SaveEntityEvent called: {}", event.getTenantId(), event);
+ EdgeEventActionType action = Boolean.TRUE.equals(event.getAdded()) ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED;
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), null, event.getEntityId(),
+ null, null, action);
+ } catch (Exception e) {
+ log.error("[{}] failed to process SaveEntityEvent: {}", event.getTenantId(), event);
+ }
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(DeleteEntityEvent> event) {
+ if (edgeSynchronizationManager.isSync()) {
+ return;
+ }
+ try {
+ log.trace("[{}] DeleteEntityEvent called: {}", event.getTenantId(), event);
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), event.getEdgeId(), event.getEntityId(),
+ JacksonUtil.toString(event.getEntity()), null, EdgeEventActionType.DELETED);
+ } catch (Exception e) {
+ log.error("[{}] failed to process DeleteEntityEvent: {}", event.getTenantId(), event);
+ }
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(ActionEntityEvent event) {
+ if (edgeSynchronizationManager.isSync()) {
+ return;
+ }
+ try {
+ log.trace("[{}] ActionEntityEvent called: {}", event.getTenantId(), event);
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), event.getEdgeId(), event.getEntityId(),
+ event.getBody(), null, edgeTypeByActionType(event.getActionType()));
+ } catch (Exception e) {
+ log.error("[{}] failed to process ActionEntityEvent: {}", event.getTenantId(), event);
+ }
+ }
+
+ @TransactionalEventListener(fallbackExecution = true)
+ public void handleEvent(RelationActionEvent event) {
+ if (edgeSynchronizationManager.isSync()) {
+ return;
+ }
+ try {
+ EntityRelation relation = event.getRelation();
+ if (relation == null) {
+ log.trace("[{}] skipping RelationActionEvent event in case relation is null: {}", event.getTenantId(), event);
+ return;
+ }
+ if (!RelationTypeGroup.COMMON.equals(relation.getTypeGroup())) {
+ log.trace("[{}] skipping RelationActionEvent event in case NOT COMMON relation type group: {}", event.getTenantId(), event);
+ return;
+ }
+ log.trace("[{}] RelationActionEvent called: {}", event.getTenantId(), event);
+ tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), null, null,
+ JacksonUtil.toString(relation), EdgeEventType.RELATION, edgeTypeByActionType(event.getActionType()));
+ } catch (Exception e) {
+ log.error("[{}] failed to process RelationActionEvent: {}", event.getTenantId(), event);
+ }
+ }
+
+ private boolean isValidEdgeEventEntity(Object entity) {
+ if (entity instanceof OtaPackageInfo) {
+ OtaPackageInfo otaPackageInfo = (OtaPackageInfo) entity;
+ return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData();
+ } else if (entity instanceof RuleChain) {
+ RuleChain ruleChain = (RuleChain) entity;
+ return RuleChainType.EDGE.equals(ruleChain.getType());
+ } else if (entity instanceof User) {
+ User user = (User) entity;
+ return !Authority.SYS_ADMIN.equals(user.getAuthority());
+ } else if (entity instanceof AlarmApiCallResult) {
+ AlarmApiCallResult alarmApiCallResult = (AlarmApiCallResult) entity;
+ return alarmApiCallResult.isModified();
+ }
+ // Default: If the entity doesn't match any of the conditions, consider it as valid.
+ return true;
+ }
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java
index bda510a762..d002854155 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java
@@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.BooleanDataEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
+import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
@@ -71,10 +72,6 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
-import static org.thingsboard.server.common.data.DataConstants.CONNECT_EVENT;
-import static org.thingsboard.server.common.data.DataConstants.DISCONNECT_EVENT;
-import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE;
-
@Service
@Slf4j
@ConditionalOnProperty(prefix = "edges", value = "enabled", havingValue = "true")
@@ -278,7 +275,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, true);
long lastConnectTs = System.currentTimeMillis();
save(edgeId, DefaultDeviceStateService.LAST_CONNECT_TIME, lastConnectTs);
- pushRuleEngineMessage(edgeGrpcSession.getEdge().getTenantId(), edgeId, lastConnectTs, CONNECT_EVENT);
+ pushRuleEngineMessage(edgeGrpcSession.getEdge().getTenantId(), edgeId, lastConnectTs, TbMsgType.CONNECT_EVENT);
cancelScheduleEdgeEventsCheck(edgeId);
scheduleEdgeEventsCheck(edgeGrpcSession);
}
@@ -341,7 +338,10 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
sessionNewEvents.put(edgeId, false);
Futures.addCallback(session.processEdgeEvents(), new FutureCallback<>() {
@Override
- public void onSuccess(Void result) {
+ public void onSuccess(Boolean newEventsAdded) {
+ if (Boolean.TRUE.equals(newEventsAdded)) {
+ sessionNewEvents.put(edgeId, true);
+ }
scheduleEdgeEventsCheck(session);
}
@@ -380,21 +380,26 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
}
}
- private void onEdgeDisconnect(EdgeId edgeId) {
- log.info("[{}] edge disconnected!", edgeId);
- EdgeGrpcSession removed = sessions.remove(edgeId);
- final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock());
- newEventLock.lock();
- try {
- sessionNewEvents.remove(edgeId);
- } finally {
- newEventLock.unlock();
+ private void onEdgeDisconnect(EdgeId edgeId, UUID sessionId) {
+ log.info("[{}][{}] edge disconnected!", edgeId, sessionId);
+ EdgeGrpcSession toRemove = sessions.get(edgeId);
+ if (toRemove.getSessionId().equals(sessionId)) {
+ toRemove = sessions.remove(edgeId);
+ final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock());
+ newEventLock.lock();
+ try {
+ sessionNewEvents.remove(edgeId);
+ } finally {
+ newEventLock.unlock();
+ }
+ save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false);
+ long lastDisconnectTs = System.currentTimeMillis();
+ save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, lastDisconnectTs);
+ pushRuleEngineMessage(toRemove.getEdge().getTenantId(), edgeId, lastDisconnectTs, TbMsgType.DISCONNECT_EVENT);
+ cancelScheduleEdgeEventsCheck(edgeId);
+ } else {
+ log.debug("[{}] edge session [{}] is not available anymore, nothing to remove. most probably this session is already outdated!", edgeId, sessionId);
}
- save(edgeId, DefaultDeviceStateService.ACTIVITY_STATE, false);
- long lastDisconnectTs = System.currentTimeMillis();
- save(edgeId, DefaultDeviceStateService.LAST_DISCONNECT_TIME, lastDisconnectTs);
- pushRuleEngineMessage(removed.getEdge().getTenantId(), edgeId, lastDisconnectTs, DISCONNECT_EVENT);
- cancelScheduleEdgeEventsCheck(edgeId);
}
private void save(EdgeId edgeId, String key, long value) {
@@ -443,10 +448,10 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
}
}
- private void pushRuleEngineMessage(TenantId tenantId, EdgeId edgeId, long ts, String msgType) {
+ private void pushRuleEngineMessage(TenantId tenantId, EdgeId edgeId, long ts, TbMsgType msgType) {
try {
ObjectNode edgeState = JacksonUtil.newObjectNode();
- if (msgType.equals(CONNECT_EVENT)) {
+ if (msgType.equals(TbMsgType.CONNECT_EVENT)) {
edgeState.put(DefaultDeviceStateService.ACTIVITY_STATE, true);
edgeState.put(DefaultDeviceStateService.LAST_CONNECT_TIME, ts);
} else {
@@ -456,7 +461,7 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
String data = JacksonUtil.toString(edgeState);
TbMsgMetaData md = new TbMsgMetaData();
if (!persistToTelemetry) {
- md.putValue(DataConstants.SCOPE, SERVER_SCOPE);
+ md.putValue(DataConstants.SCOPE, DataConstants.SERVER_SCOPE);
}
TbMsg tbMsg = TbMsg.newMsg(msgType, edgeId, md, TbMsgDataType.JSON, data);
clusterService.pushMsgToRuleEngine(tenantId, edgeId, tbMsg, null);
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
index 33aed92682..4f0f5d277a 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
@@ -24,6 +24,7 @@ import io.grpc.stub.StreamObserver;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
+import org.springframework.data.util.Pair;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.Edge;
@@ -35,6 +36,8 @@ import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
+import org.thingsboard.server.common.data.page.SortOrder;
+import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
import org.thingsboard.server.gen.edge.v1.AttributesRequestMsg;
import org.thingsboard.server.gen.edge.v1.ConnectRequestMsg;
@@ -68,17 +71,15 @@ import org.thingsboard.server.service.edge.rpc.fetch.GeneralEdgeEventFetcher;
import java.io.Closeable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
@Slf4j
@Data
@@ -89,10 +90,11 @@ public final class EdgeGrpcSession implements Closeable {
private static final int MAX_DOWNLINK_ATTEMPTS = 10; // max number of attemps to send downlink message if edge connected
private static final String QUEUE_START_TS_ATTR_KEY = "queueStartTs";
+ private static final String QUEUE_START_SEQ_ID_ATTR_KEY = "queueStartSeqId";
private final UUID sessionId;
private final BiConsumer sessionOpenListener;
- private final Consumer sessionCloseListener;
+ private final BiConsumer sessionCloseListener;
private final EdgeSessionState sessionState = new EdgeSessionState();
@@ -103,6 +105,12 @@ public final class EdgeGrpcSession implements Closeable {
private boolean connected;
private boolean syncCompleted;
+ private Long newStartTs;
+ private Long previousStartTs;
+ private Long newStartSeqId;
+ private Long previousStartSeqId;
+ private Long seqIdEnd;
+
private EdgeVersion edgeVersion;
private int maxInboundMessageSize;
@@ -111,7 +119,7 @@ public final class EdgeGrpcSession implements Closeable {
private ScheduledExecutorService sendDownlinkExecutorService;
EdgeGrpcSession(EdgeContextComponent ctx, StreamObserver outputStream, BiConsumer sessionOpenListener,
- Consumer sessionCloseListener, ScheduledExecutorService sendDownlinkExecutorService, int maxInboundMessageSize) {
+ BiConsumer sessionCloseListener, ScheduledExecutorService sendDownlinkExecutorService, int maxInboundMessageSize) {
this.sessionId = UUID.randomUUID();
this.ctx = ctx;
this.outputStream = outputStream;
@@ -180,7 +188,7 @@ public final class EdgeGrpcSession implements Closeable {
connected = false;
if (edge != null) {
try {
- sessionCloseListener.accept(edge.getId());
+ sessionCloseListener.accept(edge.getId(), sessionId);
} catch (Exception ignored) {
}
}
@@ -204,10 +212,10 @@ public final class EdgeGrpcSession implements Closeable {
EdgeEventFetcher next = cursor.getNext();
log.info("[{}][{}] starting sync process, cursor current idx = {}, class = {}",
edge.getTenantId(), edge.getId(), cursor.getCurrentIdx(), next.getClass().getSimpleName());
- ListenableFuture uuidListenableFuture = startProcessingEdgeEvents(next);
- Futures.addCallback(uuidListenableFuture, new FutureCallback<>() {
+ ListenableFuture> future = startProcessingEdgeEvents(next);
+ Futures.addCallback(future, new FutureCallback<>() {
@Override
- public void onSuccess(@Nullable UUID result) {
+ public void onSuccess(@Nullable Pair result) {
doSync(cursor);
}
@@ -288,7 +296,7 @@ public final class EdgeGrpcSession implements Closeable {
} catch (Exception e) {
log.error("[{}] Failed to send downlink message [{}]", this.sessionId, downlinkMsg, e);
connected = false;
- sessionCloseListener.accept(edge.getId());
+ sessionCloseListener.accept(edge.getId(), sessionId);
} finally {
downlinkMsgLock.unlock();
}
@@ -307,36 +315,51 @@ public final class EdgeGrpcSession implements Closeable {
sendDownlinkMsg(edgeConfigMsg);
}
- ListenableFuture processEdgeEvents() throws Exception {
- SettableFuture result = SettableFuture.create();
+ ListenableFuture processEdgeEvents() throws Exception {
+ SettableFuture result = SettableFuture.create();
log.trace("[{}] starting processing edge events", this.sessionId);
if (isConnected() && isSyncCompleted()) {
- Long queueStartTs = getQueueStartTs().get();
+ Pair startTsAndSeqId = getQueueStartTsAndSeqId().get();
+ this.previousStartTs = startTsAndSeqId.getFirst();
+ this.previousStartSeqId = startTsAndSeqId.getSecond();
GeneralEdgeEventFetcher fetcher = new GeneralEdgeEventFetcher(
- queueStartTs,
+ this.previousStartTs,
+ this.previousStartSeqId,
+ this.seqIdEnd,
+ false,
+ Integer.toUnsignedLong(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount()),
ctx.getEdgeEventService());
- ListenableFuture ifOffsetFuture = startProcessingEdgeEvents(fetcher);
- Futures.addCallback(ifOffsetFuture, new FutureCallback<>() {
+ Futures.addCallback(startProcessingEdgeEvents(fetcher), new FutureCallback<>() {
@Override
- public void onSuccess(@Nullable UUID ifOffset) {
- if (ifOffset != null) {
- Long newStartTs = Uuids.unixTimestamp(ifOffset);
- ListenableFuture> updateFuture = updateQueueStartTs(newStartTs);
+ public void onSuccess(@Nullable Pair newStartTsAndSeqId) {
+ if (newStartTsAndSeqId != null) {
+ ListenableFuture> updateFuture = updateQueueStartTsAndSeqId(newStartTsAndSeqId);
Futures.addCallback(updateFuture, new FutureCallback<>() {
@Override
public void onSuccess(@Nullable List list) {
- log.debug("[{}] queue offset was updated [{}][{}]", sessionId, ifOffset, newStartTs);
- result.set(null);
+ log.debug("[{}] queue offset was updated [{}]", sessionId, newStartTsAndSeqId);
+ if (fetcher.isSeqIdNewCycleStarted()) {
+ seqIdEnd = fetcher.getSeqIdEnd();
+ boolean newEventsAvailable = isNewEdgeEventsAvailable();
+ result.set(newEventsAvailable);
+ } else {
+ seqIdEnd = null;
+ boolean newEventsAvailable = isSeqIdStartedNewCycle();
+ if (!newEventsAvailable) {
+ newEventsAvailable = isNewEdgeEventsAvailable();
+ }
+ result.set(newEventsAvailable);
+ }
}
@Override
public void onFailure(Throwable t) {
- log.error("[{}] Failed to update queue offset [{}]", sessionId, ifOffset, t);
+ log.error("[{}] Failed to update queue offset [{}]", sessionId, newStartTsAndSeqId, t);
result.setException(t);
}
}, ctx.getGrpcCallbackExecutorService());
} else {
- log.trace("[{}] ifOffset is null. Skipping iteration without db update", sessionId);
+ log.trace("[{}] newStartTsAndSeqId is null. Skipping iteration without db update", sessionId);
result.set(null);
}
}
@@ -354,14 +377,14 @@ public final class EdgeGrpcSession implements Closeable {
return result;
}
- private ListenableFuture startProcessingEdgeEvents(EdgeEventFetcher fetcher) {
- SettableFuture result = SettableFuture.create();
+ private ListenableFuture> startProcessingEdgeEvents(EdgeEventFetcher fetcher) {
+ SettableFuture> result = SettableFuture.create();
PageLink pageLink = fetcher.getPageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount());
processEdgeEvents(fetcher, pageLink, result);
return result;
}
- private void processEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture result) {
+ private void processEdgeEvents(EdgeEventFetcher fetcher, PageLink pageLink, SettableFuture> result) {
try {
PageData pageData = fetcher.fetchEdgeEvents(edge.getTenantId(), edge, pageLink);
if (isConnected() && !pageData.getData().isEmpty()) {
@@ -377,8 +400,15 @@ public final class EdgeGrpcSession implements Closeable {
if (isConnected() && pageData.hasNext()) {
processEdgeEvents(fetcher, pageLink.nextPageLink(), result);
} else {
- UUID ifOffset = pageData.getData().get(pageData.getData().size() - 1).getUuidId();
- result.set(ifOffset);
+ EdgeEvent latestEdgeEvent = pageData.getData().get(pageData.getData().size() - 1);
+ UUID idOffset = latestEdgeEvent.getUuidId();
+ if (idOffset != null) {
+ Long newStartTs = Uuids.unixTimestamp(idOffset);
+ long newStartSeqId = latestEdgeEvent.getSeqId();
+ result.set(Pair.of(newStartTs, newStartSeqId));
+ } else {
+ result.set(null);
+ }
}
}
}
@@ -461,69 +491,113 @@ public final class EdgeGrpcSession implements Closeable {
}
}
- private DownlinkMsg convertToDownlinkMsg(EdgeEvent edgeEvent) {
- log.trace("[{}][{}] converting edge event to downlink msg [{}]", edge.getTenantId(), this.sessionId, edgeEvent);
- DownlinkMsg downlinkMsg = null;
- try {
- switch (edgeEvent.getAction()) {
- case UPDATED:
- case ADDED:
- case DELETED:
- case ASSIGNED_TO_EDGE:
- case UNASSIGNED_FROM_EDGE:
- case ALARM_ACK:
- case ALARM_CLEAR:
- case CREDENTIALS_UPDATED:
- case RELATION_ADD_OR_UPDATE:
- case RELATION_DELETED:
- case ASSIGNED_TO_CUSTOMER:
- case UNASSIGNED_FROM_CUSTOMER:
- case CREDENTIALS_REQUEST:
- case RPC_CALL:
- downlinkMsg = convertEntityEventToDownlink(edgeEvent);
- log.trace("[{}][{}] entity message processed [{}]", edgeEvent.getTenantId(), this.sessionId, downlinkMsg);
- break;
- case ATTRIBUTES_UPDATED:
- case POST_ATTRIBUTES:
- case ATTRIBUTES_DELETED:
- case TIMESERIES_UPDATED:
- downlinkMsg = ctx.getTelemetryProcessor().convertTelemetryEventToDownlink(edgeEvent);
- break;
- default:
- log.warn("[{}][{}] Unsupported action type [{}]", edge.getTenantId(), this.sessionId, edgeEvent.getAction());
+ private List convertToDownlinkMsgsPack(List edgeEvents) {
+ List result = new ArrayList<>();
+ for (EdgeEvent edgeEvent : edgeEvents) {
+ log.trace("[{}][{}] converting edge event to downlink msg [{}]", edge.getTenantId(), this.sessionId, edgeEvent);
+ DownlinkMsg downlinkMsg = null;
+ try {
+ switch (edgeEvent.getAction()) {
+ case UPDATED:
+ case ADDED:
+ case DELETED:
+ case ASSIGNED_TO_EDGE:
+ case UNASSIGNED_FROM_EDGE:
+ case ALARM_ACK:
+ case ALARM_CLEAR:
+ case CREDENTIALS_UPDATED:
+ case RELATION_ADD_OR_UPDATE:
+ case RELATION_DELETED:
+ case CREDENTIALS_REQUEST:
+ case RPC_CALL:
+ case ASSIGNED_TO_CUSTOMER:
+ case UNASSIGNED_FROM_CUSTOMER:
+ downlinkMsg = convertEntityEventToDownlink(edgeEvent);
+ log.trace("[{}][{}] entity message processed [{}]", edgeEvent.getTenantId(), this.sessionId, downlinkMsg);
+ break;
+ case ATTRIBUTES_UPDATED:
+ case POST_ATTRIBUTES:
+ case ATTRIBUTES_DELETED:
+ case TIMESERIES_UPDATED:
+ downlinkMsg = ctx.getTelemetryProcessor().convertTelemetryEventToDownlink(edgeEvent);
+ break;
+ default:
+ log.warn("[{}][{}] Unsupported action type [{}]", edge.getTenantId(), this.sessionId, edgeEvent.getAction());
+ }
+ } catch (Exception e) {
+ log.error("[{}][{}] Exception during converting edge event to downlink msg", edge.getTenantId(), this.sessionId, e);
+ }
+ if (downlinkMsg != null) {
+ result.add(downlinkMsg);
+ }
+ }
+ return result;
+ }
+
+ private ListenableFuture> getQueueStartTsAndSeqId() {
+ ListenableFuture> future =
+ ctx.getAttributesService().find(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, Arrays.asList(QUEUE_START_TS_ATTR_KEY, QUEUE_START_SEQ_ID_ATTR_KEY));
+ return Futures.transform(future, attributeKvEntries -> {
+ long startTs = 0L;
+ long startSeqId = 0L;
+ for (AttributeKvEntry attributeKvEntry : attributeKvEntries) {
+ if (QUEUE_START_TS_ATTR_KEY.equals(attributeKvEntry.getKey())) {
+ startTs = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L;
+ }
+ if (QUEUE_START_SEQ_ID_ATTR_KEY.equals(attributeKvEntry.getKey())) {
+ startSeqId = attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L;
+ }
+ }
+ if (startSeqId == 0L) {
+ startSeqId = findStartSeqIdFromOldestEventIfAny();
}
+ return Pair.of(startTs, startSeqId);
+ }, ctx.getGrpcCallbackExecutorService());
+ }
+
+ private boolean isSeqIdStartedNewCycle() {
+ try {
+ TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, this.newStartTs, System.currentTimeMillis());
+ PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), 0L, this.previousStartSeqId == 0 ? null : this.previousStartSeqId - 1, pageLink);
+ return !edgeEvents.getData().isEmpty();
} catch (Exception e) {
- log.error("[{}][{}] Exception during converting edge event to downlink msg", edge.getTenantId(), this.sessionId, e);
+ log.error("[{}][{}][{}] Failed to execute isSeqIdStartedNewCycle", edge.getTenantId(), edge.getId(), sessionId, e);
}
- return downlinkMsg;
+ return false;
}
- private List convertToDownlinkMsgsPack(List edgeEvents) {
- return edgeEvents
- .stream()
- .map(this::convertToDownlinkMsg)
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
+ private boolean isNewEdgeEventsAvailable() {
+ try {
+ TimePageLink pageLink = new TimePageLink(ctx.getEdgeEventStorageSettings().getMaxReadRecordsCount(), 0, null, null, this.newStartTs, System.currentTimeMillis());
+ PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), this.newStartSeqId, null, pageLink);
+ return !edgeEvents.getData().isEmpty();
+ } catch (Exception e) {
+ log.error("[{}][{}][{}] Failed to execute isNewEdgeEventsAvailable", edge.getTenantId(), edge.getId(), sessionId, e);
+ }
+ return false;
}
- private ListenableFuture getQueueStartTs() {
- ListenableFuture> future =
- ctx.getAttributesService().find(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, QUEUE_START_TS_ATTR_KEY);
- return Futures.transform(future, attributeKvEntryOpt -> {
- if (attributeKvEntryOpt != null && attributeKvEntryOpt.isPresent()) {
- AttributeKvEntry attributeKvEntry = attributeKvEntryOpt.get();
- return attributeKvEntry.getLongValue().isPresent() ? attributeKvEntry.getLongValue().get() : 0L;
- } else {
- return 0L;
+ private long findStartSeqIdFromOldestEventIfAny() {
+ long startSeqId = 0L;
+ try {
+ TimePageLink pageLink = new TimePageLink(1, 0, null, new SortOrder("createdTime"), null, null);
+ PageData edgeEvents = ctx.getEdgeEventService().findEdgeEvents(edge.getTenantId(), edge.getId(), null, null, pageLink);
+ if (!edgeEvents.getData().isEmpty()) {
+ startSeqId = edgeEvents.getData().get(0).getSeqId() - 1;
}
- }, ctx.getGrpcCallbackExecutorService());
+ } catch (Exception e) {
+ log.error("[{}][{}][{}] Failed to execute findStartSeqIdFromOldestEventIfAny", edge.getTenantId(), edge.getId(), sessionId, e);
+ }
+ return startSeqId;
}
- private ListenableFuture> updateQueueStartTs(Long newStartTs) {
- log.trace("[{}] updating QueueStartTs [{}][{}]", this.sessionId, edge.getId(), newStartTs);
- List attributes = Collections.singletonList(
- new BaseAttributeKvEntry(
- new LongDataEntry(QUEUE_START_TS_ATTR_KEY, newStartTs), System.currentTimeMillis()));
+ private ListenableFuture> updateQueueStartTsAndSeqId(Pair pair) {
+ this.newStartTs = pair.getFirst();
+ this.newStartSeqId = pair.getSecond();
+ log.trace("[{}] updateQueueStartTsAndSeqId [{}][{}][{}]", this.sessionId, edge.getId(), this.newStartTs, this.newStartSeqId);
+ List attributes = Arrays.asList(
+ new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_TS_ATTR_KEY, this.newStartTs), System.currentTimeMillis()),
+ new BaseAttributeKvEntry(new LongDataEntry(QUEUE_START_SEQ_ID_ATTR_KEY, this.newStartSeqId), System.currentTimeMillis()));
return ctx.getAttributesService().save(edge.getTenantId(), edge.getId(), DataConstants.SERVER_SCOPE, attributes);
}
@@ -693,8 +767,11 @@ public final class EdgeGrpcSession implements Closeable {
}
private void interruptPreviousSendDownlinkMsgsTask() {
- log.debug("[{}][{}][{}] Previous send downlink future was not properly completed, stopping it now!", edge.getTenantId(), edge.getId(), this.sessionId);
- stopCurrentSendDownlinkMsgsTask(true);
+ if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone()
+ || sessionState.getScheduledSendDownlinkTask() != null && !sessionState.getScheduledSendDownlinkTask().isCancelled()) {
+ log.debug("[{}][{}][{}] Previous send downlink future was not properly completed, stopping it now!", edge.getTenantId(), edge.getId(), this.sessionId);
+ stopCurrentSendDownlinkMsgsTask(true);
+ }
}
private void interruptGeneralProcessingOnSync() {
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java
index 69a83da0a0..447a73e5cf 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AlarmMsgConstructor.java
@@ -18,7 +18,10 @@ package org.thingsboard.server.service.edge.rpc.constructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityViewId;
@@ -47,13 +50,22 @@ public class AlarmMsgConstructor {
String entityName = null;
switch (alarm.getOriginator().getEntityType()) {
case DEVICE:
- entityName = deviceService.findDeviceById(tenantId, new DeviceId(alarm.getOriginator().getId())).getName();
+ Device deviceById = deviceService.findDeviceById(tenantId, new DeviceId(alarm.getOriginator().getId()));
+ if (deviceById != null) {
+ entityName = deviceById.getName();
+ }
break;
case ASSET:
- entityName = assetService.findAssetById(tenantId, new AssetId(alarm.getOriginator().getId())).getName();
+ Asset assetById = assetService.findAssetById(tenantId, new AssetId(alarm.getOriginator().getId()));
+ if (assetById != null) {
+ entityName = assetById.getName();
+ }
break;
case ENTITY_VIEW:
- entityName = entityViewService.findEntityViewById(tenantId, new EntityViewId(alarm.getOriginator().getId())).getName();
+ EntityView entityViewById = entityViewService.findEntityViewById(tenantId, new EntityViewId(alarm.getOriginator().getId()));
+ if (entityViewById != null) {
+ entityName = entityViewById.getName();
+ }
break;
}
AlarmUpdateMsg.Builder builder = AlarmUpdateMsg.newBuilder()
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/GeneralEdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/GeneralEdgeEventFetcher.java
index 327184e6a9..24008ece09 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/GeneralEdgeEventFetcher.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/GeneralEdgeEventFetcher.java
@@ -16,19 +16,27 @@
package org.thingsboard.server.service.edge.rpc.fetch;
import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
-import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.edge.EdgeEventService;
@AllArgsConstructor
+@Slf4j
public class GeneralEdgeEventFetcher implements EdgeEventFetcher {
private final Long queueStartTs;
+ private Long seqIdStart;
+ @Getter
+ private Long seqIdEnd;
+ @Getter
+ private boolean seqIdNewCycleStarted;
+ private Long maxReadRecordsCount;
private final EdgeEventService edgeEventService;
@Override
@@ -37,13 +45,32 @@ public class GeneralEdgeEventFetcher implements EdgeEventFetcher {
pageSize,
0,
null,
- new SortOrder("createdTime", SortOrder.Direction.ASC),
+ null,
queueStartTs,
- null);
+ System.currentTimeMillis());
}
@Override
public PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) {
- return edgeEventService.findEdgeEvents(tenantId, edge.getId(), (TimePageLink) pageLink, true);
+ try {
+ PageData edgeEvents = edgeEventService.findEdgeEvents(tenantId, edge.getId(), seqIdStart, seqIdEnd, (TimePageLink) pageLink);
+ if (edgeEvents.getData().isEmpty()) {
+ this.seqIdEnd = Math.max(this.maxReadRecordsCount, seqIdStart - this.maxReadRecordsCount);
+ edgeEvents = edgeEventService.findEdgeEvents(tenantId, edge.getId(), 0L, seqIdEnd, (TimePageLink) pageLink);
+ if (edgeEvents.getData().stream().anyMatch(ee -> ee.getSeqId() < seqIdStart)) {
+ log.info("[{}] seqId column of edge_event table started new cycle [{}]", tenantId, edge.getId());
+ this.seqIdNewCycleStarted = true;
+ this.seqIdStart = 0L;
+ } else {
+ edgeEvents = new PageData<>();
+ log.warn("[{}] unexpected edge notification message received. " +
+ "no new events found and seqId column of edge_event table doesn't started new cycle [{}]", tenantId, edge.getId());
+ }
+ }
+ return edgeEvents;
+ } catch (Exception e) {
+ log.error("[{}] failed to find edge events [{}]", tenantId, edge.getId());
+ }
+ return new PageData<>();
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java
index ac7c791338..56f4f06fa3 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java
@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
+import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EdgeUtils;
@@ -55,6 +56,7 @@ import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService;
+import org.thingsboard.server.dao.edge.EdgeSynchronizationManager;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.queue.QueueService;
@@ -249,15 +251,18 @@ public abstract class BaseEdgeProcessor {
@Autowired
protected QueueMsgConstructor queueMsgConstructor;
+ @Autowired
+ protected EdgeSynchronizationManager edgeSynchronizationManager;
+
@Autowired
protected DbCallbackExecutorService dbCallbackExecutorService;
protected ListenableFuture saveEdgeEvent(TenantId tenantId,
- EdgeId edgeId,
- EdgeEventType type,
- EdgeEventActionType action,
- EntityId entityId,
- JsonNode body) {
+ EdgeId edgeId,
+ EdgeEventType type,
+ EdgeEventActionType action,
+ EntityId entityId,
+ JsonNode body) {
log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], type[{}], " +
"action [{}], entityId [{}], body [{}]",
tenantId, edgeId, type, action, entityId, body);
@@ -288,7 +293,7 @@ public abstract class BaseEdgeProcessor {
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
}
- protected List> processActionForAllEdgesByTenantId(TenantId tenantId,
+ private List> processActionForAllEdgesByTenantId(TenantId tenantId,
EdgeEventType type,
EdgeEventActionType actionType,
EntityId entityId,
@@ -340,36 +345,46 @@ public abstract class BaseEdgeProcessor {
}
}
- protected ListenableFuture processEntityNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
+ public ListenableFuture processEntityNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
- EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type,
- new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
- EdgeId edgeId = safeGetEdgeId(edgeNotificationMsg);
- switch (actionType) {
- case ADDED:
- case UPDATED:
- case CREDENTIALS_UPDATED:
- case ASSIGNED_TO_CUSTOMER:
- case UNASSIGNED_FROM_CUSTOMER:
- 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 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);
+ EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
+ EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
+ if (type.isAllEdgesRelated()) {
+ return processEntityNotificationForAllEdges(tenantId, type, actionType, entityId);
+ } else {
+ JsonNode body = JacksonUtil.toJsonNode(edgeNotificationMsg.getBody());
+ EdgeId edgeId = safeGetEdgeId(edgeNotificationMsg);
+ switch (actionType) {
+ case UPDATED:
+ case CREDENTIALS_UPDATED:
+ case ASSIGNED_TO_CUSTOMER:
+ case UNASSIGNED_FROM_CUSTOMER:
+ if (edgeId != null) {
+ return saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, body);
} else {
- return Futures.immediateFuture(null);
+ return processNotificationToRelatedEdges(tenantId, entityId, type, actionType);
}
- }, dbCallbackExecutorService);
- default:
- return Futures.immediateFuture(null);
+ case DELETED:
+ EdgeEventActionType deleted = EdgeEventActionType.DELETED;
+ if (edgeId != null) {
+ return saveEdgeEvent(tenantId, edgeId, type, deleted, entityId, body);
+ } else {
+ return Futures.transform(Futures.allAsList(processActionForAllEdgesByTenantId(tenantId, type, deleted, entityId, body)),
+ voids -> null, dbCallbackExecutorService);
+ }
+ case ASSIGNED_TO_EDGE:
+ case UNASSIGNED_FROM_EDGE:
+ ListenableFuture future = saveEdgeEvent(tenantId, edgeId, type, actionType, entityId, body);
+ 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);
+ }
}
}
@@ -381,7 +396,7 @@ public abstract class BaseEdgeProcessor {
}
}
- private ListenableFuture pushNotificationToAllRelatedEdges(TenantId tenantId, EntityId entityId, EdgeEventType type, EdgeEventActionType actionType) {
+ private ListenableFuture processNotificationToRelatedEdges(TenantId tenantId, EntityId entityId, EdgeEventType type, EdgeEventActionType actionType) {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageData pageData;
List> futures = new ArrayList<>();
@@ -432,10 +447,7 @@ public abstract class BaseEdgeProcessor {
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
}
- protected ListenableFuture processEntityNotificationForAllEdges(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction());
- EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType());
- EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(type, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
+ private ListenableFuture processEntityNotificationForAllEdges(TenantId tenantId, EdgeEventType type, EdgeEventActionType actionType, EntityId entityId) {
switch (actionType) {
case ADDED:
case UPDATED:
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java
index 189d69e68d..0b86352c02 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java
@@ -16,6 +16,7 @@
package org.thingsboard.server.service.edge.rpc.processor.alarm;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
@@ -28,6 +29,7 @@ import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.EdgeId;
+import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
@@ -62,9 +64,9 @@ public class AlarmEdgeProcessor extends BaseAlarmProcessor {
AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
switch (actionType) {
case DELETED:
- EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
Alarm deletedAlarm = JacksonUtil.OBJECT_MAPPER.readValue(edgeNotificationMsg.getBody(), Alarm.class);
- return saveEdgeEvent(tenantId, edgeId, EdgeEventType.ALARM, actionType, alarmId, JacksonUtil.OBJECT_MAPPER.valueToTree(deletedAlarm));
+ List> delFutures = pushEventToAllRelatedEdges(tenantId, deletedAlarm.getOriginator(), alarmId, actionType, JacksonUtil.OBJECT_MAPPER.valueToTree(deletedAlarm));
+ return Futures.transform(Futures.allAsList(delFutures), voids -> null, dbCallbackExecutorService);
default:
ListenableFuture alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId);
return Futures.transformAsync(alarmFuture, alarm -> {
@@ -75,28 +77,33 @@ public class AlarmEdgeProcessor extends BaseAlarmProcessor {
if (type == null) {
return Futures.immediateFuture(null);
}
- PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
- PageData pageData;
- List> futures = new ArrayList<>();
- do {
- pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, alarm.getOriginator(), pageLink);
- if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
- for (EdgeId relatedEdgeId : pageData.getData()) {
- futures.add(saveEdgeEvent(tenantId,
- relatedEdgeId,
- EdgeEventType.ALARM,
- EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()),
- alarmId,
- null));
- }
- if (pageData.hasNext()) {
- pageLink = pageLink.nextPageLink();
- }
- }
- } while (pageData != null && pageData.hasNext());
+ List> futures = pushEventToAllRelatedEdges(tenantId, alarm.getOriginator(), alarmId, actionType, null);
return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService);
}, dbCallbackExecutorService);
}
}
+ private List> pushEventToAllRelatedEdges(TenantId tenantId, EntityId originatorId, AlarmId alarmId, EdgeEventActionType actionType, JsonNode body) {
+ PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
+ PageData pageData;
+ List> futures = new ArrayList<>();
+ do {
+ pageData = edgeService.findRelatedEdgeIdsByEntityId(tenantId, originatorId, pageLink);
+ if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
+ for (EdgeId relatedEdgeId : pageData.getData()) {
+ futures.add(saveEdgeEvent(tenantId,
+ relatedEdgeId,
+ EdgeEventType.ALARM,
+ actionType,
+ alarmId,
+ body));
+ }
+ if (pageData.hasNext()) {
+ pageLink = pageLink.nextPageLink();
+ }
+ }
+ } while (pageData != null && pageData.hasNext());
+ return futures;
+ }
+
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java
index be64f475a2..fbe141ab32 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java
@@ -49,6 +49,7 @@ public abstract class BaseAlarmProcessor extends BaseEdgeProcessor {
return Futures.immediateFuture(null);
}
try {
+ edgeSynchronizationManager.getSync().set(true);
switch (alarmUpdateMsg.getMsgType()) {
case ENTITY_CREATED_RPC_MESSAGE:
case ENTITY_UPDATED_RPC_MESSAGE:
@@ -72,26 +73,26 @@ public abstract class BaseAlarmProcessor extends BaseEdgeProcessor {
} else {
alarmService.updateAlarm(AlarmUpdateRequest.fromAlarm(alarm));
}
- return Futures.immediateFuture(null);
+ break;
case ALARM_ACK_RPC_MESSAGE:
Alarm alarmToAck = alarmService.findAlarmById(tenantId, alarmId);
if (alarmToAck != null) {
alarmService.acknowledgeAlarm(tenantId, alarmId, alarmUpdateMsg.getAckTs());
}
- return Futures.immediateFuture(null);
+ break;
case ALARM_CLEAR_RPC_MESSAGE:
Alarm alarmToClear = alarmService.findAlarmById(tenantId, alarmId);
if (alarmToClear != null) {
alarmService.clearAlarm(tenantId, alarmId, alarmUpdateMsg.getClearTs(),
JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails()));
}
- return Futures.immediateFuture(null);
+ break;
case ENTITY_DELETED_RPC_MESSAGE:
Alarm alarmToDelete = alarmService.findAlarmById(tenantId, alarmId);
if (alarmToDelete != null) {
alarmService.delAlarm(tenantId, alarmId);
}
- return Futures.immediateFuture(null);
+ break;
case UNRECOGNIZED:
default:
return handleUnsupportedMsgType(alarmUpdateMsg.getMsgType());
@@ -99,7 +100,10 @@ public abstract class BaseAlarmProcessor extends BaseEdgeProcessor {
} catch (Exception e) {
log.error("[{}] Failed to process alarm update msg [{}]", tenantId, alarmUpdateMsg, e);
return Futures.immediateFailedFuture(e);
+ } finally {
+ edgeSynchronizationManager.getSync().remove();
}
+ return Futures.immediateFuture(null);
}
private EntityId getAlarmOriginator(TenantId tenantId, String entityName, EntityType entityType) {
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessor.java
index 2fb7320219..d7824a7467 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessor.java
@@ -15,7 +15,6 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.asset;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
@@ -23,11 +22,9 @@ import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.AssetProfile;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.AssetId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.AssetUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -72,8 +69,4 @@ public class AssetEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processAssetNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotification(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetProfileEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetProfileEdgeProcessor.java
index 51c42e5764..ec0e0b9761 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetProfileEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetProfileEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.asset;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.asset.AssetProfile;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.AssetProfileId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -63,9 +60,4 @@ public class AssetProfileEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processAssetProfileNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
- }
-
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java
index 9651609bd3..14f566db0a 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.dashboard;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.DashboardId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -67,8 +64,4 @@ public class DashboardEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processDashboardNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotification(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/BaseDeviceProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/BaseDeviceProcessor.java
index 742acdbcda..1421cf32c0 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/BaseDeviceProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/BaseDeviceProcessor.java
@@ -97,7 +97,7 @@ public abstract class BaseDeviceProcessor extends BaseEdgeProcessor {
deviceCredentials.setCredentialsId(StringUtils.randomAlphanumeric(20));
deviceCredentialsService.createDeviceCredentials(device.getTenantId(), deviceCredentials);
}
- tbClusterService.onDeviceUpdated(savedDevice, created ? null : device, false);
+ tbClusterService.onDeviceUpdated(savedDevice, created ? null : device);
} finally {
deviceCreationLock.unlock();
}
@@ -113,6 +113,8 @@ public abstract class BaseDeviceProcessor extends BaseEdgeProcessor {
log.debug("Updating device credentials for device [{}]. New device credentials Id [{}], value [{}]",
device.getName(), deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentialsUpdateMsg.getCredentialsValue());
try {
+ edgeSynchronizationManager.getSync().set(true);
+
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, device.getId());
deviceCredentials.setCredentialsType(DeviceCredentialsType.valueOf(deviceCredentialsUpdateMsg.getCredentialsType()));
deviceCredentials.setCredentialsId(deviceCredentialsUpdateMsg.getCredentialsId());
@@ -123,6 +125,8 @@ public abstract class BaseDeviceProcessor extends BaseEdgeProcessor {
log.error("Can't update device credentials for device [{}], deviceCredentialsUpdateMsg [{}]",
device.getName(), deviceCredentialsUpdateMsg, e);
throw new RuntimeException(e);
+ } finally {
+ edgeSynchronizationManager.getSync().remove();
}
} else {
log.warn("Can't find device by id [{}], deviceCredentialsUpdateMsg [{}]", deviceId, deviceCredentialsUpdateMsg);
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java
index 3e617de8c6..d083c5b16f 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java
@@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rpc.RpcError;
@@ -46,7 +47,6 @@ import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse;
-import org.thingsboard.server.common.msg.session.SessionMsgType;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg;
import org.thingsboard.server.gen.edge.v1.DeviceCredentialsUpdateMsg;
@@ -54,7 +54,6 @@ import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg;
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.queue.TbQueueMsgMetadata;
import org.thingsboard.server.queue.util.TbCoreComponent;
@@ -71,6 +70,8 @@ public class DeviceEdgeProcessor extends BaseDeviceProcessor {
log.trace("[{}] executing processDeviceMsgFromEdge [{}] from edge [{}]", tenantId, deviceUpdateMsg, edge.getName());
DeviceId deviceId = new DeviceId(new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB()));
try {
+ edgeSynchronizationManager.getSync().set(true);
+
switch (deviceUpdateMsg.getMsgType()) {
case ENTITY_CREATED_RPC_MESSAGE:
case ENTITY_UPDATED_RPC_MESSAGE:
@@ -93,6 +94,8 @@ public class DeviceEdgeProcessor extends BaseDeviceProcessor {
} else {
return Futures.immediateFailedFuture(e);
}
+ } finally {
+ edgeSynchronizationManager.getSync().remove();
}
}
@@ -124,7 +127,7 @@ public class DeviceEdgeProcessor extends BaseDeviceProcessor {
try {
Device device = deviceService.findDeviceById(tenantId, deviceId);
ObjectNode entityNode = JacksonUtil.OBJECT_MAPPER.valueToTree(device);
- TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, device.getCustomerId(),
+ TbMsg tbMsg = TbMsg.newMsg(TbMsgType.ENTITY_CREATED, deviceId, device.getCustomerId(),
getActionTbMsgMetaData(edge, device.getCustomerId()), TbMsgDataType.JSON, JacksonUtil.OBJECT_MAPPER.writeValueAsString(entityNode));
tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, new TbQueueCallback() {
@Override
@@ -138,7 +141,7 @@ public class DeviceEdgeProcessor extends BaseDeviceProcessor {
}
});
} catch (JsonProcessingException | IllegalArgumentException e) {
- log.warn("[{}] Failed to push device action to rule engine: {}", deviceId, DataConstants.ENTITY_CREATED, e);
+ log.warn("[{}] Failed to push device action to rule engine: {}", deviceId, TbMsgType.ENTITY_CREATED.name(), e);
}
}
@@ -216,7 +219,7 @@ public class DeviceEdgeProcessor extends BaseDeviceProcessor {
ObjectNode data = JacksonUtil.newObjectNode();
data.put("method", deviceRpcCallMsg.getRequestMsg().getMethod());
data.put("params", deviceRpcCallMsg.getRequestMsg().getParams());
- TbMsg tbMsg = TbMsg.newMsg(SessionMsgType.TO_SERVER_RPC_REQUEST.name(), deviceId, null, metaData,
+ TbMsg tbMsg = TbMsg.newMsg(TbMsgType.TO_SERVER_RPC_REQUEST, deviceId, null, metaData,
TbMsgDataType.JSON, JacksonUtil.OBJECT_MAPPER.writeValueAsString(data));
tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, new TbQueueCallback() {
@Override
@@ -308,8 +311,4 @@ public class DeviceEdgeProcessor extends BaseDeviceProcessor {
.addDeviceCredentialsRequestMsg(deviceCredentialsRequestMsg);
return builder.build();
}
-
- public ListenableFuture processDeviceNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotification(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceProfileEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceProfileEdgeProcessor.java
index 5ddfecfdb1..c888ec2925 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceProfileEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceProfileEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.device;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.DeviceProfileId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -63,8 +60,4 @@ public class DeviceProfileEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processDeviceProfileNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java
index 29965fcc69..0964a434ba 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.entityview;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.EntityViewId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -67,8 +64,4 @@ public class EntityViewEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processEntityViewNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotification(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/ota/OtaPackageEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/ota/OtaPackageEdgeProcessor.java
index 8206e0f1b0..fae6399e3a 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/ota/OtaPackageEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/ota/OtaPackageEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.ota;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.OtaPackageId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -63,8 +60,4 @@ public class OtaPackageEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processOtaPackageNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/queue/QueueEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/queue/QueueEdgeProcessor.java
index cbacaf9276..8562582940 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/queue/QueueEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/queue/QueueEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.queue;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.QueueId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.queue.Queue;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -64,7 +61,4 @@ public class QueueEdgeProcessor extends BaseEdgeProcessor {
return downlinkMsg;
}
- public ListenableFuture processQueueNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/relation/BaseRelationProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/relation/BaseRelationProcessor.java
index df683bbbe2..9038cc9c33 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/relation/BaseRelationProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/relation/BaseRelationProcessor.java
@@ -34,8 +34,9 @@ import java.util.UUID;
public abstract class BaseRelationProcessor extends BaseEdgeProcessor {
public ListenableFuture processRelationMsg(TenantId tenantId, RelationUpdateMsg relationUpdateMsg) {
- log.trace("[{}] processRelationFromEdge [{}]", tenantId, relationUpdateMsg);
+ log.trace("[{}] processRelationMsg [{}]", tenantId, relationUpdateMsg);
try {
+ edgeSynchronizationManager.getSync().set(true);
EntityRelation entityRelation = new EntityRelation();
UUID fromUUID = new UUID(relationUpdateMsg.getFromIdMSB(), relationUpdateMsg.getFromIdLSB());
@@ -55,15 +56,15 @@ public abstract class BaseRelationProcessor extends BaseEdgeProcessor {
case ENTITY_UPDATED_RPC_MESSAGE:
if (isEntityExists(tenantId, entityRelation.getTo())
&& isEntityExists(tenantId, entityRelation.getFrom())) {
- return Futures.transform(relationService.saveRelationAsync(tenantId, entityRelation),
- (result) -> null, dbCallbackExecutorService);
+ relationService.saveRelation(tenantId, entityRelation);
+ break;
} else {
log.warn("Skipping relating update msg because from/to entity doesn't exists on edge, {}", relationUpdateMsg);
- return Futures.immediateFuture(null);
+ break;
}
case ENTITY_DELETED_RPC_MESSAGE:
- return Futures.transform(relationService.deleteRelationAsync(tenantId, entityRelation),
- (result) -> null, dbCallbackExecutorService);
+ relationService.deleteRelation(tenantId, entityRelation);
+ break;
case UNRECOGNIZED:
default:
return handleUnsupportedMsgType(relationUpdateMsg.getMsgType());
@@ -71,6 +72,9 @@ public abstract class BaseRelationProcessor extends BaseEdgeProcessor {
} catch (Exception e) {
log.error("[{}] Failed to process relation update msg [{}]", tenantId, relationUpdateMsg, e);
return Futures.immediateFailedFuture(e);
+ } finally {
+ edgeSynchronizationManager.getSync().remove();
}
+ return Futures.immediateFuture(null);
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java
index 69d4f7ef64..ba6fc1ef97 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java
@@ -15,13 +15,11 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.rule;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.RuleChainId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
@@ -29,7 +27,6 @@ import org.thingsboard.server.gen.edge.v1.EdgeVersion;
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -93,8 +90,4 @@ public class RuleChainEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processRuleChainNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotification(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java
index fece86b92a..5942628bf3 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java
@@ -50,11 +50,11 @@ import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
+import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
-import org.thingsboard.server.common.msg.session.SessionMsgType;
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
import org.thingsboard.server.common.transport.util.JsonUtils;
import org.thingsboard.server.dao.model.ModelConstants;
@@ -184,7 +184,7 @@ public abstract class BaseTelemetryProcessor extends BaseEdgeProcessor {
JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList());
metaData.putValue("ts", tsKv.getTs() + "");
var defaultQueueAndRuleChain = getDefaultQueueNameAndRuleChainId(tenantId, entityId);
- TbMsg tbMsg = TbMsg.newMsg(defaultQueueAndRuleChain.getKey(), SessionMsgType.POST_TELEMETRY_REQUEST.name(), entityId, customerId, metaData, gson.toJson(json), defaultQueueAndRuleChain.getValue(), null);
+ TbMsg tbMsg = TbMsg.newMsg(defaultQueueAndRuleChain.getKey(), TbMsgType.POST_TELEMETRY_REQUEST, entityId, customerId, metaData, gson.toJson(json), defaultQueueAndRuleChain.getValue(), null);
tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() {
@Override
public void onSuccess(TbQueueMsgMetadata metadata) {
@@ -228,7 +228,7 @@ public abstract class BaseTelemetryProcessor extends BaseEdgeProcessor {
SettableFuture futureToSet = SettableFuture.create();
JsonObject json = JsonUtils.getJsonObject(msg.getKvList());
var defaultQueueAndRuleChain = getDefaultQueueNameAndRuleChainId(tenantId, entityId);
- TbMsg tbMsg = TbMsg.newMsg(defaultQueueAndRuleChain.getKey(), SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), entityId, customerId, metaData, gson.toJson(json), defaultQueueAndRuleChain.getValue(), null);
+ TbMsg tbMsg = TbMsg.newMsg(defaultQueueAndRuleChain.getKey(), TbMsgType.POST_ATTRIBUTES_REQUEST, entityId, customerId, metaData, gson.toJson(json), defaultQueueAndRuleChain.getValue(), null);
tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() {
@Override
public void onSuccess(TbQueueMsgMetadata metadata) {
@@ -257,7 +257,7 @@ public abstract class BaseTelemetryProcessor extends BaseEdgeProcessor {
@Override
public void onSuccess(@Nullable Void tmp) {
var defaultQueueAndRuleChain = getDefaultQueueNameAndRuleChainId(tenantId, entityId);
- TbMsg tbMsg = TbMsg.newMsg(defaultQueueAndRuleChain.getKey(), DataConstants.ATTRIBUTES_UPDATED, entityId,
+ TbMsg tbMsg = TbMsg.newMsg(defaultQueueAndRuleChain.getKey(), TbMsgType.ATTRIBUTES_UPDATED, entityId,
customerId, metaData, gson.toJson(json), defaultQueueAndRuleChain.getValue(), null);
tbClusterService.pushMsgToRuleEngine(tenantId, tbMsg.getOriginator(), tbMsg, new TbQueueCallback() {
@Override
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java
index 9070686fd6..de40fdb1a3 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/user/UserEdgeProcessor.java
@@ -15,19 +15,16 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.user;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.edge.EdgeEvent;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.security.UserCredentials;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -67,11 +64,9 @@ public class UserEdgeProcessor extends BaseEdgeProcessor {
.addUserCredentialsUpdateMsg(userCredentialsUpdateMsg)
.build();
}
+ break;
}
return downlinkMsg;
}
- public ListenableFuture processUserNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetBundleEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetBundleEdgeProcessor.java
index a429816a31..d50e752fdf 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetBundleEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetBundleEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.widget;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.EdgeEvent;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -63,8 +60,4 @@ public class WidgetBundleEdgeProcessor extends BaseEdgeProcessor {
}
return downlinkMsg;
}
-
- public ListenableFuture processWidgetsBundleNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetTypeEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetTypeEdgeProcessor.java
index 3caad57081..5171724439 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetTypeEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/widget/WidgetTypeEdgeProcessor.java
@@ -15,18 +15,15 @@
*/
package org.thingsboard.server.service.edge.rpc.processor.widget;
-import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.edge.EdgeEvent;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg;
-import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
@@ -64,7 +61,4 @@ public class WidgetTypeEdgeProcessor extends BaseEdgeProcessor {
return downlinkMsg;
}
- public ListenableFuture processWidgetTypeNotification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
- return processEntityNotificationForAllEdges(tenantId, edgeNotificationMsg);
- }
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java
index 0a75404fb4..f2465c9398 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java
@@ -21,29 +21,21 @@ import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg;
import org.thingsboard.server.cluster.TbClusterService;
-import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
-import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
-import org.thingsboard.server.common.data.alarm.Alarm;
-import org.thingsboard.server.common.data.alarm.AlarmComment;
-import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
-import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
-import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.relation.EntityRelation;
-import org.thingsboard.server.common.data.rule.RuleChain;
-import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
@@ -51,8 +43,6 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.service.action.EntityActionService;
import org.thingsboard.server.service.gateway_device.GatewayNotificationsService;
-import java.util.List;
-
@Slf4j
@Service
@RequiredArgsConstructor
@@ -98,54 +88,6 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS
}
}
- @Override
- public void notifyDeleteEntity(TenantId tenantId, I entityId, E entity,
- CustomerId customerId, ActionType actionType,
- List relatedEdgeIds,
- User user, Object... additionalInfo) {
- logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo);
- sendDeleteNotificationMsg(tenantId, entityId, relatedEdgeIds, null);
- }
-
- @Override
- public void notifyDeleteAlarm(TenantId tenantId, Alarm alarm, EntityId originatorId, CustomerId customerId,
- List relatedEdgeIds, User user, String body, Object... additionalInfo) {
- logEntityAction(tenantId, originatorId, alarm, customerId, ActionType.DELETED, user, additionalInfo);
- sendAlarmDeleteNotificationMsg(tenantId, alarm, relatedEdgeIds, body);
- }
-
- @Override
- public void notifyDeleteRuleChain(TenantId tenantId, RuleChain ruleChain, List relatedEdgeIds, User user) {
- RuleChainId ruleChainId = ruleChain.getId();
- logEntityAction(tenantId, ruleChainId, ruleChain, null, ActionType.DELETED, user, null, ruleChainId.toString());
- if (RuleChainType.EDGE.equals(ruleChain.getType())) {
- sendDeleteNotificationMsg(tenantId, ruleChainId, relatedEdgeIds, null);
- }
- }
-
- @Override
- public void notifySendMsgToEdgeService(TenantId tenantId, I entityId, EdgeEventActionType edgeEventActionType) {
- sendEntityNotificationMsg(tenantId, entityId, edgeEventActionType);
- }
-
- @Override
- public void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId,
- CustomerId customerId, E entity,
- ActionType actionType,
- User user, Object... additionalInfo) {
- logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo);
- sendEntityNotificationMsg(tenantId, entityId, edgeTypeByActionType(actionType), JacksonUtil.toString(customerId));
- }
-
- @Override
- public void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId,
- CustomerId customerId, EdgeId edgeId,
- E entity, ActionType actionType,
- User user, Object... additionalInfo) {
- logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo);
- sendEntityAssignToEdgeNotificationMsg(tenantId, edgeId, entityId, edgeTypeByActionType(actionType));
- }
-
@Override
public void notifyCreateOrUpdateTenant(Tenant tenant, ComponentLifecycleEvent event) {
tbClusterService.onTenantChange(tenant, null);
@@ -168,18 +110,16 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS
@Override
public void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device,
- List relatedEdgeIds, User user, Object... additionalInfo) {
+ User user, Object... additionalInfo) {
gatewayNotificationsService.onDeviceDeleted(device);
tbClusterService.onDeviceDeleted(device, null);
-
- notifyDeleteEntity(tenantId, deviceId, device, customerId, ActionType.DELETED, relatedEdgeIds, user, additionalInfo);
+ logEntityAction(tenantId, deviceId, device, customerId, ActionType.DELETED, user, additionalInfo);
}
@Override
public void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device,
DeviceCredentials deviceCredentials, User user) {
tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(tenantId, deviceCredentials.getDeviceId(), deviceCredentials), null);
- sendEntityNotificationMsg(tenantId, deviceId, EdgeEventActionType.CREDENTIALS_UPDATED);
logEntityAction(tenantId, deviceId, device, customerId, ActionType.CREDENTIALS_UPDATED, user, deviceCredentials);
}
@@ -190,16 +130,6 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS
pushAssignedFromNotification(tenant, newTenantId, device);
}
- @Override
- public void notifyCreateOrUpdateEntity(TenantId tenantId, I entityId, E entity,
- CustomerId customerId, ActionType actionType,
- User user, Object... additionalInfo) {
- logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo);
- if (actionType == ActionType.UPDATED) {
- sendEntityNotificationMsg(tenantId, entityId, EdgeEventActionType.UPDATED);
- }
- }
-
@Override
public void notifyCreateOrUpdateOrDeleteEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge,
ActionType actionType, User user, Object... additionalInfo) {
@@ -222,71 +152,16 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS
}
@Override
- public void notifyCreateOrUpdateAlarm(AlarmInfo alarm, ActionType actionType, User user, Object... additionalInfo) {
- logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarm, alarm.getCustomerId(), actionType, user, additionalInfo);
- sendEntityNotificationMsg(alarm.getTenantId(), alarm.getId(), edgeTypeByActionType(actionType));
- }
-
- @Override
- public void notifyAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user) {
- logEntityAction(alarm.getTenantId(), alarm.getId(), alarm, alarm.getCustomerId(), actionType, user, alarmComment);
- }
-
- @Override
- public void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId,
- I entityId, E entity, User user,
- ActionType actionType, boolean sendNotifyMsgToEdge, Exception e,
- Object... additionalInfo) {
- logEntityAction(tenantId, entityId, entity, customerId, actionType, user, e, additionalInfo);
- if (sendNotifyMsgToEdge) {
- sendEntityNotificationMsg(tenantId, entityId, edgeTypeByActionType(actionType));
- }
- }
-
- @Override
- public void notifyRelation(TenantId tenantId, CustomerId customerId, EntityRelation relation, User user,
- ActionType actionType, Object... additionalInfo) {
- logEntityAction(tenantId, relation.getFrom(), null, customerId, actionType, user, additionalInfo);
- logEntityAction(tenantId, relation.getTo(), null, customerId, actionType, user, additionalInfo);
- if (!EntityType.EDGE.equals(relation.getFrom().getEntityType()) && !EntityType.EDGE.equals(relation.getTo().getEntityType())) {
- sendNotificationMsgToEdge(tenantId, null, null, JacksonUtil.toString(relation),
- EdgeEventType.RELATION, edgeTypeByActionType(actionType));
- }
- }
-
- private void sendEntityNotificationMsg(TenantId tenantId, EntityId entityId, EdgeEventActionType action) {
- sendEntityNotificationMsg(tenantId, entityId, action, null);
- }
-
- private void sendEntityNotificationMsg(TenantId tenantId, EntityId entityId, EdgeEventActionType action, String body) {
- sendNotificationMsgToEdge(tenantId, null, entityId, body, null, action);
- }
-
- private void sendAlarmDeleteNotificationMsg(TenantId tenantId, Alarm alarm, List edgeIds, String body) {
- sendDeleteNotificationMsg(tenantId, alarm.getId(), edgeIds, body);
- }
-
- private void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List edgeIds, String body) {
- if (edgeIds != null && !edgeIds.isEmpty()) {
- for (EdgeId edgeId : edgeIds) {
- sendNotificationMsgToEdge(tenantId, edgeId, entityId, body, null, EdgeEventActionType.DELETED);
- }
- }
- }
-
- private void sendEntityAssignToEdgeNotificationMsg(TenantId tenantId, EdgeId edgeId, EntityId entityId, EdgeEventActionType action) {
- sendNotificationMsgToEdge(tenantId, edgeId, entityId, null, null, action);
- }
-
- private void sendNotificationMsgToEdge(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body,
- EdgeEventType type, EdgeEventActionType action) {
- tbClusterService.sendNotificationMsgToEdge(tenantId, edgeId, entityId, body, type, action);
+ public void logEntityRelationAction(TenantId tenantId, CustomerId customerId, EntityRelation relation, User user,
+ ActionType actionType, Exception e, Object... additionalInfo) {
+ logEntityAction(tenantId, relation.getFrom(), null, customerId, actionType, user, e, additionalInfo);
+ logEntityAction(tenantId, relation.getTo(), null, customerId, actionType, user, e, additionalInfo);
}
private void pushAssignedFromNotification(Tenant currentTenant, TenantId newTenantId, Device assignedDevice) {
String data = JacksonUtil.toString(JacksonUtil.valueToTree(assignedDevice));
if (data != null) {
- TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_ASSIGNED_FROM_TENANT, assignedDevice.getId(),
+ TbMsg tbMsg = TbMsg.newMsg(TbMsgType.ENTITY_ASSIGNED_FROM_TENANT, assignedDevice.getId(),
assignedDevice.getCustomerId(), getMetaDataForAssignedFrom(currentTenant), TbMsgDataType.JSON, data);
tbClusterService.pushMsgToRuleEngine(newTenantId, assignedDevice.getId(), tbMsg, null);
}
@@ -327,6 +202,8 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS
return EdgeEventActionType.ASSIGNED_TO_EDGE;
case UNASSIGNED_FROM_EDGE:
return EdgeEventActionType.UNASSIGNED_FROM_EDGE;
+ case CREDENTIALS_UPDATED:
+ return EdgeEventActionType.CREDENTIALS_UPDATED;
default:
return null;
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java
index c5f8f85831..d14b2c6293 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java
@@ -19,12 +19,8 @@ import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
-import org.thingsboard.server.common.data.alarm.Alarm;
-import org.thingsboard.server.common.data.alarm.AlarmComment;
-import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
-import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId;
@@ -32,11 +28,8 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.relation.EntityRelation;
-import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.security.DeviceCredentials;
-import java.util.List;
-
public interface TbNotificationEntityService {
void logEntityAction(TenantId tenantId, I entityId, ActionType actionType, User user,
@@ -55,33 +48,6 @@ public interface TbNotificationEntityService {
ActionType actionType, User user, Exception e,
Object... additionalInfo);
- void notifyCreateOrUpdateEntity(TenantId tenantId, I entityId, E entity,
- CustomerId customerId, ActionType actionType,
- User user, Object... additionalInfo);
-
- void notifyDeleteEntity(TenantId tenantId, I entityId, E entity,
- CustomerId customerId, ActionType actionType,
- List relatedEdgeIds,
- User user, Object... additionalInfo);
-
- void notifyDeleteAlarm(TenantId tenantId, Alarm alarm, EntityId originatorId, CustomerId customerId,
- List relatedEdgeIds, User user, String body, Object... additionalInfo);
-
- void notifyDeleteRuleChain(TenantId tenantId, RuleChain ruleChain,
- List relatedEdgeIds, User user);
-
- void notifySendMsgToEdgeService(TenantId tenantId, I entityId, EdgeEventActionType edgeEventActionType);
-
- void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId,
- CustomerId customerId, E entity,
- ActionType actionType,
- User user, Object... additionalInfo);
-
- void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId,
- CustomerId customerId, EdgeId edgeId,
- E entity, ActionType actionType,
- User user, Object... additionalInfo);
-
void notifyCreateOrUpdateTenant(Tenant tenant, ComponentLifecycleEvent event);
void notifyDeleteTenant(Tenant tenant);
@@ -90,7 +56,7 @@ public interface TbNotificationEntityService {
Device oldDevice, ActionType actionType, User user, Object... additionalInfo);
void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device,
- List relatedEdgeIds, User user, Object... additionalInfo);
+ User user, Object... additionalInfo);
void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device,
DeviceCredentials deviceCredentials, User user);
@@ -101,16 +67,6 @@ public interface TbNotificationEntityService {
void notifyCreateOrUpdateOrDeleteEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge, ActionType actionType,
User user, Object... additionalInfo);
- void notifyCreateOrUpdateAlarm(AlarmInfo alarm, ActionType actionType, User user, Object... additionalInfo);
-
- void notifyAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user);
-
-
- void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId,
- I entityId, E entity, User user,
- ActionType actionType, boolean sendNotifyMsgToEdge,
- Exception e, Object... additionalInfo);
-
- void notifyRelation(TenantId tenantId, CustomerId customerId, EntityRelation relation, User user,
- ActionType actionType, Object... additionalInfo);
+ void logEntityRelationAction(TenantId tenantId, CustomerId customerId, EntityRelation relation, User user,
+ ActionType actionType, Exception e, Object... additionalInfo);
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java
index 6dfc81c747..282d11ab2a 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java
@@ -45,7 +45,8 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem
}
try {
AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment));
- notificationEntityService.notifyAlarmComment(alarm, savedAlarmComment, actionType, user);
+ notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getId(), alarm, alarm.getCustomerId(), actionType, user, savedAlarmComment);
+
return savedAlarmComment;
} catch (Exception e) {
notificationEntityService.logEntityAction(alarm.getTenantId(), emptyId(EntityType.ALARM), alarm, actionType, user, e, alarmComment);
@@ -62,7 +63,7 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem
String.format("User %s deleted his comment",
(user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName())));
AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.saveAlarmComment(alarm.getTenantId(), alarmComment));
- notificationEntityService.notifyAlarmComment(alarm, savedAlarmComment, ActionType.DELETED_COMMENT, user);
+ notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getId(), alarm, alarm.getCustomerId(), ActionType.DELETED_COMMENT, user, savedAlarmComment);
} else {
throw new ThingsboardException("System comment could not be deleted", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java
index caf65d39ec..e776c040c0 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java
@@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.alarm.AlarmCommentType;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
import org.thingsboard.server.common.data.alarm.AlarmInfo;
+import org.thingsboard.server.common.data.alarm.AlarmQueryV2;
import org.thingsboard.server.common.data.alarm.AlarmUpdateRequest;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
@@ -36,9 +37,13 @@ import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
+import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
@Service
@AllArgsConstructor
@@ -62,10 +67,6 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
if (!result.isSuccessful()) {
throw new ThingsboardException(ThingsboardErrorCode.ITEM_NOT_FOUND);
}
- actionType = result.isCreated() ? ActionType.ADDED : ActionType.UPDATED;
- if (result.isModified()) {
- notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), actionType, user);
- }
AlarmInfo resultAlarm = result.getAlarm();
if (alarm.isAcknowledged() && !resultAlarm.isAcknowledged()) {
resultAlarm = ack(resultAlarm, alarm.getAckTs(), user);
@@ -80,6 +81,10 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
} else if (newAssignee == null && curAssignee != null) {
resultAlarm = unassign(alarm, alarm.getAssignTs(), user);
}
+ if (result.isModified()) {
+ notificationEntityService.logEntityAction(tenantId, alarm.getOriginator(), resultAlarm,
+ resultAlarm.getCustomerId(), actionType, user);
+ }
return new Alarm(resultAlarm);
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ALARM), alarm, actionType, user, e);
@@ -98,6 +103,7 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
if (!result.isSuccessful()) {
throw new ThingsboardException(ThingsboardErrorCode.ITEM_NOT_FOUND);
}
+ AlarmInfo alarmInfo = result.getAlarm();
if (result.isModified()) {
AlarmComment alarmComment = AlarmComment.builder()
.alarmId(alarm.getId())
@@ -112,11 +118,12 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
} catch (ThingsboardException e) {
log.error("Failed to save alarm comment", e);
}
- notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), ActionType.ALARM_ACK, user);
+ notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
+ alarmInfo.getCustomerId(), ActionType.ALARM_ACK, user);
} else {
throw new ThingsboardException("Alarm was already acknowledged!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
- return result.getAlarm();
+ return alarmInfo;
}
@Override
@@ -130,6 +137,7 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
if (!result.isSuccessful()) {
throw new ThingsboardException(ThingsboardErrorCode.ITEM_NOT_FOUND);
}
+ AlarmInfo alarmInfo = result.getAlarm();
if (result.isCleared()) {
AlarmComment alarmComment = AlarmComment.builder()
.alarmId(alarm.getId())
@@ -144,11 +152,12 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
} catch (ThingsboardException e) {
log.error("Failed to save alarm comment", e);
}
- notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), ActionType.ALARM_CLEAR, user);
+ notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
+ alarmInfo.getCustomerId(), ActionType.ALARM_CLEAR, user);
} else {
throw new ThingsboardException("Alarm was already cleared!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
- return result.getAlarm();
+ return alarmInfo;
}
@Override
@@ -175,7 +184,8 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
} catch (ThingsboardException e) {
log.error("Failed to save alarm comment", e);
}
- notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), ActionType.ALARM_ASSIGNED, user);
+ notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
+ alarmInfo.getCustomerId(), ActionType.ALARM_ASSIGNED, user);
} else {
throw new ThingsboardException("Alarm was already assigned to this user!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
@@ -203,19 +213,53 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
} catch (ThingsboardException e) {
log.error("Failed to save alarm comment", e);
}
- notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), ActionType.ALARM_UNASSIGNED, user);
+ notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
+ alarmInfo.getCustomerId(), ActionType.ALARM_UNASSIGNED, user);
} else {
throw new ThingsboardException("Alarm was already unassigned!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
return alarmInfo;
}
+ @Override
+ public void unassignUserAlarms(TenantId tenantId, User user, long unassignTs) {
+ AlarmQueryV2 alarmQuery = AlarmQueryV2.builder().assigneeId(user.getId()).pageLink(new TimePageLink(Integer.MAX_VALUE)).build();
+ try {
+ List alarms = alarmService.findAlarmsV2(tenantId, alarmQuery).get(30, TimeUnit.SECONDS).getData();
+ for (AlarmInfo alarm : alarms) {
+ AlarmApiCallResult result = alarmSubscriptionService.unassignAlarm(tenantId, alarm.getId(), getOrDefault(unassignTs));
+ if (!result.isSuccessful()) {
+ continue;
+ }
+ if (result.isModified()) {
+ AlarmComment alarmComment = AlarmComment.builder()
+ .alarmId(alarm.getId())
+ .type(AlarmCommentType.SYSTEM)
+ .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was unassigned because user %s - was deleted",
+ (user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName()))
+ .put("userId", user.getId().toString())
+ .put("subtype", "ASSIGN"))
+ .build();
+ try {
+ alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
+ } catch (ThingsboardException e) {
+ log.error("Failed to save alarm comment", e);
+ }
+ notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), result.getAlarm(),
+ alarm.getCustomerId(), ActionType.ALARM_UNASSIGNED, user);
+ }
+ }
+
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@Override
public Boolean delete(Alarm alarm, User user) {
TenantId tenantId = alarm.getTenantId();
- List relatedEdgeIds = edgeService.findAllRelatedEdgeIds(tenantId, alarm.getOriginator());
- notificationEntityService.notifyDeleteAlarm(tenantId, alarm, alarm.getOriginator(), alarm.getCustomerId(),
- relatedEdgeIds, user, JacksonUtil.toString(alarm));
+ notificationEntityService.logEntityAction(tenantId, alarm.getOriginator(), alarm, alarm.getCustomerId(),
+ ActionType.DELETED, user);
return alarmSubscriptionService.deleteAlarm(tenantId, alarm.getId());
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java
index a2ae9c8cc7..24af185539 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java
@@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.exception.ThingsboardException;
+import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
public interface TbAlarmService {
@@ -37,5 +38,7 @@ public interface TbAlarmService {
AlarmInfo unassign(Alarm alarm, long unassignTs, User user) throws ThingsboardException;
+ void unassignUserAlarms(TenantId tenantId, User user, long unassignTs);
+
Boolean delete(Alarm alarm, User user);
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java
index ab57ecd050..6510ecfb7f 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java
@@ -36,8 +36,6 @@ import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
import org.thingsboard.server.service.profile.TbAssetProfileCache;
-import java.util.List;
-
import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE;
@Service
@@ -62,8 +60,8 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
}
Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
autoCommit(user, savedAsset.getId());
- notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedAsset.getId(), savedAsset,
- asset.getCustomerId(), actionType, user);
+ notificationEntityService.logEntityAction(tenantId, savedAsset.getId(), savedAsset, asset.getCustomerId(),
+ actionType, user);
tbClusterService.broadcastEntityStateChangeEvent(tenantId, savedAsset.getId(),
asset.getId() == null ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
return savedAsset;
@@ -75,17 +73,16 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
@Override
public ListenableFuture delete(Asset asset, User user) {
+ ActionType actionType = ActionType.DELETED;
TenantId tenantId = asset.getTenantId();
AssetId assetId = asset.getId();
try {
- List relatedEdgeIds = edgeService.findAllRelatedEdgeIds(tenantId, assetId);
assetService.deleteAsset(tenantId, assetId);
- notificationEntityService.notifyDeleteEntity(tenantId, assetId, asset, asset.getCustomerId(),
- ActionType.DELETED, relatedEdgeIds, user, assetId.toString());
+ notificationEntityService.logEntityAction(tenantId, assetId, asset, asset.getCustomerId(), actionType, user, assetId.toString());
tbClusterService.broadcastEntityStateChangeEvent(tenantId, assetId, ComponentLifecycleEvent.DELETED);
return removeAlarmsByEntityId(tenantId, assetId);
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET), ActionType.DELETED, user, e,
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET), actionType, user, e,
assetId.toString());
throw e;
}
@@ -97,8 +94,8 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
CustomerId customerId = customer.getId();
try {
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, customerId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset,
- actionType, user, assetId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, assetId, savedAsset, customerId, actionType, user,
+ assetId.toString(), customerId.toString(), customer.getName());
return savedAsset;
} catch (Exception e) {
@@ -114,8 +111,8 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
try {
Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(tenantId, assetId));
CustomerId customerId = customer.getId();
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset,
- actionType, user, assetId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, assetId, savedAsset, customerId, actionType, user,
+ assetId.toString(), customerId.toString(), customer.getName());
return savedAsset;
} catch (Exception e) {
@@ -130,8 +127,9 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
try {
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId);
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, publicCustomer.getId()));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, savedAsset.getCustomerId(), savedAsset,
- actionType, user, assetId.toString(), publicCustomer.getId().toString(), publicCustomer.getName());
+ CustomerId customerId = publicCustomer.getId();
+ notificationEntityService.logEntityAction(tenantId, assetId, savedAsset, customerId, actionType, user,
+ assetId.toString(), customerId.toString(), publicCustomer.getName());
return savedAsset;
} catch (Exception e) {
@@ -146,9 +144,8 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
EdgeId edgeId = edge.getId();
try {
Asset savedAsset = checkNotNull(assetService.assignAssetToEdge(tenantId, assetId, edgeId));
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, savedAsset.getCustomerId(),
- edgeId, savedAsset, actionType, user, assetId.toString(), edgeId.toString(), edge.getName());
-
+ notificationEntityService.logEntityAction(tenantId, assetId, savedAsset, savedAsset.getCustomerId(),
+ actionType, user, assetId.toString(), edgeId.toString(), edge.getName());
return savedAsset;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET), actionType,
@@ -164,9 +161,8 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb
EdgeId edgeId = edge.getId();
try {
Asset savedAsset = checkNotNull(assetService.unassignAssetFromEdge(tenantId, assetId, edgeId));
-
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, asset.getCustomerId(),
- edgeId, asset, actionType, user, assetId.toString(), edgeId.toString(), edge.getName());
+ notificationEntityService.logEntityAction(tenantId, assetId, asset, asset.getCustomerId(),
+ actionType, user, assetId.toString(), edgeId.toString(), edge.getName());
return savedAsset;
} catch (Exception e) {
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/profile/DefaultTbAssetProfileService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/profile/DefaultTbAssetProfileService.java
index b662994451..00b181a52a 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/profile/DefaultTbAssetProfileService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/profile/DefaultTbAssetProfileService.java
@@ -59,8 +59,8 @@ public class DefaultTbAssetProfileService extends AbstractTbEntityService implem
tbClusterService.broadcastEntityStateChangeEvent(tenantId, savedAssetProfile.getId(),
actionType.equals(ActionType.ADDED) ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedAssetProfile.getId(),
- savedAssetProfile, user, actionType, true, null);
+ notificationEntityService.logEntityAction(tenantId, savedAssetProfile.getId(), savedAssetProfile,
+ null, actionType, user);
return savedAssetProfile;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET_PROFILE), assetProfile, actionType, user, e);
@@ -70,16 +70,17 @@ public class DefaultTbAssetProfileService extends AbstractTbEntityService implem
@Override
public void delete(AssetProfile assetProfile, User user) {
+ ActionType actionType = ActionType.DELETED;
AssetProfileId assetProfileId = assetProfile.getId();
TenantId tenantId = assetProfile.getTenantId();
try {
assetProfileService.deleteAssetProfile(tenantId, assetProfileId);
tbClusterService.broadcastEntityStateChangeEvent(tenantId, assetProfileId, ComponentLifecycleEvent.DELETED);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, assetProfileId, assetProfile,
- user, ActionType.DELETED, true, null, assetProfileId.toString());
+ notificationEntityService.logEntityAction(tenantId, assetProfileId, assetProfile, null,
+ actionType, user, assetProfileId.toString());
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET_PROFILE), ActionType.DELETED,
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ASSET_PROFILE), actionType,
user, e, assetProfileId.toString());
throw e;
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/customer/DefaultTbCustomerService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/customer/DefaultTbCustomerService.java
index b71cfd222e..96611bb3b5 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/customer/DefaultTbCustomerService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/customer/DefaultTbCustomerService.java
@@ -22,13 +22,10 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.CustomerId;
-import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
-import java.util.List;
-
@Service
@AllArgsConstructor
public class DefaultTbCustomerService extends AbstractTbEntityService implements TbCustomerService {
@@ -40,7 +37,7 @@ public class DefaultTbCustomerService extends AbstractTbEntityService implements
try {
Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer));
autoCommit(user, savedCustomer.getId());
- notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedCustomer.getId(), savedCustomer, null, actionType, user);
+ notificationEntityService.logEntityAction(tenantId, savedCustomer.getId(), savedCustomer, null, actionType, user);
return savedCustomer;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.CUSTOMER), customer, actionType, user, e);
@@ -50,17 +47,17 @@ public class DefaultTbCustomerService extends AbstractTbEntityService implements
@Override
public void delete(Customer customer, User user) {
+ ActionType actionType = ActionType.DELETED;
TenantId tenantId = customer.getTenantId();
CustomerId customerId = customer.getId();
try {
- List relatedEdgeIds = edgeService.findAllRelatedEdgeIds(tenantId, customer.getId());
customerService.deleteCustomer(tenantId, customerId);
- notificationEntityService.notifyDeleteEntity(tenantId, customer.getId(), customer, customerId,
- ActionType.DELETED, relatedEdgeIds, user, customerId.toString());
+ notificationEntityService.logEntityAction(tenantId, customer.getId(), customer, customerId, actionType,
+ user, customerId.toString());
tbClusterService.broadcastEntityStateChangeEvent(tenantId, customer.getId(), ComponentLifecycleEvent.DELETED);
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.CUSTOMER), ActionType.DELETED,
- user, e, customerId.toString());
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.CUSTOMER), actionType, user,
+ e, customerId.toString());
throw e;
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/dashboard/DefaultTbDashboardService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/dashboard/DefaultTbDashboardService.java
index fa5b967bd0..70918486a3 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/dashboard/DefaultTbDashboardService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/dashboard/DefaultTbDashboardService.java
@@ -34,7 +34,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
@Service
@@ -51,8 +50,8 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
try {
Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard));
autoCommit(user, savedDashboard.getId());
- notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedDashboard.getId(), savedDashboard,
- null, actionType, user);
+ notificationEntityService.logEntityAction(tenantId, savedDashboard.getId(), savedDashboard, null,
+ actionType, user);
return savedDashboard;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DASHBOARD), dashboard, actionType, user, e);
@@ -62,15 +61,14 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
@Override
public void delete(Dashboard dashboard, User user) {
+ ActionType actionType = ActionType.DELETED;
DashboardId dashboardId = dashboard.getId();
TenantId tenantId = dashboard.getTenantId();
try {
- List relatedEdgeIds = edgeService.findAllRelatedEdgeIds(tenantId, dashboardId);
dashboardService.deleteDashboard(tenantId, dashboardId);
- notificationEntityService.notifyDeleteEntity(tenantId, dashboardId, dashboard, null,
- ActionType.DELETED, relatedEdgeIds, user, dashboardId.toString());
+ notificationEntityService.logEntityAction(tenantId, dashboardId, dashboard, null, actionType, user, dashboardId.toString());
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DASHBOARD), ActionType.DELETED, user, e, dashboardId.toString());
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DASHBOARD), actionType, user, e, dashboardId.toString());
throw e;
}
}
@@ -83,8 +81,8 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
DashboardId dashboardId = dashboard.getId();
try {
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(tenantId, dashboardId, customerId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, dashboardId, customerId, savedDashboard,
- actionType, user, dashboardId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, dashboardId, savedDashboard, customerId, actionType,
+ user, dashboardId.toString(), customerId.toString(), customer.getName());
return savedDashboard;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DASHBOARD), actionType,
@@ -101,9 +99,8 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
try {
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId);
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(tenantId, dashboardId, publicCustomer.getId()));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, dashboardId, publicCustomer.getId(), savedDashboard,
- actionType, user, dashboardId.toString(),
- publicCustomer.getId().toString(), publicCustomer.getName());
+ notificationEntityService.logEntityAction(tenantId, dashboardId, savedDashboard, publicCustomer.getId(),
+ actionType, user, dashboardId.toString(), publicCustomer.getId().toString(), publicCustomer.getName());
return savedDashboard;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DASHBOARD), actionType, user, e, dashboardId.toString());
@@ -119,9 +116,8 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
try {
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId);
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(tenantId, dashboardId, publicCustomer.getId()));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, dashboardId, publicCustomer.getId(), dashboard,
- actionType, user, dashboardId.toString(),
- publicCustomer.getId().toString(), publicCustomer.getName());
+ notificationEntityService.logEntityAction(tenantId, dashboardId, dashboard, publicCustomer.getId(), actionType,
+ user, dashboardId.toString(), publicCustomer.getId().toString(), publicCustomer.getName());
return savedDashboard;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DASHBOARD), actionType, user, e, dashboardId.toString());
@@ -159,15 +155,15 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
for (CustomerId customerId : addedCustomerIds) {
savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(tenantId, dashboardId, customerId));
ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, savedDashboard.getId(), customerId, savedDashboard,
+ notificationEntityService.logEntityAction(tenantId, savedDashboard.getId(), savedDashboard, customerId,
actionType, user, dashboardId.toString(), customerId.toString(), customerInfo.getTitle());
}
actionType = ActionType.UNASSIGNED_FROM_CUSTOMER;
for (CustomerId customerId : removedCustomerIds) {
ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(tenantId, dashboardId, customerId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, savedDashboard.getId(), customerId, savedDashboard,
- ActionType.UNASSIGNED_FROM_CUSTOMER, user, dashboardId.toString(), customerId.toString(), customerInfo.getTitle());
+ notificationEntityService.logEntityAction(tenantId, savedDashboard.getId(), savedDashboard, customerId,
+ actionType, user, dashboardId.toString(), customerId.toString(), customerInfo.getTitle());
}
return savedDashboard;
}
@@ -196,7 +192,7 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
for (CustomerId customerId : addedCustomerIds) {
savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(tenantId, dashboardId, customerId));
ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId);
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, dashboardId, customerId, savedDashboard,
+ notificationEntityService.logEntityAction(tenantId, dashboardId, savedDashboard, customerId,
actionType, user, dashboardId.toString(), customerId.toString(), customerInfo.getTitle());
}
return savedDashboard;
@@ -226,7 +222,7 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
for (CustomerId customerId : removedCustomerIds) {
ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId);
savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(tenantId, dashboardId, customerId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, dashboardId, customerId, savedDashboard,
+ notificationEntityService.logEntityAction(tenantId, dashboardId, savedDashboard, customerId,
actionType, user, dashboardId.toString(), customerId.toString(), customerInfo.getTitle());
}
return savedDashboard;
@@ -243,9 +239,8 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
EdgeId edgeId = edge.getId();
try {
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToEdge(tenantId, dashboardId, edgeId));
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, dashboardId, null,
- edgeId, savedDashboard, actionType, user, dashboardId.toString(),
- edgeId.toString(), edge.getName());
+ notificationEntityService.logEntityAction(tenantId, dashboardId, savedDashboard, null, actionType,
+ user, dashboardId.toString(), edgeId.toString(), edge.getName());
return savedDashboard;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DEVICE),
@@ -262,10 +257,8 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
EdgeId edgeId = edge.getId();
try {
Dashboard savedDevice = checkNotNull(dashboardService.unassignDashboardFromEdge(tenantId, dashboardId, edgeId));
-
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, dashboardId, null,
- edgeId, dashboard, actionType, user, dashboardId.toString(),
- edgeId.toString(), edge.getName());
+ notificationEntityService.logEntityAction(tenantId, dashboardId, dashboard, null, actionType,
+ user, dashboardId.toString(), edgeId.toString(), edge.getName());
return savedDevice;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DASHBOARD), actionType, user, e,
@@ -281,7 +274,7 @@ public class DefaultTbDashboardService extends AbstractTbEntityService implement
DashboardId dashboardId = dashboard.getId();
try {
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(tenantId, dashboardId, customer.getId()));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, dashboardId, customer.getId(), savedDashboard,
+ notificationEntityService.logEntityAction(tenantId, dashboardId, savedDashboard, customer.getId(),
actionType, user, dashboardId.toString(), customer.getId().toString(), customer.getName());
return savedDashboard;
} catch (Exception e) {
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java
index 2ab8de9438..544a199498 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java
@@ -44,8 +44,6 @@ import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
-import java.util.List;
-
@AllArgsConstructor
@TbCoreComponent
@Service
@@ -97,10 +95,9 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T
TenantId tenantId = device.getTenantId();
DeviceId deviceId = device.getId();
try {
- List relatedEdgeIds = edgeService.findAllRelatedEdgeIds(tenantId, deviceId);
deviceService.deleteDevice(tenantId, deviceId);
notificationEntityService.notifyDeleteDevice(tenantId, deviceId, device.getCustomerId(), device,
- relatedEdgeIds, user, deviceId.toString());
+ user, deviceId.toString());
return removeAlarmsByEntityId(tenantId, deviceId);
} catch (Exception e) {
@@ -116,8 +113,8 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T
CustomerId customerId = customer.getId();
try {
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(tenantId, deviceId, customerId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice,
- actionType, user, deviceId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, deviceId, savedDevice, customerId, actionType, user,
+ deviceId.toString(), customerId.toString(), customer.getName());
return savedDevice;
} catch (Exception e) {
@@ -136,8 +133,8 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(tenantId, deviceId));
CustomerId customerId = customer.getId();
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice,
- actionType, user, deviceId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, deviceId, savedDevice, customerId, actionType, user,
+ deviceId.toString(), customerId.toString(), customer.getName());
return savedDevice;
} catch (Exception e) {
@@ -154,9 +151,8 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T
try {
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(tenantId, deviceId, publicCustomer.getId()));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, savedDevice.getCustomerId(), savedDevice,
- actionType, user, deviceId.toString(),
- publicCustomer.getId().toString(), publicCustomer.getName());
+ notificationEntityService.logEntityAction(tenantId, deviceId, savedDevice, savedDevice.getCustomerId(),
+ actionType, user, deviceId.toString(), publicCustomer.getId().toString(), publicCustomer.getName());
return savedDevice;
} catch (Exception e) {
@@ -252,30 +248,32 @@ public class DefaultTbDeviceService extends AbstractTbEntityService implements T
EdgeId edgeId = edge.getId();
try {
Device savedDevice = checkNotNull(deviceService.assignDeviceToEdge(tenantId, deviceId, edgeId));
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, savedDevice.getCustomerId(),
- edgeId, savedDevice, actionType, user, deviceId.toString(), edgeId.toString(), edge.getName());
+ notificationEntityService.logEntityAction(tenantId, deviceId, savedDevice, savedDevice.getCustomerId(),
+ actionType, user, deviceId.toString(), edgeId.toString(), edge.getName());
+
return savedDevice;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DEVICE),
- ActionType.ASSIGNED_TO_EDGE, user, e, deviceId.toString(), edgeId.toString());
+ actionType, user, e, deviceId.toString(), edgeId.toString());
throw e;
}
}
@Override
public Device unassignDeviceFromEdge(Device device, Edge edge, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE;
TenantId tenantId = device.getTenantId();
DeviceId deviceId = device.getId();
EdgeId edgeId = edge.getId();
try {
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromEdge(tenantId, deviceId, edgeId));
+ notificationEntityService.logEntityAction(tenantId, deviceId, savedDevice, savedDevice.getCustomerId(),
+ actionType, user, deviceId.toString(), edgeId.toString(), edge.getName());
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, device.getCustomerId(),
- edgeId, device, ActionType.UNASSIGNED_FROM_EDGE, user, deviceId.toString(), edgeId.toString(), edge.getName());
return savedDevice;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DEVICE),
- ActionType.UNASSIGNED_FROM_EDGE, user, e, deviceId.toString(), edgeId.toString());
+ actionType, user, e, deviceId.toString(), edgeId.toString());
throw e;
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/device/profile/DefaultTbDeviceProfileService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/device/profile/DefaultTbDeviceProfileService.java
index faa6a69983..70ee722493 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/device/profile/DefaultTbDeviceProfileService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/device/profile/DefaultTbDeviceProfileService.java
@@ -67,8 +67,8 @@ public class DefaultTbDeviceProfileService extends AbstractTbEntityService imple
otaPackageStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedDeviceProfile.getId(),
- savedDeviceProfile, user, actionType, true, null);
+ notificationEntityService.logEntityAction(tenantId, savedDeviceProfile.getId(), savedDeviceProfile,
+ null, actionType, user);
return savedDeviceProfile;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DEVICE_PROFILE), deviceProfile, actionType, user, e);
@@ -78,6 +78,7 @@ public class DefaultTbDeviceProfileService extends AbstractTbEntityService imple
@Override
public void delete(DeviceProfile deviceProfile, User user) {
+ ActionType actionType = ActionType.DELETED;
DeviceProfileId deviceProfileId = deviceProfile.getId();
TenantId tenantId = deviceProfile.getTenantId();
try {
@@ -85,10 +86,10 @@ public class DefaultTbDeviceProfileService extends AbstractTbEntityService imple
tbClusterService.onDeviceProfileDelete(deviceProfile, null);
tbClusterService.broadcastEntityStateChangeEvent(tenantId, deviceProfileId, ComponentLifecycleEvent.DELETED);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, deviceProfileId, deviceProfile,
- user, ActionType.DELETED, true, null, deviceProfileId.toString());
+ notificationEntityService.logEntityAction(tenantId, deviceProfileId, deviceProfile, null,
+ actionType, user, deviceProfileId.toString());
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DEVICE_PROFILE), ActionType.DELETED,
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.DEVICE_PROFILE), actionType,
user, e, deviceProfileId.toString());
throw e;
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java
index c51ae3352e..adc20c21d0 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java
@@ -89,8 +89,8 @@ public class DefaultTbEdgeService extends AbstractTbEntityService implements TbE
CustomerId customerId = customer.getId();
try {
Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(tenantId, edgeId, customerId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, edgeId, customerId, savedEdge,
- actionType, user, edgeId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, edgeId, savedEdge, customerId, actionType,
+ user, edgeId.toString(), customerId.toString(), customer.getName());
return savedEdge;
} catch (Exception e) {
@@ -108,8 +108,8 @@ public class DefaultTbEdgeService extends AbstractTbEntityService implements TbE
CustomerId customerId = customer.getId();
try {
Edge savedEdge = checkNotNull(edgeService.unassignEdgeFromCustomer(tenantId, edgeId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, edgeId, customerId, savedEdge,
- actionType, user, edgeId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, edgeId, savedEdge, customerId, actionType,
+ user, edgeId.toString(), customerId.toString(), customer.getName());
return savedEdge;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.EDGE),
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/DefaultTbEntityRelationService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/DefaultTbEntityRelationService.java
index b978b730fd..904d98653e 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/DefaultTbEntityRelationService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/DefaultTbEntityRelationService.java
@@ -40,41 +40,38 @@ public class DefaultTbEntityRelationService extends AbstractTbEntityService impl
@Override
public void save(TenantId tenantId, CustomerId customerId, EntityRelation relation, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.RELATION_ADD_OR_UPDATE;
try {
relationService.saveRelation(tenantId, relation);
- notificationEntityService.notifyRelation(tenantId, customerId,
- relation, user, ActionType.RELATION_ADD_OR_UPDATE, relation);
+ notificationEntityService.logEntityRelationAction(tenantId, customerId,
+ relation, user, actionType, null, relation);
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, relation.getFrom(), null, customerId,
- ActionType.RELATION_ADD_OR_UPDATE, user, e, relation);
- notificationEntityService.logEntityAction(tenantId, relation.getTo(), null, customerId,
- ActionType.RELATION_ADD_OR_UPDATE, user, e, relation);
+ notificationEntityService.logEntityRelationAction(tenantId, customerId,
+ relation, user, actionType, e, relation);
throw e;
}
}
@Override
public void delete(TenantId tenantId, CustomerId customerId, EntityRelation relation, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.RELATION_DELETED;
try {
boolean found = relationService.deleteRelation(tenantId, relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup());
if (!found) {
throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND);
}
- notificationEntityService.notifyRelation(tenantId, customerId,
- relation, user, ActionType.RELATION_DELETED, relation);
+ notificationEntityService.logEntityRelationAction(tenantId, customerId, relation, user, actionType, null, relation);
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, relation.getFrom(), null, customerId,
- ActionType.RELATION_DELETED, user, e, relation);
- notificationEntityService.logEntityAction(tenantId, relation.getTo(), null, customerId,
- ActionType.RELATION_DELETED, user, e, relation);
+ notificationEntityService.logEntityRelationAction(tenantId, customerId,
+ relation, user, actionType, e, relation);
throw e;
}
}
@Override
- public void deleteRelations(TenantId tenantId, CustomerId customerId, EntityId entityId, User user) throws ThingsboardException {
+ public void deleteCommonRelations(TenantId tenantId, CustomerId customerId, EntityId entityId, User user) throws ThingsboardException {
try {
- relationService.deleteEntityRelations(tenantId, entityId);
+ relationService.deleteEntityCommonRelations(tenantId, entityId);
notificationEntityService.logEntityAction(tenantId, entityId, null, customerId, ActionType.RELATIONS_DELETED, user);
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, entityId, null, customerId,
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/TbEntityRelationService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/TbEntityRelationService.java
index 2caee86d0c..8bf5018c95 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/TbEntityRelationService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/entity/relation/TbEntityRelationService.java
@@ -28,6 +28,6 @@ public interface TbEntityRelationService {
void delete(TenantId tenantId, CustomerId customerId, EntityRelation entity, User user) throws ThingsboardException;
- void deleteRelations(TenantId tenantId, CustomerId customerId, EntityId entityId, User user) throws ThingsboardException;
+ void deleteCommonRelations(TenantId tenantId, CustomerId customerId, EntityId entityId, User user) throws ThingsboardException;
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java
index 48e6c4b634..f587e19ef2 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java
@@ -81,7 +81,7 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView));
this.updateEntityViewAttributes(tenantId, savedEntityView, existingEntityView, user);
autoCommit(user, savedEntityView.getId());
- notificationEntityService.notifyCreateOrUpdateEntity(savedEntityView.getTenantId(), savedEntityView.getId(), savedEntityView,
+ notificationEntityService.logEntityAction(savedEntityView.getTenantId(), savedEntityView.getId(), savedEntityView,
null, actionType, user);
localCache.computeIfAbsent(savedEntityView.getTenantId(), (k) -> new ConcurrentReferenceHashMap<>()).clear();
tbClusterService.broadcastEntityStateChangeEvent(savedEntityView.getTenantId(), savedEntityView.getId(),
@@ -129,10 +129,9 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
TenantId tenantId = entityView.getTenantId();
EntityViewId entityViewId = entityView.getId();
try {
- List relatedEdgeIds = edgeService.findAllRelatedEdgeIds(tenantId, entityViewId);
entityViewService.deleteEntityView(tenantId, entityViewId);
- notificationEntityService.notifyDeleteEntity(tenantId, entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED,
- relatedEdgeIds, user, entityViewId.toString());
+ notificationEntityService.logEntityAction(tenantId, entityViewId, entityView, entityView.getCustomerId(),
+ ActionType.DELETED, user, entityViewId.toString());
localCache.computeIfAbsent(tenantId, (k) -> new ConcurrentReferenceHashMap<>()).clear();
tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityViewId, ComponentLifecycleEvent.DELETED);
@@ -145,15 +144,31 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
@Override
public EntityView assignEntityViewToCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER;
CustomerId customerId = customer.getId();
try {
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(tenantId, entityViewId, customerId));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, entityViewId, customerId, savedEntityView,
- ActionType.ASSIGNED_TO_CUSTOMER, user, entityViewId.toString(), customerId.toString(), customer.getName());
+ notificationEntityService.logEntityAction(tenantId, entityViewId, savedEntityView, savedEntityView.getCustomerId(),
+ actionType, user, entityViewId.toString(), customerId.toString(), customer.getName());
+ return savedEntityView;
+ } catch (Exception e) {
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ENTITY_VIEW),
+ actionType, user, e, entityViewId.toString(), customerId.toString());
+ throw e;
+ }
+ }
+
+ @Override
+ public EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER;
+ try {
+ EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(tenantId, entityViewId));
+ notificationEntityService.logEntityAction(tenantId, entityViewId, savedEntityView, customer.getId(),
+ actionType, user, savedEntityView.getId().toString(), customer.getId().toString(), customer.getName());
return savedEntityView;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ENTITY_VIEW),
- ActionType.ASSIGNED_TO_CUSTOMER, user, e, entityViewId.toString(), customerId.toString());
+ actionType, user, e, entityViewId.toString());
throw e;
}
}
@@ -165,9 +180,8 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
try {
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(tenantId,
entityViewId, publicCustomer.getId()));
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, entityViewId, savedEntityView.getCustomerId(), savedEntityView,
- actionType, user, savedEntityView.getId().toString(),
- publicCustomer.getId().toString(), publicCustomer.getName());
+ notificationEntityService.logEntityAction(tenantId, entityViewId, savedEntityView, savedEntityView.getCustomerId(),
+ actionType, user, savedEntityView.getId().toString(), publicCustomer.getId().toString(), publicCustomer.getName());
return savedEntityView;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ENTITY_VIEW),
@@ -178,16 +192,16 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
@Override
public EntityView assignEntityViewToEdge(TenantId tenantId, CustomerId customerId, EntityViewId entityViewId, Edge edge, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.ASSIGNED_TO_EDGE;
EdgeId edgeId = edge.getId();
try {
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToEdge(tenantId, entityViewId, edgeId));
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, entityViewId, customerId,
- edgeId, savedEntityView, ActionType.ASSIGNED_TO_EDGE, user, savedEntityView.getEntityId().toString(),
- edgeId.toString(), edge.getName());
+ notificationEntityService.logEntityAction(tenantId, entityViewId, savedEntityView, customerId, actionType,
+ user, savedEntityView.getEntityId().toString(), edgeId.toString(), edge.getName());
return savedEntityView;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ENTITY_VIEW),
- ActionType.ASSIGNED_TO_EDGE, user, e, entityViewId.toString(), edgeId.toString());
+ actionType, user, e, entityViewId.toString(), edgeId.toString());
throw e;
}
}
@@ -195,34 +209,17 @@ public class DefaultTbEntityViewService extends AbstractTbEntityService implemen
@Override
public EntityView unassignEntityViewFromEdge(TenantId tenantId, CustomerId customerId, EntityView entityView,
Edge edge, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE;
EntityViewId entityViewId = entityView.getId();
EdgeId edgeId = edge.getId();
try {
EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromEdge(tenantId, entityViewId, edgeId));
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, entityViewId, customerId,
- edgeId, entityView, ActionType.UNASSIGNED_FROM_EDGE, user, entityViewId.toString(),
- edgeId.toString(), edge.getName());
+ notificationEntityService.logEntityAction(tenantId, entityViewId, savedEntityView, customerId, actionType,
+ user, entityViewId.toString(), edgeId.toString(), edge.getName());
return savedEntityView;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ENTITY_VIEW),
- ActionType.UNASSIGNED_FROM_EDGE, user, e, entityViewId.toString(), edgeId.toString());
- throw e;
- }
- }
-
- @Override
- public EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer, User user) throws ThingsboardException {
- ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER;
- try {
- EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(tenantId, entityViewId));
-
- notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, entityViewId, customer.getId(), savedEntityView,
- actionType, user, savedEntityView.getId().toString(), customer.getId().toString(), customer.getName());
-
- return savedEntityView;
- } catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ENTITY_VIEW),
- actionType, user, e, entityViewId.toString());
+ actionType, user, e, entityViewId.toString(), edgeId.toString());
throw e;
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/ota/DefaultTbOtaPackageService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/ota/DefaultTbOtaPackageService.java
index 4d3c61e615..3cc444caf5 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/ota/DefaultTbOtaPackageService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/ota/DefaultTbOtaPackageService.java
@@ -50,9 +50,8 @@ public class DefaultTbOtaPackageService extends AbstractTbEntityService implemen
try {
OtaPackageInfo savedOtaPackageInfo = otaPackageService.saveOtaPackageInfo(new OtaPackageInfo(saveOtaPackageInfoRequest), saveOtaPackageInfoRequest.isUsesUrl());
- boolean sendMsgToEdge = savedOtaPackageInfo.hasUrl() || savedOtaPackageInfo.isHasData();
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedOtaPackageInfo.getId(),
- savedOtaPackageInfo, user, actionType, sendMsgToEdge, null);
+ notificationEntityService.logEntityAction(tenantId, savedOtaPackageInfo.getId(), savedOtaPackageInfo,
+ null, actionType, user);
return savedOtaPackageInfo;
} catch (Exception e) {
@@ -65,6 +64,7 @@ public class DefaultTbOtaPackageService extends AbstractTbEntityService implemen
@Override
public OtaPackageInfo saveOtaPackageData(OtaPackageInfo otaPackageInfo, String checksum, ChecksumAlgorithm checksumAlgorithm,
byte[] data, String filename, String contentType, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.UPDATED;
TenantId tenantId = otaPackageInfo.getTenantId();
OtaPackageId otaPackageId = otaPackageInfo.getId();
try {
@@ -87,27 +87,26 @@ public class DefaultTbOtaPackageService extends AbstractTbEntityService implemen
otaPackage.setData(ByteBuffer.wrap(data));
otaPackage.setDataSize((long) data.length);
OtaPackageInfo savedOtaPackage = otaPackageService.saveOtaPackage(otaPackage);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedOtaPackage.getId(),
- savedOtaPackage, user, ActionType.UPDATED, true, null);
+ notificationEntityService.logEntityAction(tenantId, savedOtaPackage.getId(), savedOtaPackage, null, actionType, user);
return savedOtaPackage;
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.OTA_PACKAGE), ActionType.UPDATED,
- user, e, otaPackageId.toString());
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.OTA_PACKAGE), actionType, user, e, otaPackageId.toString());
throw e;
}
}
@Override
public void delete(OtaPackageInfo otaPackageInfo, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.DELETED;
TenantId tenantId = otaPackageInfo.getTenantId();
OtaPackageId otaPackageId = otaPackageInfo.getId();
try {
otaPackageService.deleteOtaPackage(tenantId, otaPackageId);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, otaPackageId, otaPackageInfo,
- user, ActionType.DELETED, true, null, otaPackageInfo.getId().toString());
+ notificationEntityService.logEntityAction(tenantId, otaPackageId, otaPackageInfo, null,
+ actionType, user, otaPackageInfo.getId().toString());
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.OTA_PACKAGE),
- ActionType.DELETED, user, e, otaPackageId.toString());
+ actionType, user, e, otaPackageId.toString());
throw e;
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/queue/DefaultTbQueueService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/queue/DefaultTbQueueService.java
index 63e11aeb7a..40d294d238 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/queue/DefaultTbQueueService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/queue/DefaultTbQueueService.java
@@ -20,7 +20,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.TenantProfile;
-import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.id.QueueId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.queue.Queue;
@@ -71,8 +70,6 @@ public class DefaultTbQueueService extends AbstractTbEntityService implements Tb
onQueueUpdated(savedQueue, oldQueue);
}
- notificationEntityService.notifySendMsgToEdgeService(queue.getTenantId(), savedQueue.getId(), create ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED);
-
return savedQueue;
}
@@ -145,8 +142,6 @@ public class DefaultTbQueueService extends AbstractTbEntityService implements Tb
}
}
}, DELETE_DELAY, TimeUnit.SECONDS);
-
- notificationEntityService.notifySendMsgToEdgeService(queue.getTenantId(), queue.getId(), EdgeEventActionType.DELETED);
}
@Override
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java
index c83c48cc8a..58bd40d070 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java
@@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.security.UserCredentials;
import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
+import org.thingsboard.server.service.entitiy.alarm.TbAlarmService;
import org.thingsboard.server.service.security.system.SystemSecurityService;
import javax.servlet.http.HttpServletRequest;
@@ -43,6 +44,7 @@ import static org.thingsboard.server.controller.UserController.ACTIVATE_URL_PATT
public class DefaultUserService extends AbstractTbEntityService implements TbUserService {
private final UserService userService;
+ private final TbAlarmService tbAlarmService;
private final MailService mailService;
private final SystemSecurityService systemSecurityService;
@@ -52,7 +54,7 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse
ActionType actionType = tbUser.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
try {
boolean sendEmail = tbUser.getId() == null && sendActivationMail;
- User savedUser = checkNotNull(userService.saveUser(tbUser));
+ User savedUser = checkNotNull(userService.saveUser(tenantId, tbUser));
if (sendEmail) {
UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, savedUser.getId());
String baseUrl = systemSecurityService.getBaseUrl(tenantId, customerId, request);
@@ -66,8 +68,7 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse
throw e;
}
}
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, customerId, savedUser.getId(),
- savedUser, user, actionType, true, null);
+ notificationEntityService.logEntityAction(tenantId, savedUser.getId(), savedUser, customerId, actionType, user);
return savedUser;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.USER), tbUser, actionType, user, e);
@@ -77,15 +78,16 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse
@Override
public void delete(TenantId tenantId, CustomerId customerId, User tbUser, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.DELETED;
UserId userId = tbUser.getId();
try {
+ tbAlarmService.unassignUserAlarms(tbUser.getTenantId(), tbUser, System.currentTimeMillis());
userService.deleteUser(tenantId, userId);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, customerId, userId, tbUser,
- user, ActionType.DELETED, true, null, customerId.toString());
+ notificationEntityService.logEntityAction(tenantId, userId, tbUser, customerId, actionType, user, customerId.toString());
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.USER),
- ActionType.DELETED, user, e, userId.toString());
+ actionType, user, e, userId.toString());
throw e;
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java
index 7cc150b746..efc20cd422 100644
--- a/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java
+++ b/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java
@@ -40,8 +40,8 @@ public class DefaultWidgetsBundleService extends AbstractTbEntityService impleme
try {
WidgetsBundle savedWidgetsBundle = checkNotNull(widgetsBundleService.saveWidgetsBundle(widgetsBundle));
autoCommit(user, savedWidgetsBundle.getId());
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedWidgetsBundle.getId(),
- savedWidgetsBundle, user, actionType, true, null);
+ notificationEntityService.logEntityAction(tenantId, savedWidgetsBundle.getId(), savedWidgetsBundle,
+ null, actionType, user);
return savedWidgetsBundle;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.WIDGETS_BUNDLE), widgetsBundle, actionType, user, e);
@@ -51,14 +51,13 @@ public class DefaultWidgetsBundleService extends AbstractTbEntityService impleme
@Override
public void delete(WidgetsBundle widgetsBundle, User user) {
+ ActionType actionType = ActionType.DELETED;
TenantId tenantId = widgetsBundle.getTenantId();
try {
widgetsBundleService.deleteWidgetsBundle(widgetsBundle.getTenantId(), widgetsBundle.getId());
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, widgetsBundle.getId(), widgetsBundle,
- user, ActionType.DELETED, true, null);
+ notificationEntityService.logEntityAction(tenantId, widgetsBundle.getId(), widgetsBundle, null, actionType, user);
} catch (Exception e) {
- notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.WIDGETS_BUNDLE),
- ActionType.DELETED, user, e, widgetsBundle.getId());
+ notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.WIDGETS_BUNDLE), actionType, user, e, widgetsBundle.getId());
throw e;
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
index 497627f629..acadd35577 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -114,13 +114,14 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import static org.thingsboard.server.common.data.DataConstants.DEFAULT_DEVICE_TYPE;
+
@Service
@Profile("install")
@Slf4j
public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
public static final String CUSTOMER_CRED = "customer";
- public static final String DEFAULT_DEVICE_TYPE = "default";
public static final String ACTIVITY_STATE = "active";
@Autowired
@@ -524,7 +525,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
user.setEmail(email);
user.setTenantId(tenantId);
user.setCustomerId(customerId);
- user = userService.saveUser(user);
+ user = userService.saveUser(tenantId, user);
UserCredentials userCredentials = userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, user.getId());
userCredentials.setPassword(passwordEncoder.encode(password));
userCredentials.setEnabled(true);
@@ -709,4 +710,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
}
+ @Override
+ public void updateDefaultNotificationConfigs() {
+ notificationSettingsService.updateDefaultNotificationConfigs(TenantId.SYS_TENANT_ID);
+ }
+
}
diff --git a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
index 9a810aa446..36ec2b9b78 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
@@ -48,6 +48,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Optional;
+import java.util.function.Function;
import static org.thingsboard.server.utils.LwM2mObjectModelUtils.toLwm2mResource;
@@ -173,7 +174,7 @@ public class InstallScripts {
ruleChain = ruleChainService.saveRuleChain(ruleChain);
ruleChainMetaData.setRuleChainId(ruleChain.getId());
- ruleChainService.saveRuleChainMetaData(TenantId.SYS_TENANT_ID, ruleChainMetaData);
+ ruleChainService.saveRuleChainMetaData(TenantId.SYS_TENANT_ID, ruleChainMetaData, Function.identity());
return ruleChain;
}
diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
index e1a34e616b..2e2b3e96be 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
@@ -744,6 +744,22 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
} catch (Exception e) {
}
}
+ try {
+ conn.createStatement().execute("ALTER TABLE component_descriptor ADD COLUMN IF NOT EXISTS configuration_version int DEFAULT 0;");
+ } catch (Exception e) {
+ }
+ try {
+ conn.createStatement().execute("ALTER TABLE rule_node ADD COLUMN IF NOT EXISTS configuration_version int DEFAULT 0;");
+ } catch (Exception e) {
+ }
+ try {
+ conn.createStatement().execute("CREATE INDEX IF NOT EXISTS idx_rule_node_type_configuration_version ON rule_node(type, configuration_version);");
+ } catch (Exception e) {
+ }
+ try {
+ conn.createStatement().execute("CREATE INDEX IF NOT EXISTS idx_notification_recipient_id_unread ON notification(recipient_id) WHERE status <> 'READ';");
+ } catch (Exception e) {
+ }
conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3005002;");
}
diff --git a/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java
index fb6b28592c..08de12da78 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java
@@ -41,4 +41,6 @@ public interface SystemDataLoaderService {
void createDefaultNotificationConfigs();
+ void updateDefaultNotificationConfigs();
+
}
diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DataUpdateService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DataUpdateService.java
index ae573b829a..289e3b1c94 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/update/DataUpdateService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/update/DataUpdateService.java
@@ -19,4 +19,5 @@ public interface DataUpdateService {
void updateData(String fromVersion) throws Exception;
+ void upgradeRuleNodes();
}
diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java
index 13943d5698..ff53682ca7 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java
@@ -17,6 +17,7 @@ package org.thingsboard.server.service.install.update;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
@@ -26,6 +27,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.rule.engine.api.TbVersionedNode;
import org.thingsboard.rule.engine.flow.TbRuleChainInputNode;
import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration;
import org.thingsboard.rule.engine.profile.TbDeviceProfileNode;
@@ -45,7 +47,9 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
import org.thingsboard.server.common.data.kv.TsKvEntry;
+import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import org.thingsboard.server.common.data.page.PageData;
+import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.query.DynamicValue;
@@ -62,6 +66,7 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileQueueConfiguration;
+import org.thingsboard.server.common.data.util.TbPair;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.alarm.AlarmDao;
import org.thingsboard.server.dao.audit.AuditLogDao;
@@ -77,15 +82,18 @@ import org.thingsboard.server.dao.sql.device.DeviceProfileRepository;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.timeseries.TimeseriesService;
+import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.install.InstallScripts;
import org.thingsboard.server.service.install.SystemDataLoaderService;
-import org.thingsboard.server.service.install.TbRuleEngineQueueConfigService;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.StringUtils.isBlank;
@@ -133,7 +141,7 @@ public class DefaultDataUpdateService implements DataUpdateService {
private QueueService queueService;
@Autowired
- private TbRuleEngineQueueConfigService queueConfig;
+ private ComponentDiscoveryService componentDiscoveryService;
@Autowired
private SystemDataLoaderService systemDataLoaderService;
@@ -195,19 +203,73 @@ public class DefaultDataUpdateService implements DataUpdateService {
} else {
log.info("Skipping audit logs migration");
}
- boolean skipEdgeEventsMigration = getEnv("TB_SKIP_EDGE_EVENTS_MIGRATION", false);
- if (!skipEdgeEventsMigration) {
- log.info("Starting edge events migration. Can be skipped with TB_SKIP_EDGE_EVENTS_MIGRATION env variable set to true");
- edgeEventDao.migrateEdgeEvents();
- } else {
- log.info("Skipping edge events migration");
- }
+ migrateEdgeEvents("Starting edge events migration. ");
+ break;
+ case "3.5.1":
+ log.info("Updating data from version 3.5.1 to 3.5.2 ...");
+ migrateEdgeEvents("Starting edge events migration - adding seq_id column. ");
break;
default:
throw new RuntimeException("Unable to update data, unsupported fromVersion: " + fromVersion);
}
}
+ private void migrateEdgeEvents(String logPrefix) {
+ boolean skipEdgeEventsMigration = getEnv("TB_SKIP_EDGE_EVENTS_MIGRATION", false);
+ if (!skipEdgeEventsMigration) {
+ log.info(logPrefix + "Can be skipped with TB_SKIP_EDGE_EVENTS_MIGRATION env variable set to true");
+ edgeEventDao.migrateEdgeEvents();
+ } else {
+ log.info("Skipping edge events migration");
+ }
+ }
+
+ @Override
+ public void upgradeRuleNodes() {
+ try {
+ log.info("Lookup rule nodes to upgrade ...");
+ var nodeClassToVersionMap = componentDiscoveryService.getVersionedNodes();
+ log.info("Found {} versioned nodes to check for upgrade!", nodeClassToVersionMap.size());
+ nodeClassToVersionMap.forEach(clazz -> {
+ var ruleNodeType = clazz.getClassName();
+ var ruleNodeTypeForLogs = clazz.getSimpleName();
+ var toVersion = clazz.getCurrentVersion();
+ log.info("Going to check for nodes with type: {} to upgrade to version: {}.", ruleNodeTypeForLogs, toVersion);
+ var ruleNodesToUpdate = new PageDataIterable<>(
+ pageLink -> ruleChainService.findAllRuleNodesByTypeAndVersionLessThan(ruleNodeType, toVersion, pageLink), 1024
+ );
+ if (Iterables.isEmpty(ruleNodesToUpdate)) {
+ log.info("There are no active nodes with type: {}, or all nodes with this type already set to latest version!", ruleNodeTypeForLogs);
+ } else {
+ for (var ruleNode : ruleNodesToUpdate) {
+ var ruleNodeId = ruleNode.getId();
+ var oldConfiguration = ruleNode.getConfiguration();
+ int fromVersion = ruleNode.getConfigurationVersion();
+ log.info("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
+ ruleNodeId, ruleNodeTypeForLogs, fromVersion, toVersion);
+ try {
+ var tbVersionedNode = (TbVersionedNode) clazz.getClazz().getDeclaredConstructor().newInstance();
+ TbPair upgradeRuleNodeConfigurationResult = tbVersionedNode.upgrade(fromVersion, oldConfiguration);
+ if (upgradeRuleNodeConfigurationResult.getFirst()) {
+ ruleNode.setConfiguration(upgradeRuleNodeConfigurationResult.getSecond());
+ }
+ ruleNode.setConfigurationVersion(toVersion);
+ ruleChainService.saveRuleNode(TenantId.SYS_TENANT_ID, ruleNode);
+ log.info("Successfully upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
+ ruleNodeId, ruleNodeTypeForLogs, fromVersion, toVersion);
+ } catch (Exception e) {
+ log.warn("Failed to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {} due to: ",
+ ruleNodeId, ruleNodeTypeForLogs, fromVersion, toVersion, e);
+ }
+ }
+ }
+ });
+ log.info("Finished rule nodes upgrade!");
+ } catch (Exception e) {
+ log.error("Unexpected error during rule nodes upgrade: ", e);
+ }
+ }
+
private final PaginatedUpdater deviceProfileEntityDynamicConditionsUpdater =
new PaginatedUpdater<>() {
@@ -441,8 +503,8 @@ public class DefaultDataUpdateService implements DataUpdateService {
md.getNodes().add(ruleNode);
md.setFirstNodeIndex(newIdx);
- md.addConnectionInfo(newIdx, oldIdx, "Success");
- ruleChainService.saveRuleChainMetaData(tenant.getId(), md);
+ md.addConnectionInfo(newIdx, oldIdx, TbNodeConnectionType.SUCCESS);
+ ruleChainService.saveRuleChainMetaData(tenant.getId(), md, Function.identity());
}
} catch (Exception e) {
log.error("[{}] Unable to update Tenant: {}", tenant.getId(), tenant.getName(), e);
diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java
index 1c6af41360..246fa4a0fa 100644
--- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java
+++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java
@@ -16,7 +16,6 @@
package org.thingsboard.server.service.mail;
import com.fasterxml.jackson.databind.JsonNode;
-
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java
index 7215776170..042d5cbf00 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java
@@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
+import org.thingsboard.server.common.data.limit.LimitedApi;
import org.thingsboard.server.common.data.notification.AlreadySentException;
import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
@@ -38,6 +39,7 @@ import org.thingsboard.server.common.data.notification.NotificationRequestStatus
import org.thingsboard.server.common.data.notification.NotificationStatus;
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
+import org.thingsboard.server.common.data.notification.settings.UserNotificationSettings;
import org.thingsboard.server.common.data.notification.targets.NotificationRecipient;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig;
@@ -56,7 +58,6 @@ import org.thingsboard.server.dao.notification.NotificationService;
import org.thingsboard.server.dao.notification.NotificationSettingsService;
import org.thingsboard.server.dao.notification.NotificationTargetService;
import org.thingsboard.server.dao.notification.NotificationTemplateService;
-import org.thingsboard.server.dao.util.limits.LimitedApi;
import org.thingsboard.server.dao.util.limits.RateLimitService;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
@@ -237,7 +238,17 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
private void processForRecipient(NotificationDeliveryMethod deliveryMethod, NotificationRecipient recipient, NotificationProcessingContext ctx) throws Exception {
if (ctx.getStats().contains(deliveryMethod, recipient.getId())) {
throw new AlreadySentException();
+ } else {
+ ctx.getStats().reportProcessed(deliveryMethod, recipient.getId());
}
+
+ if (recipient instanceof User) {
+ UserNotificationSettings settings = notificationSettingsService.getUserNotificationSettings(ctx.getTenantId(), ((User) recipient).getId(), false);
+ if (!settings.isEnabled(ctx.getNotificationType(), deliveryMethod)) {
+ throw new RuntimeException("User disabled " + deliveryMethod.getName() + " notifications of this type");
+ }
+ }
+
NotificationChannel notificationChannel = channels.get(deliveryMethod);
DeliveryMethodNotificationTemplate processedTemplate = ctx.getProcessedTemplate(deliveryMethod, recipient);
@@ -251,7 +262,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
Notification notification = Notification.builder()
.requestId(request.getId())
.recipientId(recipient.getId())
- .type(ctx.getNotificationTemplate().getNotificationType())
+ .type(ctx.getNotificationType())
.subject(processedTemplate.getSubject())
.text(processedTemplate.getBody())
.additionalConfig(processedTemplate.getAdditionalConfig())
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java b/application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java
index 27a9cabe43..c4d8895266 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/NotificationProcessingContext.java
@@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestStats;
+import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.notification.settings.NotificationDeliveryMethodConfig;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.targets.NotificationRecipient;
@@ -52,6 +53,8 @@ public class NotificationProcessingContext {
private final Set deliveryMethods;
@Getter
private final NotificationTemplate notificationTemplate;
+ @Getter
+ private final NotificationType notificationType;
private final Map templates;
@Getter
@@ -65,6 +68,7 @@ public class NotificationProcessingContext {
this.deliveryMethods = deliveryMethods;
this.settings = settings;
this.notificationTemplate = template;
+ this.notificationType = template.getNotificationType();
this.templates = new EnumMap<>(NotificationDeliveryMethod.class);
this.stats = new NotificationRequestStats();
init();
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java
index 71a59026a2..e9656f2ea6 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java
@@ -16,82 +16,63 @@
package org.thingsboard.server.service.notification.rule;
import lombok.RequiredArgsConstructor;
-import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.cache.Cache;
-import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.thingsboard.rule.engine.api.NotificationCenter;
-import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.limit.LimitedApi;
import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.notification.NotificationRequestConfig;
import org.thingsboard.server.common.data.notification.NotificationRequestStatus;
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
-import org.thingsboard.server.common.data.notification.settings.TriggerTypeConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTrigger;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
-import org.thingsboard.server.common.msg.notification.trigger.NotificationRuleTrigger;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.dao.notification.NotificationRequestService;
-import org.thingsboard.server.dao.util.limits.LimitedApi;
import org.thingsboard.server.dao.util.limits.RateLimitService;
import org.thingsboard.server.queue.discovery.PartitionService;
+import org.thingsboard.server.queue.notification.NotificationDeduplicationService;
import org.thingsboard.server.service.executors.NotificationExecutorService;
import org.thingsboard.server.service.notification.rule.cache.NotificationRulesCache;
import org.thingsboard.server.service.notification.rule.trigger.NotificationRuleTriggerProcessor;
-import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
-@ConfigurationProperties(prefix = "notification-system.rules")
@Slf4j
@SuppressWarnings({"rawtypes", "unchecked"})
public class DefaultNotificationRuleProcessor implements NotificationRuleProcessor {
private final NotificationRulesCache notificationRulesCache;
private final NotificationRequestService notificationRequestService;
+ private final NotificationDeduplicationService deduplicationService;
private final PartitionService partitionService;
private final RateLimitService rateLimitService;
@Autowired @Lazy
private NotificationCenter notificationCenter;
private final NotificationExecutorService notificationExecutor;
- private final CacheManager cacheManager;
- private Cache sentNotifications;
- @Setter
- private Map triggerTypesConfigs;
private final Map triggerProcessors = new EnumMap<>(NotificationRuleTriggerType.class);
- @PostConstruct
- private void init() {
- sentNotifications = cacheManager.getCache(CacheConstants.SENT_NOTIFICATIONS_CACHE);
- if (sentNotifications == null) {
- throw new IllegalStateException("Sent notifications cache is not set up");
- }
- }
-
@Override
public void process(NotificationRuleTrigger trigger) {
NotificationRuleTriggerType triggerType = trigger.getType();
@@ -104,7 +85,7 @@ public class DefaultNotificationRuleProcessor implements NotificationRuleProcess
}
if (trigger.deduplicate()) {
enabledRules = new ArrayList<>(enabledRules);
- enabledRules.removeIf(rule -> alreadySent(rule, trigger));
+ enabledRules.removeIf(rule -> deduplicationService.alreadyProcessed(trigger, rule));
}
final List rules = enabledRules;
notificationExecutor.submit(() -> {
@@ -199,34 +180,6 @@ public class DefaultNotificationRuleProcessor implements NotificationRuleProcess
return triggerProcessors.get(triggerConfig.getTriggerType()).constructNotificationInfo(trigger);
}
- private boolean alreadySent(NotificationRule rule, NotificationRuleTrigger trigger) {
- String deduplicationKey = getDeduplicationKey(trigger, rule);
-
- boolean alreadySent = false;
- Long lastSentTs = sentNotifications.get(deduplicationKey, Long.class);
- if (lastSentTs != null) {
- long deduplicationDuration = Optional.ofNullable(triggerTypesConfigs)
- .map(triggerTypes -> triggerTypes.get(trigger.getType()))
- .map(TriggerTypeConfig::getDeduplicationDuration)
- .orElseGet(trigger::getDefaultDeduplicationDuration);
- long passed = System.currentTimeMillis() - lastSentTs;
- log.trace("Deduplicating trigger {} for rule '{}' by key '{}'. Deduplication duration: {} ms, passed: {} ms",
- trigger.getType(), rule.getName(), deduplicationKey, deduplicationDuration, passed);
- if (deduplicationDuration == 0 || passed <= deduplicationDuration) {
- alreadySent = true;
- }
- }
- if (!alreadySent) {
- lastSentTs = System.currentTimeMillis();
- }
- sentNotifications.put(deduplicationKey, lastSentTs);
- return alreadySent;
- }
-
- public static String getDeduplicationKey(NotificationRuleTrigger trigger, NotificationRule rule) {
- return String.join("_", trigger.getDeduplicationKey(), rule.getDeduplicationKey());
- }
-
@EventListener(ComponentLifecycleMsg.class)
public void onNotificationRuleDeleted(ComponentLifecycleMsg componentLifecycleMsg) {
if (componentLifecycleMsg.getEvent() != ComponentLifecycleEvent.DELETED ||
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java
index a43ed59efa..d8ac13364b 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java
@@ -24,7 +24,7 @@ import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
import org.thingsboard.server.dao.notification.NotificationRuleService;
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/NotificationRulesCache.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/NotificationRulesCache.java
index 2a1054b352..bcfa7d0120 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/NotificationRulesCache.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/NotificationRulesCache.java
@@ -17,7 +17,7 @@ package org.thingsboard.server.service.notification.rule.cache;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
import java.util.List;
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java
index eca258aecc..dba5fd8de4 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java
@@ -22,10 +22,10 @@ import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.notification.info.AlarmAssignmentNotificationInfo;
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
-import org.thingsboard.server.common.data.notification.rule.trigger.AlarmAssignmentNotificationRuleTriggerConfig;
-import org.thingsboard.server.common.data.notification.rule.trigger.AlarmAssignmentNotificationRuleTriggerConfig.Action;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
-import org.thingsboard.server.common.msg.notification.trigger.AlarmAssignmentTrigger;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmAssignmentNotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmAssignmentNotificationRuleTriggerConfig.Action;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
+import org.thingsboard.server.common.data.notification.rule.trigger.AlarmAssignmentTrigger;
import static org.apache.commons.collections.CollectionUtils.isEmpty;
import static org.thingsboard.server.common.data.util.CollectionsUtil.emptyOrContains;
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java
index 70024d6e09..ef742922b3 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java
@@ -24,9 +24,9 @@ import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.notification.info.AlarmCommentNotificationInfo;
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
-import org.thingsboard.server.common.data.notification.rule.trigger.AlarmCommentNotificationRuleTriggerConfig;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
-import org.thingsboard.server.common.msg.notification.trigger.AlarmCommentTrigger;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmCommentNotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
+import org.thingsboard.server.common.data.notification.rule.trigger.AlarmCommentTrigger;
import org.thingsboard.server.dao.entity.EntityService;
import static org.apache.commons.collections.CollectionUtils.isEmpty;
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java
index c32ed26854..a942dce736 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java
@@ -22,11 +22,11 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
import org.thingsboard.server.common.data.notification.info.AlarmNotificationInfo;
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
-import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig;
-import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig.AlarmAction;
-import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig.ClearRule;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
-import org.thingsboard.server.common.msg.notification.trigger.AlarmTrigger;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig.AlarmAction;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig.ClearRule;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
+import org.thingsboard.server.common.data.notification.rule.trigger.AlarmTrigger;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
import static org.thingsboard.server.common.data.util.CollectionsUtil.emptyOrContains;
@@ -108,6 +108,8 @@ public class AlarmTriggerProcessor implements NotificationRuleTriggerProcessor {
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RateLimitsTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RateLimitsTriggerProcessor.java
new file mode 100644
index 0000000000..bec1502427
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RateLimitsTriggerProcessor.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright © 2016-2023 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.service.notification.rule.trigger;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.notification.info.RateLimitsNotificationInfo;
+import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.RateLimitsNotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.util.CollectionsUtil;
+import org.thingsboard.server.common.data.notification.rule.trigger.RateLimitsTrigger;
+import org.thingsboard.server.dao.entity.EntityService;
+import org.thingsboard.server.dao.tenant.TenantService;
+
+import java.util.Optional;
+
+@Service
+@RequiredArgsConstructor
+public class RateLimitsTriggerProcessor implements NotificationRuleTriggerProcessor {
+
+ private final TenantService tenantService;
+ private final EntityService entityService;
+
+ @Override
+ public boolean matchesFilter(RateLimitsTrigger trigger, RateLimitsNotificationRuleTriggerConfig triggerConfig) {
+ return trigger.getLimitLevel() != null && trigger.getApi().getLabel() != null &&
+ CollectionsUtil.emptyOrContains(triggerConfig.getApis(), trigger.getApi());
+ }
+
+ @Override
+ public RuleOriginatedNotificationInfo constructNotificationInfo(RateLimitsTrigger trigger) {
+ EntityId limitLevel = trigger.getLimitLevel();
+ String tenantName = tenantService.findTenantById(trigger.getTenantId()).getName();
+ String limitLevelEntityName = null;
+ if (limitLevel instanceof TenantId) {
+ limitLevelEntityName = tenantName;
+ } else if (limitLevel != null) {
+ limitLevelEntityName = Optional.ofNullable(trigger.getLimitLevelEntityName())
+ .orElseGet(() -> entityService.fetchEntityName(trigger.getTenantId(), limitLevel).orElse(null));
+ }
+ return RateLimitsNotificationInfo.builder()
+ .tenantId(trigger.getTenantId())
+ .tenantName(tenantName)
+ .api(trigger.getApi())
+ .limitLevel(limitLevel)
+ .limitLevelEntityName(limitLevelEntityName)
+ .build();
+ }
+
+ @Override
+ public NotificationRuleTriggerType getTriggerType() {
+ return NotificationRuleTriggerType.RATE_LIMITS;
+ }
+
+}
diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java
index 6e37db83ef..8aac7ffd66 100644
--- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java
@@ -23,10 +23,10 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.notification.info.RuleEngineComponentLifecycleEventNotificationInfo;
import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
-import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
-import org.thingsboard.server.common.msg.notification.trigger.RuleEngineComponentLifecycleEventTrigger;
+import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineComponentLifecycleEventTrigger;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.queue.discovery.PartitionService;
diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java
index 76631aaa95..53ef38d96a 100644
--- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java
+++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java
@@ -32,10 +32,10 @@ import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.HasName;
+import org.thingsboard.server.common.data.HasRuleEngineProfile;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
-import org.thingsboard.server.common.data.asset.AssetProfile;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.AssetId;
@@ -178,15 +178,8 @@ public class DefaultTbClusterService implements TbClusterService {
return;
}
} else {
- if (entityId.getEntityType().equals(EntityType.DEVICE)) {
- tbMsg = transformMsg(tbMsg, deviceProfileCache.get(tenantId, new DeviceId(entityId.getId())));
- } else if (entityId.getEntityType().equals(EntityType.DEVICE_PROFILE)) {
- tbMsg = transformMsg(tbMsg, deviceProfileCache.get(tenantId, new DeviceProfileId(entityId.getId())));
- } else if (entityId.getEntityType().equals(EntityType.ASSET)) {
- tbMsg = transformMsg(tbMsg, assetProfileCache.get(tenantId, new AssetId(entityId.getId())));
- } else if (entityId.getEntityType().equals(EntityType.ASSET_PROFILE)) {
- tbMsg = transformMsg(tbMsg, assetProfileCache.get(tenantId, new AssetProfileId(entityId.getId())));
- }
+ HasRuleEngineProfile ruleEngineProfile = getRuleEngineProfileForEntityOrElseNull(tenantId, entityId);
+ tbMsg = transformMsg(tbMsg, ruleEngineProfile);
}
TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_RULE_ENGINE, tbMsg.getQueueName(), tenantId, entityId);
log.trace("PUSHING msg: {} to:{}", tbMsg, tpi);
@@ -198,34 +191,33 @@ public class DefaultTbClusterService implements TbClusterService {
toRuleEngineMsgs.incrementAndGet();
}
- private TbMsg transformMsg(TbMsg tbMsg, DeviceProfile deviceProfile) {
- if (deviceProfile != null) {
- RuleChainId targetRuleChainId = deviceProfile.getDefaultRuleChainId();
- String targetQueueName = deviceProfile.getDefaultQueueName();
- tbMsg = transformMsg(tbMsg, targetRuleChainId, targetQueueName);
+ private HasRuleEngineProfile getRuleEngineProfileForEntityOrElseNull(TenantId tenantId, EntityId entityId) {
+ if (entityId.getEntityType().equals(EntityType.DEVICE)) {
+ return deviceProfileCache.get(tenantId, new DeviceId(entityId.getId()));
+ } else if (entityId.getEntityType().equals(EntityType.DEVICE_PROFILE)) {
+ return deviceProfileCache.get(tenantId, new DeviceProfileId(entityId.getId()));
+ } else if (entityId.getEntityType().equals(EntityType.ASSET)) {
+ return assetProfileCache.get(tenantId, new AssetId(entityId.getId()));
+ } else if (entityId.getEntityType().equals(EntityType.ASSET_PROFILE)) {
+ return assetProfileCache.get(tenantId, new AssetProfileId(entityId.getId()));
}
- return tbMsg;
- }
-
- private TbMsg transformMsg(TbMsg tbMsg, AssetProfile assetProfile) {
- if (assetProfile != null) {
- RuleChainId targetRuleChainId = assetProfile.getDefaultRuleChainId();
- String targetQueueName = assetProfile.getDefaultQueueName();
- tbMsg = transformMsg(tbMsg, targetRuleChainId, targetQueueName);
- }
- return tbMsg;
- }
-
- private TbMsg transformMsg(TbMsg tbMsg, RuleChainId targetRuleChainId, String targetQueueName) {
- boolean isRuleChainTransform = targetRuleChainId != null && !targetRuleChainId.equals(tbMsg.getRuleChainId());
- boolean isQueueTransform = targetQueueName != null && !targetQueueName.equals(tbMsg.getQueueName());
-
- if (isRuleChainTransform && isQueueTransform) {
- tbMsg = TbMsg.transformMsg(tbMsg, targetRuleChainId, targetQueueName);
- } else if (isRuleChainTransform) {
- tbMsg = TbMsg.transformMsg(tbMsg, targetRuleChainId);
- } else if (isQueueTransform) {
- tbMsg = TbMsg.transformMsg(tbMsg, targetQueueName);
+ return null;
+ }
+ private TbMsg transformMsg(TbMsg tbMsg, HasRuleEngineProfile ruleEngineProfile) {
+ if (ruleEngineProfile != null) {
+ RuleChainId targetRuleChainId = ruleEngineProfile.getDefaultRuleChainId();
+ String targetQueueName = ruleEngineProfile.getDefaultQueueName();
+
+ boolean isRuleChainTransform = targetRuleChainId != null && !targetRuleChainId.equals(tbMsg.getRuleChainId());
+ boolean isQueueTransform = targetQueueName != null && !targetQueueName.equals(tbMsg.getQueueName());
+
+ if (isRuleChainTransform && isQueueTransform) {
+ tbMsg = TbMsg.transformMsg(tbMsg, targetRuleChainId, targetQueueName);
+ } else if (isRuleChainTransform) {
+ tbMsg = TbMsg.transformMsgRuleChainId(tbMsg, targetRuleChainId);
+ } else if (isQueueTransform) {
+ tbMsg = TbMsg.transformMsgQueueName(tbMsg, targetQueueName);
+ }
}
return tbMsg;
}
@@ -466,11 +458,6 @@ public class DefaultTbClusterService implements TbClusterService {
@Override
public void onDeviceUpdated(Device device, Device old) {
- onDeviceUpdated(device, old, true);
- }
-
- @Override
- public void onDeviceUpdated(Device device, Device old, boolean notifyEdge) {
var created = old == null;
broadcastEntityChangeToTransport(device.getTenantId(), device.getId(), device, null);
if (old != null) {
@@ -485,9 +472,6 @@ public class DefaultTbClusterService implements TbClusterService {
broadcastEntityStateChangeEvent(device.getTenantId(), device.getId(), created ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
sendDeviceStateServiceEvent(device.getTenantId(), device.getId(), created, !created, false);
otaPackageStateService.update(device, old);
- if (!created && notifyEdge) {
- sendNotificationMsgToEdge(device.getTenantId(), null, device.getId(), null, null, EdgeEventActionType.UPDATED);
- }
}
@Override
diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java
index 182fce1c48..fef22acf40 100644
--- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java
+++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java
@@ -32,10 +32,11 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.NotificationRequestId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
+import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTrigger;
import org.thingsboard.server.common.data.rpc.RpcError;
import org.thingsboard.server.common.msg.MsgType;
import org.thingsboard.server.common.msg.TbActorMsg;
-import org.thingsboard.server.common.msg.notification.trigger.NotificationRuleTrigger;
+import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse;
@@ -63,7 +64,6 @@ import org.thingsboard.server.queue.TbQueueConsumer;
import org.thingsboard.server.queue.common.TbProtoQueueMsg;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent;
-import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.provider.TbCoreQueueFactory;
import org.thingsboard.server.queue.util.AfterStartUp;
import org.thingsboard.server.queue.util.DataDecodingEncodingService;
diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java
index f8f6a7d25f..ac7d796e33 100644
--- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java
+++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java
@@ -259,7 +259,21 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
}
void launchConsumer(TbQueueConsumer> consumer, Queue configuration, TbRuleEngineConsumerStats stats, String threadSuffix) {
- consumersExecutor.execute(() -> consumerLoop(consumer, configuration, stats, threadSuffix));
+ if (isReady) {
+ consumersExecutor.execute(() -> consumerLoop(consumer, configuration, stats, threadSuffix));
+ } else {
+ scheduleLaunchConsumer(consumer, configuration, stats, threadSuffix);
+ }
+ }
+
+ private void scheduleLaunchConsumer(TbQueueConsumer> consumer, Queue configuration, TbRuleEngineConsumerStats stats, String threadSuffix) {
+ repartitionExecutor.schedule(() -> {
+ if (isReady) {
+ consumersExecutor.execute(() -> consumerLoop(consumer, configuration, stats, threadSuffix));
+ } else {
+ scheduleLaunchConsumer(consumer, configuration, stats, threadSuffix);
+ }
+ }, 10, TimeUnit.SECONDS);
}
void consumerLoop(TbQueueConsumer> consumer, org.thingsboard.server.common.data.queue.Queue configuration, TbRuleEngineConsumerStats stats, String threadSuffix) {
@@ -349,7 +363,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
callback.onSuccess();
}
} catch (Exception e) {
- callback.onFailure(new RuleEngineException(e.getMessage()));
+ callback.onFailure(new RuleEngineException(e.getMessage(), e));
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackCallback.java b/application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackCallback.java
index ef2ba8798d..c2171c2550 100644
--- a/application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackCallback.java
+++ b/application/src/main/java/org/thingsboard/server/service/queue/TbMsgPackCallback.java
@@ -17,11 +17,14 @@ package org.thingsboard.server.service.queue;
import io.micrometer.core.instrument.Timer;
import lombok.extern.slf4j.Slf4j;
+import org.thingsboard.common.util.ExceptionUtil;
+import org.thingsboard.server.common.data.exception.AbstractRateLimitException;
import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.queue.RuleEngineException;
import org.thingsboard.server.common.msg.queue.RuleNodeInfo;
import org.thingsboard.server.common.msg.queue.TbMsgCallback;
+import org.thingsboard.server.common.msg.tools.TbRateLimitsException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@@ -57,8 +60,23 @@ public class TbMsgPackCallback implements TbMsgCallback {
ctx.onSuccess(id);
}
+ @Override
+ public void onRateLimit(RuleEngineException e) {
+ log.debug("[{}] ON RATE LIMIT", id, e);
+ //TODO notify tenant on rate limit
+ if (failedMsgTimer != null) {
+ failedMsgTimer.record(System.currentTimeMillis() - startMsgProcessing, TimeUnit.MILLISECONDS);
+ }
+ ctx.onSuccess(id);
+ }
+
@Override
public void onFailure(RuleEngineException e) {
+ if (ExceptionUtil.lookupExceptionInCause(e, AbstractRateLimitException.class) != null) {
+ onRateLimit(e);
+ return;
+ }
+
log.trace("[{}] ON FAILURE", id, e);
if (failedMsgTimer != null) {
failedMsgTimer.record(System.currentTimeMillis() - startMsgProcessing, TimeUnit.MILLISECONDS);
diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java
index 2d517a2213..b59086a350 100644
--- a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java
+++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java
@@ -68,7 +68,7 @@ public abstract class AbstractConsumerService getRuleChainOutputLabels(TenantId tenantId, RuleChainId ruleChainId) {
@@ -182,9 +184,7 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
tbClusterService.broadcastEntityStateChangeEvent(tenantId, savedRuleChain.getId(),
actionType.equals(ActionType.ADDED) ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
}
- boolean sendMsgToEdge = RuleChainType.EDGE.equals(savedRuleChain.getType()) && actionType.equals(ActionType.UPDATED);
- notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedRuleChain.getId(),
- savedRuleChain, user, actionType, sendMsgToEdge, null);
+ notificationEntityService.logEntityAction(tenantId, savedRuleChain.getId(), savedRuleChain, null, actionType, user);
return savedRuleChain;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.RULE_CHAIN), ruleChain, actionType, user, e);
@@ -201,11 +201,6 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
Set referencingRuleChainIds = referencingRuleNodes.stream().map(RuleNode::getRuleChainId).collect(Collectors.toSet());
- List relatedEdgeIds = null;
- if (RuleChainType.EDGE.equals(ruleChain.getType())) {
- relatedEdgeIds = edgeService.findAllRelatedEdgeIds(tenantId, ruleChainId);
- }
-
ruleChainService.deleteRuleChainById(tenantId, ruleChainId);
referencingRuleChainIds.remove(ruleChain.getId());
@@ -217,7 +212,7 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
tbClusterService.broadcastEntityStateChangeEvent(tenantId, ruleChain.getId(), ComponentLifecycleEvent.DELETED);
}
- notificationEntityService.notifyDeleteRuleChain(tenantId, ruleChain, relatedEdgeIds, user);
+ notificationEntityService.logEntityAction(tenantId, ruleChainId, ruleChain, null, ActionType.DELETED, user, ruleChainId.toString());
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.RULE_CHAIN), ActionType.DELETED,
user, e, ruleChainId.toString());
@@ -277,7 +272,7 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
RuleChainId ruleChainId = ruleChain.getId();
RuleChainId ruleChainMetaDataId = ruleChainMetaData.getRuleChainId();
try {
- RuleChainUpdateResult result = ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData);
+ RuleChainUpdateResult result = ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData, this::updateRuleNodeConfiguration);
checkNotNull(result.isSuccess() ? true : null);
List updatedRuleChains;
@@ -307,14 +302,8 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
notificationEntityService.logEntityAction(tenantId, ruleChainId, ruleChain, ActionType.UPDATED, user, ruleChainMetaData);
- if (RuleChainType.EDGE.equals(ruleChain.getType())) {
- notificationEntityService.notifySendMsgToEdgeService(tenantId, ruleChain.getId(), EdgeEventActionType.UPDATED);
- }
-
for (RuleChain updatedRuleChain : updatedRuleChains) {
- if (RuleChainType.EDGE.equals(ruleChain.getType())) {
- notificationEntityService.notifySendMsgToEdgeService(tenantId, updatedRuleChain.getId(), EdgeEventActionType.UPDATED);
- } else {
+ if (RuleChainType.CORE.equals(ruleChain.getType())) {
RuleChainMetaData updatedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, updatedRuleChain.getId()));
notificationEntityService.logEntityAction(tenantId, updatedRuleChain.getId(), updatedRuleChain,
ActionType.UPDATED, user, updatedRuleChainMetaData);
@@ -330,34 +319,34 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
@Override
public RuleChain assignRuleChainToEdge(TenantId tenantId, RuleChain ruleChain, Edge edge, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.ASSIGNED_TO_EDGE;
RuleChainId ruleChainId = ruleChain.getId();
EdgeId edgeId = edge.getId();
try {
RuleChain savedRuleChain = checkNotNull(ruleChainService.assignRuleChainToEdge(tenantId, ruleChainId, edgeId));
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, ruleChainId,
- null, edgeId, savedRuleChain, ActionType.ASSIGNED_TO_EDGE,
+ notificationEntityService.logEntityAction(tenantId, ruleChainId, savedRuleChain, null, actionType,
user, ruleChainId.toString(), edgeId.toString(), edge.getName());
return savedRuleChain;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.RULE_CHAIN),
- ActionType.ASSIGNED_TO_EDGE, user, e, ruleChainId.toString(), edgeId.toString());
+ actionType, user, e, ruleChainId.toString(), edgeId.toString());
throw e;
}
}
@Override
public RuleChain unassignRuleChainFromEdge(TenantId tenantId, RuleChain ruleChain, Edge edge, User user) throws ThingsboardException {
+ ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE;
RuleChainId ruleChainId = ruleChain.getId();
EdgeId edgeId = edge.getId();
try {
RuleChain savedRuleChain = checkNotNull(ruleChainService.unassignRuleChainFromEdge(tenantId, ruleChainId, edgeId, false));
- notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, ruleChainId,
- null, edgeId, savedRuleChain, ActionType.UNASSIGNED_FROM_EDGE,
+ notificationEntityService.logEntityAction(tenantId, ruleChainId, savedRuleChain, null, actionType,
user, ruleChainId.toString(), edgeId.toString(), edge.getName());
return savedRuleChain;
} catch (Exception e) {
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.RULE_CHAIN),
- ActionType.UNASSIGNED_FROM_EDGE, user, e, ruleChainId, edgeId);
+ actionType, user, e, ruleChainId, edgeId);
throw e;
}
}
@@ -404,6 +393,45 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
}
}
+ @Override
+ public RuleNode updateRuleNodeConfiguration(RuleNode node) {
+ var ruleChainId = node.getRuleChainId();
+ var ruleNodeId = node.getId();
+ var ruleNodeType = node.getType();
+ try {
+ var ruleNodeClass = componentDiscoveryService.getRuleNodeInfo(ruleNodeType)
+ .orElseThrow(() -> new RuntimeException("Rule node " + ruleNodeType + " is not supported!"));
+ if (ruleNodeClass.isVersioned()) {
+ TbVersionedNode tbVersionedNode = (TbVersionedNode) ruleNodeClass.getClazz().getDeclaredConstructor().newInstance();
+ int fromVersion = node.getConfigurationVersion();
+ int toVersion = ruleNodeClass.getCurrentVersion();
+ if (fromVersion < toVersion) {
+ log.debug("Going to upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
+ ruleNodeId, ruleNodeType, fromVersion, toVersion);
+ try {
+ TbPair upgradeResult = tbVersionedNode.upgrade(fromVersion, node.getConfiguration());
+ if (upgradeResult.getFirst()) {
+ node.setConfiguration(upgradeResult.getSecond());
+ }
+ node.setConfigurationVersion(toVersion);
+ log.debug("Successfully upgrade rule node with id: {} type: {}, rule chain id: {} fromVersion: {} toVersion: {}",
+ ruleNodeId, ruleNodeType, ruleChainId, fromVersion, toVersion);
+ } catch (TbNodeException e) {
+ log.warn("Failed to upgrade rule node with id: {} type: {} rule chain id: {} fromVersion: {} toVersion: {} due to: ",
+ ruleNodeId, ruleNodeType, ruleChainId, fromVersion, toVersion, e);
+ }
+ } else {
+ log.debug("Rule node with id: {} type: {} ruleChainId: {} already set to latest version!",
+ ruleNodeId, ruleChainId, ruleNodeType);
+ }
+ }
+ } catch (Exception e) {
+ log.error("Failed to update the rule node with id: {} type: {}, rule chain id: {}",
+ ruleNodeId, ruleNodeType, ruleChainId, e);
+ }
+ return node;
+ }
+
private Set updateRelatedRuleChains(TenantId tenantId, RuleChainId ruleChainId, Map labelsMap) {
Set updatedRuleChains = new HashSet<>();
List usageList = getOutputLabelUsage(tenantId, ruleChainId);
diff --git a/application/src/main/java/org/thingsboard/server/service/rule/TbRuleChainService.java b/application/src/main/java/org/thingsboard/server/service/rule/TbRuleChainService.java
index 02b79544f4..17f1338bba 100644
--- a/application/src/main/java/org/thingsboard/server/service/rule/TbRuleChainService.java
+++ b/application/src/main/java/org/thingsboard/server/service/rule/TbRuleChainService.java
@@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleChainOutputLabelsUsage;
import org.thingsboard.server.common.data.rule.RuleChainUpdateResult;
+import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.service.entitiy.SimpleTbEntityService;
import java.util.List;
@@ -54,4 +55,6 @@ public interface TbRuleChainService extends SimpleTbEntityService {
RuleChain setAutoAssignToEdgeRuleChain(TenantId tenantId, RuleChain ruleChain, User user) throws ThingsboardException;
RuleChain unsetAutoAssignToEdgeRuleChain(TenantId tenantId, RuleChain ruleChain, User user) throws ThingsboardException;
+
+ RuleNode updateRuleNodeConfiguration(RuleNode ruleNode);
}
diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java b/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java
index a58c801583..08717986bf 100644
--- a/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java
+++ b/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/DefaultTwoFactorAuthService.java
@@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.security.model.mfa.account.TwoFaAccoun
import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderConfig;
import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType;
import org.thingsboard.server.dao.user.UserService;
-import org.thingsboard.server.dao.util.limits.LimitedApi;
+import org.thingsboard.server.common.data.limit.LimitedApi;
import org.thingsboard.server.dao.util.limits.RateLimitService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.auth.mfa.config.TwoFaConfigManager;
diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java
index 337d607fac..cdc5afe361 100644
--- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java
+++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java
@@ -36,7 +36,6 @@ import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.ApiUsageRecordKey;
-import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceIdInfo;
import org.thingsboard.server.common.data.EntityType;
@@ -51,6 +50,8 @@ import org.thingsboard.server.common.data.kv.BooleanDataEntry;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
+import org.thingsboard.server.common.data.msg.TbMsgType;
+import org.thingsboard.server.common.data.notification.rule.trigger.DeviceActivityTrigger;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.query.EntityData;
@@ -63,7 +64,6 @@ import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
-import org.thingsboard.server.common.msg.notification.trigger.DeviceActivityTrigger;
import org.thingsboard.server.common.msg.queue.ServiceType;
import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
@@ -102,10 +102,7 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
-import static org.thingsboard.server.common.data.DataConstants.ACTIVITY_EVENT;
-import static org.thingsboard.server.common.data.DataConstants.CONNECT_EVENT;
-import static org.thingsboard.server.common.data.DataConstants.DISCONNECT_EVENT;
-import static org.thingsboard.server.common.data.DataConstants.INACTIVITY_EVENT;
+import static org.thingsboard.server.common.data.DataConstants.SCOPE;
import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE;
/**
@@ -229,9 +226,8 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService= deviceState.getLastActivityTime()) {
+ deviceState.setLastInactivityAlarmTime(0L);
+ save(deviceId, INACTIVITY_ALARM_TIME, 0L);
+ }
}
}
}
@@ -533,7 +534,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService> tsData = tsService.findLatest(TenantId.SYS_TENANT_ID, device.getId(), PERSISTENT_ATTRIBUTES);
future = Futures.transform(tsData, extractDeviceStateData(device), deviceStateExecutor);
} else {
- ListenableFuture> attrData = attributesService.find(TenantId.SYS_TENANT_ID, device.getId(), DataConstants.SERVER_SCOPE, PERSISTENT_ATTRIBUTES);
+ ListenableFuture> attrData = attributesService.find(TenantId.SYS_TENANT_ID, device.getId(), SERVER_SCOPE, PERSISTENT_ATTRIBUTES);
future = Futures.transform(attrData, extractDeviceStateData(device), deviceStateExecutor);
}
return transformInactivityTimeout(future);
@@ -771,11 +772,11 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService(deviceId, key, value));
} else {
- tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new TelemetrySaveCallback<>(deviceId, key, value));
+ tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, SERVER_SCOPE, key, value, new TelemetrySaveCallback<>(deviceId, key, value));
}
}
@@ -811,7 +812,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService(deviceId, key, value));
} else {
- tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new TelemetrySaveCallback<>(deviceId, key, value));
+ tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, SERVER_SCOPE, key, value, new TelemetrySaveCallback<>(deviceId, key, value));
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java
index c8f8f945f9..dcb6764201 100644
--- a/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java
+++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java
@@ -25,15 +25,15 @@ import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.limit.LimitedApi;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.common.data.sync.ie.EntityImportResult;
import org.thingsboard.server.common.data.util.ThrowingRunnable;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.relation.RelationService;
-import org.thingsboard.server.queue.util.TbCoreComponent;
-import org.thingsboard.server.dao.util.limits.LimitedApi;
import org.thingsboard.server.dao.util.limits.RateLimitService;
+import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.entitiy.TbNotificationEntityService;
import org.thingsboard.server.service.sync.ie.exporting.EntityExportService;
import org.thingsboard.server.service.sync.ie.exporting.impl.BaseEntityExportService;
@@ -119,8 +119,8 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
relationService.saveRelations(ctx.getTenantId(), new ArrayList<>(ctx.getRelations()));
for (EntityRelation relation : ctx.getRelations()) {
- entityNotificationService.notifyRelation(ctx.getTenantId(), null,
- relation, ctx.getUser(), ActionType.RELATION_ADD_OR_UPDATE, relation);
+ entityNotificationService.logEntityRelationAction(ctx.getTenantId(), null,
+ relation, ctx.getUser(), ActionType.RELATION_ADD_OR_UPDATE, null, relation);
}
}
diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationRuleExportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationRuleExportService.java
index 0906fb83ef..a2b9c54403 100644
--- a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationRuleExportService.java
+++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/NotificationRuleExportService.java
@@ -28,9 +28,9 @@ import org.thingsboard.server.common.data.notification.rule.DefaultNotificationR
import org.thingsboard.server.common.data.notification.rule.EscalatedNotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.rule.NotificationRuleRecipientsConfig;
-import org.thingsboard.server.common.data.notification.rule.trigger.DeviceActivityNotificationRuleTriggerConfig;
-import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
-import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.DeviceActivityNotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerConfig;
+import org.thingsboard.server.common.data.notification.rule.trigger.config.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.data.EntitiesExportCtx;
diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/AssetProfileImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/AssetProfileImportService.java
index 7f0af64ed7..3255c418c5 100644
--- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/AssetProfileImportService.java
+++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/AssetProfileImportService.java
@@ -58,8 +58,8 @@ public class AssetProfileImportService extends BaseEntityImportService {
- entityNotificationService.notifyRelation(tenantId, null,
- existingRelation, ctx.getUser(), ActionType.RELATION_DELETED, existingRelation);
+ entityNotificationService.logEntityRelationAction(tenantId, null,
+ existingRelation, ctx.getUser(), ActionType.RELATION_DELETED, null, existingRelation);
});
} else if (Objects.equal(relation.getAdditionalInfo(), existingRelation.getAdditionalInfo())) {
relationsMap.remove(relation);
@@ -266,8 +266,8 @@ public abstract class BaseEntityImportService HINTS = new LinkedHashSet<>(Arrays.asList(EntityType.RULE_CHAIN, EntityType.DEVICE, EntityType.ASSET));
+ private final TbRuleChainService tbRuleChainService;
private final RuleChainService ruleChainService;
private final RuleNodeDao ruleNodeDao;
@@ -106,7 +107,7 @@ public class RuleChainImportService extends BaseEntityImportService taskCache;
@@ -432,12 +429,11 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
return exportableEntitiesService.findEntitiesByTenantId(ctx.getTenantId(), entityType, pageLink);
}, 100, entity -> {
if (ctx.getImportedEntities().get(entityType) == null || !ctx.getImportedEntities().get(entityType).contains(entity.getId())) {
- List relatedEdgeIds = edgeService.findAllRelatedEdgeIds(ctx.getTenantId(), entity.getId());
exportableEntitiesService.removeById(ctx.getTenantId(), entity.getId());
ctx.addEventCallback(() -> {
- entityNotificationService.notifyDeleteEntity(ctx.getTenantId(), entity.getId(),
- entity, null, ActionType.DELETED, relatedEdgeIds, ctx.getUser());
+ entityNotificationService.logEntityAction(ctx.getTenantId(), entity.getId(), entity, null,
+ ActionType.DELETED, ctx.getUser());
});
ctx.registerDeleted(entityType);
}
diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java
index e7f2a5a66f..b2b9d992e6 100644
--- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java
+++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java
@@ -44,15 +44,15 @@ import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
+import org.thingsboard.server.common.data.notification.rule.trigger.AlarmTrigger;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.AlarmData;
import org.thingsboard.server.common.data.query.AlarmDataQuery;
-import org.thingsboard.server.common.msg.notification.trigger.AlarmTrigger;
+import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.dao.alarm.AlarmOperationResult;
import org.thingsboard.server.dao.alarm.AlarmService;
-import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService;
import org.thingsboard.server.service.subscription.TbSubscriptionUtils;
diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java
index 3f5e52796a..df3a15e765 100644
--- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java
+++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java
@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
@@ -78,6 +79,9 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
private ExecutorService tsCallBackExecutor;
+ @Value("${sql.ts.value_no_xss_validation:false}")
+ private boolean valueNoXssValidation;
+
public DefaultTelemetrySubscriptionService(AttributesService attrService,
TimeseriesService tsService,
@Lazy TbEntityViewService tbEntityViewService,
@@ -135,7 +139,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer
checkInternalEntity(entityId);
boolean sysTenant = TenantId.SYS_TENANT_ID.equals(tenantId) || tenantId == null;
if (sysTenant || apiUsageStateService.getApiUsageState(tenantId).isDbStorageEnabled()) {
- KvUtils.validate(ts);
+ KvUtils.validate(ts, valueNoXssValidation);
if (saveLatest) {
saveAndNotifyInternal(tenantId, entityId, ts, ttl, getCallback(tenantId, customerId, sysTenant, callback));
} else {
diff --git a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
index d0d996fe1f..89a7480708 100644
--- a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
+++ b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
@@ -53,6 +53,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.ota.OtaPackageUtil;
import org.thingsboard.server.common.data.page.PageData;
@@ -346,7 +347,7 @@ public class DefaultTransportApiService implements TransportApiService {
DeviceId deviceId = device.getId();
JsonNode entityNode = JacksonUtil.valueToTree(device);
- TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, customerId, metaData, TbMsgDataType.JSON, JacksonUtil.toString(entityNode));
+ TbMsg tbMsg = TbMsg.newMsg(TbMsgType.ENTITY_CREATED, deviceId, customerId, metaData, TbMsgDataType.JSON, JacksonUtil.toString(entityNode));
tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, null);
} else {
JsonNode deviceAdditionalInfo = device.getAdditionalInfo();
diff --git a/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java b/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java
index 587d86af32..f5e3daf05d 100644
--- a/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java
+++ b/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java
@@ -28,7 +28,7 @@ import org.springframework.web.client.RestTemplate;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.common.data.UpdateMessage;
-import org.thingsboard.server.common.msg.notification.trigger.NewPlatformVersionTrigger;
+import org.thingsboard.server.common.data.notification.rule.trigger.NewPlatformVersionTrigger;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.queue.util.AfterStartUp;
import org.thingsboard.server.queue.util.TbCoreComponent;
diff --git a/application/src/main/java/org/thingsboard/server/utils/LwM2mObjectModelUtils.java b/application/src/main/java/org/thingsboard/server/utils/LwM2mObjectModelUtils.java
index 4a07444bbb..0deb2f6bb7 100644
--- a/application/src/main/java/org/thingsboard/server/utils/LwM2mObjectModelUtils.java
+++ b/application/src/main/java/org/thingsboard/server/utils/LwM2mObjectModelUtils.java
@@ -16,8 +16,6 @@
package org.thingsboard.server.utils;
import lombok.extern.slf4j.Slf4j;
-import org.eclipse.leshan.core.model.DDFFileParser;
-import org.eclipse.leshan.core.model.DefaultDDFFileValidator;
import org.eclipse.leshan.core.model.InvalidDDFFileException;
import org.eclipse.leshan.core.model.ObjectModel;
import org.thingsboard.server.common.data.ResourceType;
diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml
index 8e9c6147f0..e874e41cd7 100644
--- a/application/src/main/resources/thingsboard.yml
+++ b/application/src/main/resources/thingsboard.yml
@@ -96,6 +96,10 @@ zk:
session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}"
# Name of the directory in zookeeper 'filesystem'
zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}"
+ # The recalculate_delay property recommended in a microservices architecture setup for rule-engine services.
+ # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions.
+ # The delay is recommended because the initialization of rule chain actors is time-consuming. Avoiding unnecessary recalculations during a restart can enhance system performance and stability.
+ recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}"
cluster:
stats:
@@ -249,7 +253,8 @@ cassandra:
concurrent_limit: "${CASSANDRA_QUERY_CONCURRENT_LIMIT:1000}"
permit_max_wait_time: "${PERMIT_MAX_WAIT_TIME:120000}"
dispatcher_threads: "${CASSANDRA_QUERY_DISPATCHER_THREADS:2}"
- callback_threads: "${CASSANDRA_QUERY_CALLBACK_THREADS:4}"
+ callback_threads: "${CASSANDRA_QUERY_CALLBACK_THREADS:4}" # Buffered rate executor (read, write), for managing I/O rate. See "nosql-*-callback" threads in JMX
+ result_processing_threads: "${CASSANDRA_QUERY_RESULT_PROCESSING_THREADS:50}" # Result set transformer and processing. See "cassandra-callback" threads in JMX
poll_ms: "${CASSANDRA_QUERY_POLL_MS:50}"
rate_limit_print_interval_ms: "${CASSANDRA_QUERY_RATE_LIMIT_PRINT_MS:10000}"
# set all data types values except target to null for the same ts on save
@@ -267,11 +272,13 @@ sql:
batch_max_delay: "${SQL_ATTRIBUTES_BATCH_MAX_DELAY_MS:100}"
stats_print_interval_ms: "${SQL_ATTRIBUTES_BATCH_STATS_PRINT_MS:10000}"
batch_threads: "${SQL_ATTRIBUTES_BATCH_THREADS:3}" # batch thread count have to be a prime number like 3 or 5 to gain perfect hash distribution
+ value_no_xss_validation: "${SQL_ATTRIBUTES_VALUE_NO_XSS_VALIDATION:false}"
ts:
batch_size: "${SQL_TS_BATCH_SIZE:10000}"
batch_max_delay: "${SQL_TS_BATCH_MAX_DELAY_MS:100}"
stats_print_interval_ms: "${SQL_TS_BATCH_STATS_PRINT_MS:10000}"
batch_threads: "${SQL_TS_BATCH_THREADS:3}" # batch thread count have to be a prime number like 3 or 5 to gain perfect hash distribution
+ value_no_xss_validation: "${SQL_TS_VALUE_NO_XSS_VALIDATION:false}"
ts_latest:
batch_size: "${SQL_TS_LATEST_BATCH_SIZE:10000}"
batch_max_delay: "${SQL_TS_LATEST_BATCH_MAX_DELAY_MS:100}"
@@ -393,6 +400,10 @@ actors:
queue_size: "${ACTORS_RULE_TRANSACTION_QUEUE_SIZE:15000}"
# Time in milliseconds for transaction to complete
duration: "${ACTORS_RULE_TRANSACTION_DURATION:60000}"
+ external:
+ # Force acknowledgement of the incoming message for external rule nodes to decrease processing latency.
+ # Enqueue the result of external node processing as a separate message to the rule engine.
+ force_ack: "${ACTORS_RULE_EXTERNAL_NODE_FORCE_ACK:false}"
rpc:
max_retries: "${ACTORS_RPC_MAX_RETRIES:5}"
sequential: "${ACTORS_RPC_SEQUENTIAL:false}"
@@ -493,6 +504,9 @@ cache:
entityCount:
timeToLiveInMinutes: "${CACHE_SPECS_ENTITY_COUNT_TTL:1440}"
maxSize: "${CACHE_SPECS_ENTITY_COUNT_MAX_SIZE:100000}"
+ resourceInfo:
+ timeToLiveInMinutes: "${CACHE_SPECS_RESOURCE_INFO_TTL:1440}"
+ maxSize: "${CACHE_SPECS_RESOURCE_INFO_MAX_SIZE:100000}"
# deliberately placed outside 'specs' group above
notificationRules:
@@ -978,6 +992,35 @@ transport:
enabled: "${TB_TRANSPORT_STATS_ENABLED:true}"
print-interval-ms: "${TB_TRANSPORT_STATS_PRINT_INTERVAL_MS:60000}"
+# Device connectivity properties to publish telemetry
+device:
+ connectivity:
+ http:
+ enabled: "${DEVICE_CONNECTIVITY_HTTP_ENABLED:true}"
+ host: "${DEVICE_CONNECTIVITY_HTTP_HOST:}"
+ port: "${DEVICE_CONNECTIVITY_HTTP_PORT:8080}"
+ https:
+ enabled: "${DEVICE_CONNECTIVITY_HTTPS_ENABLED:false}"
+ host: "${DEVICE_CONNECTIVITY_HTTPS_HOST:}"
+ port: "${DEVICE_CONNECTIVITY_HTTPS_PORT:443}"
+ mqtt:
+ enabled: "${DEVICE_CONNECTIVITY_MQTT_ENABLED:true}"
+ host: "${DEVICE_CONNECTIVITY_MQTT_HOST:}"
+ port: "${DEVICE_CONNECTIVITY_MQTT_PORT:1883}"
+ mqtts:
+ enabled: "${DEVICE_CONNECTIVITY_MQTTS_ENABLED:false}"
+ host: "${DEVICE_CONNECTIVITY_MQTTS_HOST:}"
+ port: "${DEVICE_CONNECTIVITY_MQTTS_PORT:8883}"
+ pem_cert_file: "${DEVICE_CONNECTIVITY_MQTT_SSL_PEM_CERT:mqttserver.pem}"
+ coap:
+ enabled: "${DEVICE_CONNECTIVITY_COAP_ENABLED:true}"
+ host: "${DEVICE_CONNECTIVITY_COAP_HOST:}"
+ port: "${DEVICE_CONNECTIVITY_COAP_PORT:5683}"
+ coaps:
+ enabled: "${DEVICE_CONNECTIVITY_COAPS_ENABLED:false}"
+ host: "${DEVICE_CONNECTIVITY_COAPS_HOST:}"
+ port: "${DEVICE_CONNECTIVITY_COAPS_PORT:5684}"
+
# Edges parameters
edges:
enabled: "${EDGES_ENABLED:true}"
@@ -1276,10 +1319,8 @@ vc:
notification_system:
thread_pool_size: "${TB_NOTIFICATION_SYSTEM_THREAD_POOL_SIZE:10}"
rules:
- trigger_types_configs:
- NEW_PLATFORM_VERSION:
- # In milliseconds, infinitely by default
- deduplication_duration: "${NEW_PLATFORM_VERSION_NOTIFICATION_RULE_DEDUPLICATION_DURATION:0}"
+ # Semicolon-separated deduplication durations (in millis) for trigger types. Format: 'NotificationRuleTriggerType1:123;NotificationRuleTriggerType2:456'
+ deduplication_durations: "${TB_NOTIFICATION_RULES_DEDUPLICATION_DURATIONS:NEW_PLATFORM_VERSION:0;RATE_LIMITS:14400000;}"
management:
endpoints:
diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java
index d5eabdff2a..71c244890d 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java
@@ -74,6 +74,17 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
Mockito.reset(tbClusterService, auditLogService);
}
+ protected void testNotifyAssignUnassignEntityAllOneTime(HasName entity, EntityId entityId, EntityId originatorId,
+ TenantId tenantId, CustomerId customerId, UserId userId, String userName,
+ ActionType actionType, ActionType actionTypeEdge, Object... additionalInfo) {
+ int cntTime = 1;
+ testNotificationMsgToEdgeServiceTime(entityId, tenantId, actionTypeEdge, cntTime);
+ testLogEntityAction(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo);
+ ArgumentMatcher matcherOriginatorId = argument -> argument.equals(originatorId);
+ testPushMsgToRuleEngineTime(matcherOriginatorId, tenantId, entity, cntTime);
+ Mockito.reset(tbClusterService, auditLogService);
+ }
+
protected void testNotifyEntityAllOneTimeRelation(EntityRelation relation,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
ActionType actionType, Object... additionalInfo) {
@@ -115,9 +126,9 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
protected void testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(HasName entity, EntityId entityId, EntityId originatorId,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
- ActionType actionType, Object... additionalInfo) {
+ ActionType actionType, ActionType actionTypeEdge, Object... additionalInfo) {
int cntTime = 1;
- testNotificationMsgToEdgeServiceTime(entityId, tenantId, actionType, cntTime);
+ testNotificationMsgToEdgeServiceTime(entityId, tenantId, actionTypeEdge, cntTime);
testLogEntityActionEntityEqClass(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo);
ArgumentMatcher matcherOriginatorId = argument -> argument.equals(originatorId);
testPushMsgToRuleEngineTime(matcherOriginatorId, tenantId, entity, cntTime);
@@ -163,10 +174,10 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest {
protected void testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(HasName entity, HasName originator,
TenantId tenantId, CustomerId customerId, UserId userId, String userName,
- ActionType actionType, ActionType actionTypeEdge,
+ ActionType actionType,
int cntTime, int cntTimeEdge, int cntTimeRuleEngine, Object... additionalInfo) {
EntityId originatorId = createEntityId_NULL_UUID(originator);
- testSendNotificationMsgToEdgeServiceTimeEntityEqAny(tenantId, actionTypeEdge, cntTimeEdge);
+ testSendNotificationMsgToEdgeServiceTimeEntityEqAny(tenantId, actionType, cntTimeEdge);
ArgumentMatcher matcherEntityClassEquals = argument -> argument.getClass().equals(entity.getClass());
ArgumentMatcher matcherOriginatorId = argument -> argument.getClass().equals(originatorId.getClass());
ArgumentMatcher matcherCustomerId = customerId == null ?
diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java
index 49e3550a1e..656936b175 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AbstractRuleEngineControllerTest.java
@@ -25,13 +25,13 @@ import org.thingsboard.server.common.data.event.EventType;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.dao.rule.RuleChainService;
-import java.io.IOException;
import java.util.function.Predicate;
/**
@@ -82,8 +82,8 @@ public abstract class AbstractRuleEngineControllerTest extends AbstractControlle
}
}
- protected Predicate filterByCustomEvent() {
- return event -> event.getBody().get("msgType").textValue().equals("CUSTOM");
+ protected Predicate filterByPostTelemetryEventType() {
+ return event -> event.getBody().get("msgType").textValue().equals(TbMsgType.POST_TELEMETRY_REQUEST.name());
}
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
index 7f57fbbb3f..c32b4cf8d7 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
@@ -95,6 +95,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.PageData;
@@ -188,7 +189,9 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
protected String username;
protected TenantId tenantId;
+ protected TenantProfileId tenantProfileId;
protected UserId tenantAdminUserId;
+ protected User tenantAdminUser;
protected CustomerId tenantAdminCustomerId;
protected CustomerId customerId;
protected TenantId differentTenantId;
@@ -269,15 +272,16 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
Tenant savedTenant = doPost("/api/tenant", tenant, Tenant.class);
Assert.assertNotNull(savedTenant);
tenantId = savedTenant.getId();
+ tenantProfileId = savedTenant.getTenantProfileId();
- User tenantAdmin = new User();
- tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
- tenantAdmin.setTenantId(tenantId);
- tenantAdmin.setEmail(TENANT_ADMIN_EMAIL);
+ tenantAdminUser = new User();
+ tenantAdminUser.setAuthority(Authority.TENANT_ADMIN);
+ tenantAdminUser.setTenantId(tenantId);
+ tenantAdminUser.setEmail(TENANT_ADMIN_EMAIL);
- tenantAdmin = createUserAndLogin(tenantAdmin, TENANT_ADMIN_PASSWORD);
- tenantAdminUserId = tenantAdmin.getId();
- tenantAdminCustomerId = tenantAdmin.getCustomerId();
+ tenantAdminUser = createUserAndLogin(tenantAdminUser, TENANT_ADMIN_PASSWORD);
+ tenantAdminUserId = tenantAdminUser.getId();
+ tenantAdminCustomerId = tenantAdminUser.getCustomerId();
Customer customer = new Customer();
customer.setTitle("Customer");
@@ -792,6 +796,10 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
return readResponse(doDelete(urlTemplate, params).andExpect(status().isOk()), responseClass);
}
+ protected T doDeleteAsync(String urlTemplate, Class responseClass, String... params) throws Exception {
+ return readResponse(doDeleteAsync(urlTemplate, DEFAULT_TIMEOUT, params).andExpect(status().isOk()), responseClass);
+ }
+
protected ResultActions doPost(String urlTemplate, String... params) throws Exception {
MockHttpServletRequestBuilder postRequest = post(urlTemplate);
setJwtToken(postRequest);
@@ -824,6 +832,15 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
return mockMvc.perform(deleteRequest);
}
+ protected ResultActions doDeleteAsync(String urlTemplate, Long timeout, String... params) throws Exception {
+ MockHttpServletRequestBuilder deleteRequest = delete(urlTemplate, params);
+ setJwtToken(deleteRequest);
+// populateParams(deleteRequest, params);
+ MvcResult result = mockMvc.perform(deleteRequest).andReturn();
+ result.getAsyncResult(timeout);
+ return mockMvc.perform(asyncDispatch(result));
+ }
+
protected void populateParams(MockHttpServletRequestBuilder request, String... params) {
if (params != null && params.length > 0) {
Assert.assertEquals(0, params.length % 2);
diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java
index 05030f0091..36c5eacd36 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java
@@ -32,6 +32,7 @@ import org.springframework.test.context.ContextConfiguration;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityType;
+import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
@@ -39,6 +40,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.page.PageData;
+import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.alarm.AlarmDao;
import org.thingsboard.server.dao.service.DaoSqlTest;
@@ -156,8 +158,10 @@ public class AlarmControllerTest extends AbstractControllerTest {
Assert.assertEquals(alarm.getAckTs(), updatedAlarm.getAckTs());
foundAlarm = doGet("/api/alarm/info/" + updatedAlarm.getId(), AlarmInfo.class);
- testNotifyEntityAllOneTime(foundAlarm, foundAlarm.getId(), foundAlarm.getOriginator(),
- tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_ACK);
+
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(foundAlarm, customerDevice, tenantId,
+ customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_ACK, 1, 1, 1);
+ Mockito.reset(tbClusterService, auditLogService);
alarm = updatedAlarm;
alarm.setCleared(true);
@@ -168,8 +172,10 @@ public class AlarmControllerTest extends AbstractControllerTest {
Assert.assertEquals(alarm.getClearTs(), updatedAlarm.getClearTs());
foundAlarm = doGet("/api/alarm/info/" + updatedAlarm.getId(), AlarmInfo.class);
- testNotifyEntityAllOneTime(foundAlarm, foundAlarm.getId(), foundAlarm.getOriginator(),
- tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_CLEAR);
+
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(foundAlarm, customerDevice, tenantId,
+ customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_CLEAR, 1, 1, 1);
+ Mockito.reset(tbClusterService, auditLogService);
alarm = updatedAlarm;
alarm.setAssigneeId(tenantAdminUserId);
@@ -180,8 +186,10 @@ public class AlarmControllerTest extends AbstractControllerTest {
Assert.assertEquals(alarm.getAssignTs(), updatedAlarm.getAssignTs());
foundAlarm = doGet("/api/alarm/info/" + updatedAlarm.getId(), AlarmInfo.class);
- testNotifyEntityAllOneTime(foundAlarm, foundAlarm.getId(), foundAlarm.getOriginator(),
- tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_ASSIGNED);
+
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(foundAlarm, customerDevice, tenantId,
+ customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_ASSIGNED, 1, 1, 1);
+ Mockito.reset(tbClusterService, auditLogService);
alarm = updatedAlarm;
alarm.setAssigneeId(null);
@@ -192,8 +200,11 @@ public class AlarmControllerTest extends AbstractControllerTest {
Assert.assertEquals(alarm.getAssignTs(), updatedAlarm.getAssignTs());
foundAlarm = doGet("/api/alarm/info/" + updatedAlarm.getId(), AlarmInfo.class);
- testNotifyEntityAllOneTime(foundAlarm, foundAlarm.getId(), foundAlarm.getOriginator(),
- tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_UNASSIGNED);
+
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(foundAlarm, customerDevice, tenantId,
+ customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_UNASSIGNED, 1, 1, 1);
+ Mockito.reset(tbClusterService, auditLogService);
+
}
@Test
@@ -239,7 +250,7 @@ public class AlarmControllerTest extends AbstractControllerTest {
doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk());
- testNotifyEntityOneTimeMsgToEdgeServiceNever(new Alarm(alarm), alarm.getId(), alarm.getOriginator(),
+ testNotifyEntityAllOneTime(new Alarm(alarm), alarm.getId(), alarm.getOriginator(),
tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.DELETED);
}
@@ -252,7 +263,7 @@ public class AlarmControllerTest extends AbstractControllerTest {
doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk());
- testNotifyEntityOneTimeMsgToEdgeServiceNever(new Alarm(alarm), alarm.getId(), alarm.getOriginator(),
+ testNotifyEntityAllOneTime(new Alarm(alarm), alarm.getId(), alarm.getOriginator(),
tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.DELETED);
}
@@ -529,6 +540,100 @@ public class AlarmControllerTest extends AbstractControllerTest {
tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ALARM_UNASSIGNED);
}
+ @Test
+ public void testUnassignTenantUserAlarmOnUserRemoving() throws Exception {
+ loginDifferentTenant();
+
+ User user = new User();
+ user.setAuthority(Authority.TENANT_ADMIN);
+ user.setTenantId(tenantId);
+ user.setEmail("tenantForAssign@thingsboard.org");
+ User savedUser = createUser(user, "password");
+
+ Device device = createDevice("Different tenant device", "default", "differentTenantTest");
+
+ Alarm alarm = Alarm.builder()
+ .type(TEST_ALARM_TYPE)
+ .tenantId(savedDifferentTenant.getId())
+ .originator(device.getId())
+ .severity(AlarmSeverity.MAJOR)
+ .build();
+ alarm = doPost("/api/alarm", alarm, Alarm.class);
+ Assert.assertNotNull(alarm);
+
+ alarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
+ Assert.assertNotNull(alarm);
+
+ Mockito.reset(tbClusterService, auditLogService);
+ long beforeAssignmentTs = System.currentTimeMillis();
+
+ doPost("/api/alarm/" + alarm.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk());
+ AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
+ Assert.assertNotNull(foundAlarm);
+ Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId());
+ Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
+
+ beforeAssignmentTs = System.currentTimeMillis();
+
+ Mockito.reset(tbClusterService, auditLogService);
+
+ loginSysAdmin();
+
+ doDelete("/api/user/" + savedUser.getId().getId()).andExpect(status().isOk());
+
+ loginDifferentTenant();
+
+ foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
+ Assert.assertNotNull(foundAlarm);
+ Assert.assertNull(foundAlarm.getAssigneeId());
+ Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
+ }
+
+ @Test
+ public void testUnassignAlarmOnUserRemoving() throws Exception {
+ loginDifferentTenant();
+
+ User user = new User();
+ user.setAuthority(Authority.TENANT_ADMIN);
+ user.setTenantId(tenantId);
+ user.setEmail("tenantForAssign@thingsboard.org");
+ User savedUser = createUser(user, "password");
+
+ Device device = createDevice("Different tenant device", "default", "differentTenantTest");
+
+ Alarm alarm = Alarm.builder()
+ .type(TEST_ALARM_TYPE)
+ .tenantId(savedDifferentTenant.getId())
+ .originator(device.getId())
+ .severity(AlarmSeverity.MAJOR)
+ .build();
+ alarm = doPost("/api/alarm", alarm, Alarm.class);
+ Assert.assertNotNull(alarm);
+
+ alarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
+ Assert.assertNotNull(alarm);
+
+ Mockito.reset(tbClusterService, auditLogService);
+ long beforeAssignmentTs = System.currentTimeMillis();
+
+ doPost("/api/alarm/" + alarm.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk());
+ AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
+ Assert.assertNotNull(foundAlarm);
+ Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId());
+ Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
+
+ beforeAssignmentTs = System.currentTimeMillis();
+
+ Mockito.reset(tbClusterService, auditLogService);
+
+ doDelete("/api/user/" + savedUser.getId().getId()).andExpect(status().isOk());
+
+ foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
+ Assert.assertNotNull(foundAlarm);
+ Assert.assertNull(foundAlarm.getAssigneeId());
+ Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
+ }
+
@Test
public void testFindAlarmsViaCustomerUser() throws Exception {
loginCustomerUser();
diff --git a/application/src/test/java/org/thingsboard/server/controller/AssetControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AssetControllerTest.java
index 40b1707271..88a8b939b8 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AssetControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AssetControllerTest.java
@@ -50,7 +50,6 @@ import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.service.stats.DefaultRuleEngineStatisticsService;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import static org.hamcrest.Matchers.containsString;
@@ -114,8 +113,8 @@ public class AssetControllerTest extends AbstractControllerTest {
Asset savedAsset = doPost("/api/asset", asset, Asset.class);
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedAsset, savedAsset.getId(), savedAsset.getId(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED);
+ testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(), savedTenant.getId(),
+ tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED);
Assert.assertNotNull(savedAsset);
Assert.assertNotNull(savedAsset.getId());
@@ -130,8 +129,8 @@ public class AssetControllerTest extends AbstractControllerTest {
savedAsset.setName("My new asset");
doPost("/api/asset", savedAsset, Asset.class);
- testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED);
+ testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(), savedTenant.getId(),
+ tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED);
Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(foundAsset.getName(), savedAsset.getName());
@@ -229,7 +228,8 @@ public class AssetControllerTest extends AbstractControllerTest {
@Test
public void testFindAssetTypesByTenantId() throws Exception {
- List assets = new ArrayList<>();
+ AssetProfile assetProfile = createAssetProfile("typeB");
+ assetProfile = doPost("/api/assetProfile", assetProfile, AssetProfile.class);
Mockito.reset(tbClusterService, auditLogService);
@@ -238,24 +238,25 @@ public class AssetControllerTest extends AbstractControllerTest {
Asset asset = new Asset();
asset.setName("My asset B" + i);
asset.setType("typeB");
- assets.add(doPost("/api/asset", asset, Asset.class));
+ asset.setAssetProfileId(assetProfile.getId());
+ doPost("/api/asset", asset, Asset.class);
}
- testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Asset(), new Asset(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Asset(), new Asset(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, cntTime);
+ ActionType.ADDED, cntTime, cntTime, cntTime);
for (int i = 0; i < 7; i++) {
Asset asset = new Asset();
asset.setName("My asset C" + i);
asset.setType("typeC");
- assets.add(doPost("/api/asset", asset, Asset.class));
+ doPost("/api/asset", asset, Asset.class);
}
for (int i = 0; i < 9; i++) {
Asset asset = new Asset();
asset.setName("My asset A" + i);
asset.setType("typeA");
- assets.add(doPost("/api/asset", asset, Asset.class));
+ doPost("/api/asset", asset, Asset.class);
}
List assetTypes = doGetTyped("/api/asset/types",
new TypeReference>() {
@@ -280,7 +281,7 @@ public class AssetControllerTest extends AbstractControllerTest {
doDelete("/api/asset/" + savedAsset.getId().getId().toString())
.andExpect(status().isOk());
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedAsset, savedAsset.getId(), savedAsset.getId(),
+ testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.DELETED, savedAsset.getId().getId().toString());
@@ -342,7 +343,7 @@ public class AssetControllerTest extends AbstractControllerTest {
Asset savedAsset = doPost("/api/asset", asset, Asset.class);
Assert.assertEquals("default", savedAsset.getType());
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedAsset, savedAsset.getId(), savedAsset.getId(),
+ testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.ADDED);
}
@@ -380,9 +381,9 @@ public class AssetControllerTest extends AbstractControllerTest {
+ "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(savedCustomer.getId(), assignedAsset.getCustomerId());
- testNotifyEntityAllOneTime(assignedAsset, assignedAsset.getId(), assignedAsset.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(assignedAsset, assignedAsset.getId(), assignedAsset.getId(),
savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ASSIGNED_TO_CUSTOMER, assignedAsset.getId().toString(), savedCustomer.getId().toString(), savedCustomer.getTitle());
+ ActionType.ASSIGNED_TO_CUSTOMER, ActionType.UPDATED, assignedAsset.getId().toString(), savedCustomer.getId().toString(), savedCustomer.getTitle());
Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(savedCustomer.getId(), foundAsset.getCustomerId());
@@ -393,9 +394,9 @@ public class AssetControllerTest extends AbstractControllerTest {
doDelete("/api/customer/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(ModelConstants.NULL_UUID, unassignedAsset.getCustomerId().getId());
- testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(),
savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.UNASSIGNED_FROM_CUSTOMER, savedAsset.getId().toString(), savedCustomer.getId().toString(), savedCustomer.getTitle());
+ ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UPDATED, savedAsset.getId().toString(), savedCustomer.getId().toString(), savedCustomer.getTitle());
foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(ModelConstants.NULL_UUID, foundAsset.getCustomerId().getId());
@@ -415,9 +416,10 @@ public class AssetControllerTest extends AbstractControllerTest {
Customer publicCustomer = doGet("/api/customer/" + assignedAsset.getCustomerId(), Customer.class);
Assert.assertTrue(publicCustomer.isPublic());
- testNotifyEntityAllOneTime(assignedAsset, assignedAsset.getId(), assignedAsset.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(assignedAsset, assignedAsset.getId(), assignedAsset.getId(),
savedTenant.getId(), publicCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ASSIGNED_TO_CUSTOMER, assignedAsset.getId().toString(), publicCustomer.getId().toString(), publicCustomer.getTitle());
+ ActionType.ASSIGNED_TO_CUSTOMER, ActionType.UPDATED, assignedAsset.getId().toString(),
+ publicCustomer.getId().toString(), publicCustomer.getTitle());
Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(publicCustomer.getId(), foundAsset.getCustomerId());
@@ -428,9 +430,10 @@ public class AssetControllerTest extends AbstractControllerTest {
doDelete("/api/customer/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(ModelConstants.NULL_UUID, unassignedAsset.getCustomerId().getId());
- testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(),
savedTenant.getId(), publicCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.UNASSIGNED_FROM_CUSTOMER, savedAsset.getId().toString(), publicCustomer.getId().toString(), publicCustomer.getTitle());
+ ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UPDATED, savedAsset.getId().toString(),
+ publicCustomer.getId().toString(), publicCustomer.getTitle());
foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class);
Assert.assertEquals(ModelConstants.NULL_UUID, foundAsset.getCustomerId().getId());
@@ -513,7 +516,7 @@ public class AssetControllerTest extends AbstractControllerTest {
}
List loadedAssets = new ArrayList<>();
PageLink pageLink = new PageLink(23);
- PageData pageData = null;
+ PageData pageData;
do {
pageData = doGetTypedWithPageLink("/api/tenant/assets?",
new TypeReference>() {
@@ -524,14 +527,14 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Asset(), new Asset(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Asset(), new Asset(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, cntEntity);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity);
loadedAssets.removeIf(asset -> asset.getType().equals(DefaultRuleEngineStatisticsService.TB_SERVICE_QUEUE));
- Collections.sort(assets, idComparator);
- Collections.sort(loadedAssets, idComparator);
+ assets.sort(idComparator);
+ loadedAssets.sort(idComparator);
Assert.assertEquals(assets, loadedAssets);
}
@@ -574,8 +577,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsTitle1, idComparator);
- Collections.sort(loadedAssetsTitle1, idComparator);
+ assetsTitle1.sort(idComparator);
+ loadedAssetsTitle1.sort(idComparator);
Assert.assertEquals(assetsTitle1, loadedAssetsTitle1);
@@ -591,8 +594,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsTitle2, idComparator);
- Collections.sort(loadedAssetsTitle2, idComparator);
+ assetsTitle2.sort(idComparator);
+ loadedAssetsTitle2.sort(idComparator);
Assert.assertEquals(assetsTitle2, loadedAssetsTitle2);
@@ -661,8 +664,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsType1, idComparator);
- Collections.sort(loadedAssetsType1, idComparator);
+ assetsType1.sort(idComparator);
+ loadedAssetsType1.sort(idComparator);
Assert.assertEquals(assetsType1, loadedAssetsType1);
@@ -678,8 +681,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsType2, idComparator);
- Collections.sort(loadedAssetsType2, idComparator);
+ assetsType2.sort(idComparator);
+ loadedAssetsType2.sort(idComparator);
Assert.assertEquals(assetsType2, loadedAssetsType2);
@@ -738,8 +741,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assets, idComparator);
- Collections.sort(loadedAssets, idComparator);
+ assets.sort(idComparator);
+ loadedAssets.sort(idComparator);
Assert.assertEquals(assets, loadedAssets);
}
@@ -791,8 +794,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsTitle1, idComparator);
- Collections.sort(loadedAssetsTitle1, idComparator);
+ assetsTitle1.sort(idComparator);
+ loadedAssetsTitle1.sort(idComparator);
Assert.assertEquals(assetsTitle1, loadedAssetsTitle1);
@@ -808,8 +811,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsTitle2, idComparator);
- Collections.sort(loadedAssetsTitle2, idComparator);
+ assetsTitle2.sort(idComparator);
+ loadedAssetsTitle2.sort(idComparator);
Assert.assertEquals(assetsTitle2, loadedAssetsTitle2);
@@ -887,8 +890,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsType1, idComparator);
- Collections.sort(loadedAssetsType1, idComparator);
+ assetsType1.sort(idComparator);
+ loadedAssetsType1.sort(idComparator);
Assert.assertEquals(assetsType1, loadedAssetsType1);
@@ -904,8 +907,8 @@ public class AssetControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(assetsType2, idComparator);
- Collections.sort(loadedAssetsType2, idComparator);
+ assetsType2.sort(idComparator);
+ loadedAssetsType2.sort(idComparator);
Assert.assertEquals(assetsType2, loadedAssetsType2);
diff --git a/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java
index c84b058cc7..38420c3e32 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AssetProfileControllerTest.java
@@ -355,7 +355,7 @@ public class AssetProfileControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new AssetProfile(), new AssetProfile(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, ActionType.ADDED, cntEntity, cntEntity, cntEntity);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity);
Mockito.reset(tbClusterService, auditLogService);
List loadedAssetProfiles = new ArrayList<>();
@@ -384,7 +384,7 @@ public class AssetProfileControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(loadedAssetProfiles.get(0), loadedAssetProfiles.get(0),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.DELETED, ActionType.DELETED, cntEntity, cntEntity, cntEntity, loadedAssetProfiles.get(0).getId().getId().toString());
+ ActionType.DELETED, cntEntity, cntEntity, cntEntity, loadedAssetProfiles.get(0).getId().getId().toString());
pageLink = new PageLink(17);
pageData = doGetTypedWithPageLink("/api/assetProfiles?",
diff --git a/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java
index 125e533471..f5c33debb2 100644
--- a/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/CustomerControllerTest.java
@@ -117,8 +117,8 @@ public class CustomerControllerTest extends AbstractControllerTest {
Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedCustomer, savedCustomer.getId(), savedCustomer.getId(),
- savedCustomer.getTenantId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
+ testNotifyEntityAllOneTime(savedCustomer, savedCustomer.getId(), savedCustomer.getId(), savedCustomer.getTenantId(),
+ new CustomerId(CustomerId.NULL_UUID), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.ADDED);
Assert.assertNotNull(savedCustomer);
@@ -242,7 +242,7 @@ public class CustomerControllerTest extends AbstractControllerTest {
doDelete("/api/customer/" + savedCustomer.getId().getId().toString())
.andExpect(status().isOk());
- testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(savedCustomer, savedCustomer.getId(),
+ testNotifyEntityBroadcastEntityStateChangeEventOneTime(savedCustomer, savedCustomer.getId(),
savedCustomer.getId(), savedCustomer.getTenantId(), savedCustomer.getId(), tenantAdmin.getId(),
tenantAdmin.getEmail(), ActionType.DELETED, savedCustomer.getId().getId().toString());
}
@@ -272,7 +272,7 @@ public class CustomerControllerTest extends AbstractControllerTest {
doDelete("/api/customer/" + savedCustomer.getId().getId().toString())
.andExpect(status().isOk());
- testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(savedCustomer, savedCustomer.getId(),
+ testNotifyEntityBroadcastEntityStateChangeEventOneTime(savedCustomer, savedCustomer.getId(),
savedCustomer.getId(), savedCustomer.getTenantId(), savedCustomer.getId(), tenantAdmin.getId(),
tenantAdmin.getEmail(), ActionType.DELETED, savedCustomer.getId().getId().toString());
@@ -332,9 +332,9 @@ public class CustomerControllerTest extends AbstractControllerTest {
}
List customers = Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS);
- testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Customer(), new Customer(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Customer(), new Customer(),
tenantId, tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, cntEntity);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity);
List loadedCustomers = new ArrayList<>(135);
PageLink pageLink = new PageLink(23);
diff --git a/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java
index 9f8e63e3b0..6f0d6f9465 100644
--- a/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/DashboardControllerTest.java
@@ -46,7 +46,6 @@ import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DaoSqlTest;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import static org.hamcrest.Matchers.containsString;
@@ -154,7 +153,7 @@ public class DashboardControllerTest extends AbstractControllerTest {
doDelete("/api/dashboard/" + savedDashboard.getId().getId().toString()).andExpect(status().isOk());
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedDashboard, savedDashboard.getId(), savedDashboard.getId(),
+ testNotifyEntityAllOneTime(savedDashboard, savedDashboard.getId(), savedDashboard.getId(),
savedDashboard.getTenantId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.DELETED,
savedDashboard.getId().getId().toString());
@@ -198,7 +197,7 @@ public class DashboardControllerTest extends AbstractControllerTest {
testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(assignedDashboard, assignedDashboard.getId(), assignedDashboard.getId(),
savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ASSIGNED_TO_CUSTOMER,
- assignedDashboard .getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
+ ActionType.UPDATED, assignedDashboard.getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
Dashboard foundDashboard = doGet("/api/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
Assert.assertTrue(foundDashboard.getAssignedCustomers().contains(savedCustomer.toShortCustomerInfo()));
@@ -210,7 +209,7 @@ public class DashboardControllerTest extends AbstractControllerTest {
testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(assignedDashboard, assignedDashboard.getId(), assignedDashboard.getId(),
savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UNASSIGNED_FROM_CUSTOMER,
- unassignedDashboard.getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
+ ActionType.UPDATED, unassignedDashboard.getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
Assert.assertTrue(unassignedDashboard.getAssignedCustomers() == null || unassignedDashboard.getAssignedCustomers().isEmpty());
@@ -241,7 +240,7 @@ public class DashboardControllerTest extends AbstractControllerTest {
testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(assignedDashboard, assignedDashboard.getId(), assignedDashboard.getId(),
savedTenant.getId(), publicCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ASSIGNED_TO_CUSTOMER,
- assignedDashboard .getId().getId().toString(), publicCustomer.getId().getId().toString(), publicCustomer.getTitle());
+ ActionType.UPDATED, assignedDashboard .getId().getId().toString(), publicCustomer.getId().getId().toString(), publicCustomer.getTitle());
Dashboard foundDashboard = doGet("/api/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
Assert.assertTrue(foundDashboard.getAssignedCustomers().contains(publicCustomer.toShortCustomerInfo()));
@@ -253,7 +252,7 @@ public class DashboardControllerTest extends AbstractControllerTest {
testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(assignedDashboard, assignedDashboard.getId(), assignedDashboard.getId(),
savedTenant.getId(), publicCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UNASSIGNED_FROM_CUSTOMER,
- unassignedDashboard.getId().getId().toString(), publicCustomer.getId().getId().toString(), publicCustomer.getTitle());
+ ActionType.UPDATED, unassignedDashboard.getId().getId().toString(), publicCustomer.getId().getId().toString(), publicCustomer.getTitle());
Assert.assertTrue(unassignedDashboard.getAssignedCustomers() == null || unassignedDashboard.getAssignedCustomers().isEmpty());
@@ -339,9 +338,9 @@ public class DashboardControllerTest extends AbstractControllerTest {
dashboards.add(new DashboardInfo(doPost("/api/dashboard", dashboard, Dashboard.class)));
}
- testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Dashboard(), new Dashboard(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Dashboard(), new Dashboard(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, cntEntity);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity);
List loadedDashboards = new ArrayList<>();
PageLink pageLink = new PageLink(24);
@@ -356,8 +355,8 @@ public class DashboardControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(dashboards, idComparator);
- Collections.sort(loadedDashboards, idComparator);
+ dashboards.sort(idComparator);
+ loadedDashboards.sort(idComparator);
Assert.assertEquals(dashboards, loadedDashboards);
}
@@ -400,8 +399,8 @@ public class DashboardControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(dashboardsTitle1, idComparator);
- Collections.sort(loadedDashboardsTitle1, idComparator);
+ dashboardsTitle1.sort(idComparator);
+ loadedDashboardsTitle1.sort(idComparator);
Assert.assertEquals(dashboardsTitle1, loadedDashboardsTitle1);
@@ -417,8 +416,8 @@ public class DashboardControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(dashboardsTitle2, idComparator);
- Collections.sort(loadedDashboardsTitle2, idComparator);
+ dashboardsTitle2.sort(idComparator);
+ loadedDashboardsTitle2.sort(idComparator);
Assert.assertEquals(dashboardsTitle2, loadedDashboardsTitle2);
@@ -429,9 +428,9 @@ public class DashboardControllerTest extends AbstractControllerTest {
.andExpect(status().isOk());
}
- testNotifyManyEntityManyTimeMsgToEdgeServiceNeverAdditionalInfoAny(new Dashboard(), new Dashboard(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAnyAdditionalInfoAny(new Dashboard(), new Dashboard(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.DELETED, cntEntity, 1);
+ ActionType.DELETED, ActionType.DELETED, cntEntity, cntEntity, 1);
pageLink = new PageLink(4, 0, title1);
pageData = doGetTypedWithPageLink("/api/tenant/dashboards?",
@@ -474,7 +473,7 @@ public class DashboardControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Dashboard(), new Dashboard(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, ActionType.ASSIGNED_TO_CUSTOMER, cntEntity, cntEntity, cntEntity*2);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity*2);
List loadedDashboards = new ArrayList<>();
PageLink pageLink = new PageLink(21);
@@ -489,8 +488,8 @@ public class DashboardControllerTest extends AbstractControllerTest {
}
} while (pageData.hasNext());
- Collections.sort(dashboards, idComparator);
- Collections.sort(loadedDashboards, idComparator);
+ dashboards.sort(idComparator);
+ loadedDashboards.sort(idComparator);
Assert.assertEquals(dashboards, loadedDashboards);
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java
new file mode 100644
index 0000000000..36a4365544
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java
@@ -0,0 +1,340 @@
+/**
+ * Copyright © 2016-2023 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.AdditionalAnswers;
+import org.mockito.Mockito;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.common.util.ThingsBoardExecutors;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.DeviceProfile;
+import org.thingsboard.server.common.data.DeviceProfileType;
+import org.thingsboard.server.common.data.DeviceTransportType;
+import org.thingsboard.server.common.data.Tenant;
+import org.thingsboard.server.common.data.User;
+import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
+import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
+import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;
+import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
+import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
+import org.thingsboard.server.common.data.id.DeviceProfileId;
+import org.thingsboard.server.common.data.page.PageData;
+import org.thingsboard.server.common.data.security.Authority;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.common.data.security.DeviceCredentialsType;
+import org.thingsboard.server.dao.device.DeviceDao;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.COAP;
+import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.COAPS;
+import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.DOCKER;
+import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTP;
+import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTPS;
+import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTT;
+import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTTS;
+
+@TestPropertySource(properties = {
+ "device.connectivity.https.enabled=true",
+ "device.connectivity.mqtts.enabled=true",
+ "device.connectivity.coaps.enabled=true",
+})
+@ContextConfiguration(classes = {DeviceConnectivityControllerTest.Config.class})
+@DaoSqlTest
+public class DeviceConnectivityControllerTest extends AbstractControllerTest {
+ static final TypeReference> PAGE_DATA_DEVICE_TYPE_REF = new TypeReference<>() {
+ };
+
+ private static final String DEVICE_TELEMETRY_TOPIC = "v1/devices/customTopic";
+ private static final String CHECK_DOCUMENTATION = "Check documentation";
+
+ ListeningExecutorService executor;
+
+ private Tenant savedTenant;
+ private User tenantAdmin;
+ private DeviceProfileId mqttDeviceProfileId;
+ private DeviceProfileId coapDeviceProfileId;
+
+ static class Config {
+ @Bean
+ @Primary
+ public DeviceDao deviceDao(DeviceDao deviceDao) {
+ return Mockito.mock(DeviceDao.class, AdditionalAnswers.delegatesTo(deviceDao));
+ }
+ }
+
+ @Before
+ public void beforeTest() throws Exception {
+ executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(8, getClass()));
+
+ loginSysAdmin();
+
+ Tenant tenant = new Tenant();
+ tenant.setTitle("My tenant");
+ savedTenant = doPost("/api/tenant", tenant, Tenant.class);
+ Assert.assertNotNull(savedTenant);
+
+ tenantAdmin = new User();
+ tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
+ tenantAdmin.setTenantId(savedTenant.getId());
+ tenantAdmin.setEmail("tenant2@thingsboard.org");
+ tenantAdmin.setFirstName("Joe");
+ tenantAdmin.setLastName("Downs");
+
+ tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
+
+ DeviceProfile mqttProfile = new DeviceProfile();
+ mqttProfile.setName("Mqtt device profile");
+ mqttProfile.setType(DeviceProfileType.DEFAULT);
+ mqttProfile.setTransportType(DeviceTransportType.MQTT);
+ DeviceProfileData deviceProfileData = new DeviceProfileData();
+ deviceProfileData.setConfiguration(new DefaultDeviceProfileConfiguration());
+ MqttDeviceProfileTransportConfiguration transportConfiguration = new MqttDeviceProfileTransportConfiguration();
+ transportConfiguration.setDeviceTelemetryTopic(DEVICE_TELEMETRY_TOPIC);
+ deviceProfileData.setTransportConfiguration(transportConfiguration);
+ mqttProfile.setProfileData(deviceProfileData);
+ mqttProfile.setDefault(false);
+ mqttProfile.setDefaultRuleChainId(null);
+
+ mqttDeviceProfileId = doPost("/api/deviceProfile", mqttProfile, DeviceProfile.class).getId();
+
+ DeviceProfile coapProfile = new DeviceProfile();
+ coapProfile.setName("Coap device profile");
+ coapProfile.setType(DeviceProfileType.DEFAULT);
+ coapProfile.setTransportType(DeviceTransportType.COAP);
+ DeviceProfileData deviceProfileData2 = new DeviceProfileData();
+ deviceProfileData2.setConfiguration(new DefaultDeviceProfileConfiguration());
+ deviceProfileData2.setTransportConfiguration(new CoapDeviceProfileTransportConfiguration());
+ coapProfile.setProfileData(deviceProfileData);
+ coapProfile.setDefault(false);
+ coapProfile.setDefaultRuleChainId(null);
+
+ coapDeviceProfileId = doPost("/api/deviceProfile", coapProfile, DeviceProfile.class).getId();
+ }
+
+ @After
+ public void afterTest() throws Exception {
+ executor.shutdownNow();
+
+ loginSysAdmin();
+
+ doDelete("/api/tenant/" + savedTenant.getId().getId())
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ public void testFetchPublishTelemetryCommandsForDefaultDevice() throws Exception {
+ Device device = new Device();
+ device.setName("My device");
+ device.setType("default");
+ Device savedDevice = doPost("/api/device", device, Device.class);
+ JsonNode commands =
+ doGetTyped("/api/device-connectivity/" + savedDevice.getId().getId(), new TypeReference<>() {
+ });
+
+ DeviceCredentials credentials =
+ doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
+
+ assertThat(commands).hasSize(3);
+ JsonNode httpCommands = commands.get(HTTP);
+ assertThat(httpCommands.get(HTTP).asText()).isEqualTo(String.format("curl -v -X POST http://localhost:8080/api/v1/%s/telemetry " +
+ "--header Content-Type:application/json --data \"{temperature:25}\"",
+ credentials.getCredentialsId()));
+ assertThat(httpCommands.get(HTTPS).asText()).isEqualTo(String.format("curl -v -X POST https://localhost:443/api/v1/%s/telemetry " +
+ "--header Content-Type:application/json --data \"{temperature:25}\"",
+ credentials.getCredentialsId()));
+
+
+ JsonNode mqttCommands = commands.get(MQTT);
+ assertThat(mqttCommands.get(MQTT).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 -h localhost -p 1883 -t v1/devices/me/telemetry " +
+ "-u %s -m \"{temperature:25}\"",
+ credentials.getCredentialsId()));
+ assertThat(mqttCommands.get(MQTTS).get(0).asText()).isEqualTo("curl -f -S -o tb-server-chain.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download");
+ assertThat(mqttCommands.get(MQTTS).get(1).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 --cafile tb-server-chain.pem -h localhost -p 8883 " +
+ "-t v1/devices/me/telemetry -u %s -m \"{temperature:25}\"", credentials.getCredentialsId()));
+
+ JsonNode dockerMqttCommands = commands.get(MQTT).get(DOCKER);
+ assertThat(dockerMqttCommands.get(MQTT).asText()).isEqualTo(String.format("docker run --rm -it thingsboard/mosquitto-clients mosquitto_pub -d -q 1 -h localhost" +
+ " -p 1883 -t v1/devices/me/telemetry -u %s -m \"{temperature:25}\"",
+ credentials.getCredentialsId()));
+ assertThat(dockerMqttCommands.get(MQTTS).asText()).isEqualTo(String.format("docker run --rm -it thingsboard/mosquitto-clients " +
+ "/bin/sh -c \"curl -f -S -o tb-server-chain.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download && " +
+ "mosquitto_pub -d -q 1 --cafile tb-server-chain.pem -h localhost -p 8883 -t v1/devices/me/telemetry -u %s -m \"{temperature:25}\"\"",
+ credentials.getCredentialsId()));
+
+ JsonNode linuxCoapCommands = commands.get(COAP);
+ assertThat(linuxCoapCommands.get(COAP).asText()).isEqualTo(String.format("coap-client -m POST coap://localhost:5683/api/v1/%s/telemetry " +
+ "-t json -e \"{temperature:25}\"", credentials.getCredentialsId()));
+ assertThat(linuxCoapCommands.get(COAPS).asText()).isEqualTo(String.format("coap-client-openssl -m POST coaps://localhost:5684/api/v1/%s/telemetry" +
+ " -t json -e \"{temperature:25}\"", credentials.getCredentialsId()));
+ }
+
+ @Test
+ public void testFetchPublishTelemetryCommandsForMqttDeviceWithAccessToken() throws Exception {
+ Device device = new Device();
+ device.setName("My device");
+ device.setDeviceProfileId(mqttDeviceProfileId);
+
+ Device savedDevice = doPost("/api/device", device, Device.class);
+ DeviceCredentials credentials =
+ doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
+
+ JsonNode commands =
+ doGetTyped("/api/device-connectivity/" + savedDevice.getId().getId(), new TypeReference<>() {
+ });
+ assertThat(commands).hasSize(1);
+
+ JsonNode mqttCommands = commands.get(MQTT);
+ assertThat(mqttCommands.get(MQTT).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 -h localhost -p 1883 -t %s " +
+ "-u %s -m \"{temperature:25}\"", DEVICE_TELEMETRY_TOPIC, credentials.getCredentialsId()));
+ assertThat(mqttCommands.get(MQTTS).get(0).asText()).isEqualTo("curl -f -S -o tb-server-chain.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download");
+ assertThat(mqttCommands.get(MQTTS).get(1).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 --cafile tb-server-chain.pem -h localhost -p 8883 " +
+ "-t %s -u %s -m \"{temperature:25}\"", DEVICE_TELEMETRY_TOPIC, credentials.getCredentialsId()));
+
+ JsonNode dockerMqttCommands = commands.get(MQTT).get(DOCKER);
+ assertThat(dockerMqttCommands.get(MQTT).asText()).isEqualTo(String.format("docker run --rm -it thingsboard/mosquitto-clients mosquitto_pub -d -q 1 -h localhost" +
+ " -p 1883 -t %s -u %s -m \"{temperature:25}\"",
+ DEVICE_TELEMETRY_TOPIC, credentials.getCredentialsId()));
+ assertThat(dockerMqttCommands.get(MQTTS).asText()).isEqualTo(String.format("docker run --rm -it thingsboard/mosquitto-clients " +
+ "/bin/sh -c \"curl -f -S -o tb-server-chain.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download && " +
+ "mosquitto_pub -d -q 1 --cafile tb-server-chain.pem -h localhost -p 8883 -t %s -u %s -m \"{temperature:25}\"\"",
+ DEVICE_TELEMETRY_TOPIC, credentials.getCredentialsId()));
+ }
+
+ @Test
+ public void testFetchPublishTelemetryCommandsForDeviceWithMqttBasicCreds() throws Exception {
+ Device device = new Device();
+ device.setName("My device");
+ device.setDeviceProfileId(mqttDeviceProfileId);
+
+ Device savedDevice = doPost("/api/device", device, Device.class);
+ DeviceCredentials credentials =
+ doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
+ credentials.setCredentialsId(null);
+ credentials.setCredentialsType(DeviceCredentialsType.MQTT_BASIC);
+ BasicMqttCredentials basicMqttCredentials = new BasicMqttCredentials();
+ String clientId = "testClientId";
+ String userName = "testUsername";
+ String password = "testPassword";
+ basicMqttCredentials.setClientId(clientId);
+ basicMqttCredentials.setUserName(userName);
+ basicMqttCredentials.setPassword(password);
+ credentials.setCredentialsValue(JacksonUtil.toString(basicMqttCredentials));
+ doPost("/api/device/credentials", credentials)
+ .andExpect(status().isOk());
+
+ JsonNode commands =
+ doGetTyped("/api/device-connectivity/" + savedDevice.getId().getId(), new TypeReference<>() {
+ });
+ assertThat(commands).hasSize(1);
+
+ JsonNode mqttCommands = commands.get(MQTT);
+ assertThat(mqttCommands.get(MQTT).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 -h localhost -p 1883 -t %s " +
+ "-i %s -u %s -P %s -m \"{temperature:25}\"", DEVICE_TELEMETRY_TOPIC, clientId, userName, password));
+ assertThat(mqttCommands.get(MQTTS).get(0).asText()).isEqualTo("curl -f -S -o tb-server-chain.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download");
+ assertThat(mqttCommands.get(MQTTS).get(1).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 --cafile tb-server-chain.pem -h localhost -p 8883 " +
+ "-t %s -i %s -u %s -P %s -m \"{temperature:25}\"", DEVICE_TELEMETRY_TOPIC, clientId, userName, password));
+
+ JsonNode dockerMqttCommands = commands.get(MQTT).get(DOCKER);
+ assertThat(dockerMqttCommands.get(MQTT).asText()).isEqualTo(String.format("docker run --rm -it thingsboard/mosquitto-clients mosquitto_pub -d -q 1 -h localhost" +
+ " -p 1883 -t %s -i %s -u %s -P %s -m \"{temperature:25}\"",
+ DEVICE_TELEMETRY_TOPIC, clientId, userName, password));
+ assertThat(dockerMqttCommands.get(MQTTS).asText()).isEqualTo(String.format("docker run --rm -it thingsboard/mosquitto-clients " +
+ "/bin/sh -c \"curl -f -S -o tb-server-chain.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download && " +
+ "mosquitto_pub -d -q 1 --cafile tb-server-chain.pem -h localhost -p 8883 -t %s -i %s -u %s -P %s -m \"{temperature:25}\"\"",
+ DEVICE_TELEMETRY_TOPIC, clientId, userName, password));
+ }
+
+ @Test
+ public void testFetchPublishTelemetryCommandsForDeviceWithX509Creds() throws Exception {
+ Device device = new Device();
+ device.setName("My device");
+ device.setDeviceProfileId(mqttDeviceProfileId);
+
+ Device savedDevice = doPost("/api/device", device, Device.class);
+ DeviceCredentials credentials =
+ doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
+ credentials.setCredentialsId(null);
+ credentials.setCredentialsType(DeviceCredentialsType.X509_CERTIFICATE);
+ credentials.setCredentialsValue("testValue");
+ doPost("/api/device/credentials", credentials)
+ .andExpect(status().isOk());
+
+ JsonNode commands =
+ doGetTyped("/api/device-connectivity/" + savedDevice.getId().getId(), new TypeReference<>() {
+ });
+ assertThat(commands).hasSize(1);
+ assertThat(commands.get(MQTT).get(MQTTS).asText()).isEqualTo(CHECK_DOCUMENTATION);
+ assertThat(commands.get(MQTT).get(DOCKER)).isNull();
+ }
+
+ @Test
+ public void testFetchPublishTelemetryCommandsForCoapDevice() throws Exception {
+ Device device = new Device();
+ device.setName("My device");
+ device.setDeviceProfileId(coapDeviceProfileId);
+
+ Device savedDevice = doPost("/api/device", device, Device.class);
+ DeviceCredentials credentials =
+ doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
+
+ JsonNode commands =
+ doGetTyped("/api/device-connectivity/" + savedDevice.getId().getId(), new TypeReference<>() {
+ });
+ assertThat(commands).hasSize(1);
+
+ JsonNode linuxCommands = commands.get(COAP);
+ assertThat(linuxCommands.get(COAP).asText()).isEqualTo(String.format("coap-client -m POST coap://localhost:5683/api/v1/%s/telemetry -t json -e \"{temperature:25}\"",
+ credentials.getCredentialsId()));
+ assertThat(linuxCommands.get(COAPS).asText()).isEqualTo(String.format("coap-client-openssl -m POST coaps://localhost:5684/api/v1/%s/telemetry -t json -e \"{temperature:25}\"",
+ credentials.getCredentialsId()));
+ }
+
+ @Test
+ public void testFetchPublishTelemetryCommandsForCoapDeviceWithX509Creds() throws Exception {
+ Device device = new Device();
+ device.setName("My device");
+ device.setDeviceProfileId(coapDeviceProfileId);
+
+ Device savedDevice = doPost("/api/device", device, Device.class);
+ DeviceCredentials credentials =
+ doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
+ credentials.setCredentialsId(null);
+ credentials.setCredentialsType(DeviceCredentialsType.X509_CERTIFICATE);
+ credentials.setCredentialsValue("testValue");
+ doPost("/api/device/credentials", credentials)
+ .andExpect(status().isOk());
+
+ JsonNode commands =
+ doGetTyped("/api/device-connectivity/" + savedDevice.getId().getId(), new TypeReference<>() {
+ });
+ assertThat(commands).hasSize(1);
+ assertThat(commands.get(COAP).get(COAPS).asText()).isEqualTo(CHECK_DOCUMENTATION);
+ }
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java
index 11d11eccdd..5cc9c3dc91 100644
--- a/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java
@@ -156,9 +156,8 @@ public class DeviceControllerTest extends AbstractControllerTest {
Device oldDevice = new Device(savedDevice);
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedDevice, savedDevice.getId(), savedDevice.getId(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED);
+ testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(),
+ tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED);
testNotificationUpdateGatewayNever();
Assert.assertNotNull(savedDevice);
@@ -212,7 +211,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
Device oldDevice = new Device(savedDevice);
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedDevice, savedDevice.getId(), savedDevice.getId(),
+ testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.ADDED);
testNotificationUpdateGatewayNever();
@@ -244,6 +243,53 @@ public class DeviceControllerTest extends AbstractControllerTest {
testNotificationUpdateGatewayOneTime(savedDevice, oldDevice);
}
+ @Test
+ public void testSaveDeviceWithCredentials_CredentialsIsNull() throws Exception {
+ Device device = new Device();
+ device.setName("My device");
+ device.setType("default");
+
+ SaveDeviceWithCredentialsRequest saveRequest = new SaveDeviceWithCredentialsRequest(device, null);
+ doPost("/api/device-with-credentials", saveRequest).andExpect(status().isBadRequest())
+ .andExpect(statusReason(containsString("Validation error: credentials must not be null")));
+ }
+
+ @Test
+ public void testSaveDeviceWithCredentials_DeviceIsNull() throws Exception {
+ String testToken = "TEST_TOKEN";
+
+ DeviceCredentials deviceCredentials = new DeviceCredentials();
+ deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
+ deviceCredentials.setCredentialsId(testToken);
+
+ SaveDeviceWithCredentialsRequest saveRequest = new SaveDeviceWithCredentialsRequest(null, deviceCredentials);
+ doPost("/api/device-with-credentials", saveRequest).andExpect(status().isBadRequest())
+ .andExpect(statusReason(containsString("Validation error: device must not be null")));
+ }
+
+ @Test
+ public void testSaveDeviceWithCredentials_WithExistingName() throws Exception {
+ String testToken = "TEST_TOKEN";
+
+ Device device = new Device();
+ device.setName("My device");
+ device.setType("default");
+
+ DeviceCredentials deviceCredentials = new DeviceCredentials();
+ deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN);
+ deviceCredentials.setCredentialsId(testToken);
+
+ SaveDeviceWithCredentialsRequest saveRequest = new SaveDeviceWithCredentialsRequest(device, deviceCredentials);
+
+ Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService);
+
+ Device savedDevice = readResponse(doPost("/api/device-with-credentials", saveRequest).andExpect(status().isOk()), Device.class);
+ Assert.assertNotNull(savedDevice);
+
+ doPost("/api/device-with-credentials", saveRequest).andExpect(status().isBadRequest())
+ .andExpect(statusReason(containsString("Device with such name already exists!")));
+ }
+
@Test
public void saveDeviceWithViolationOfValidation() throws Exception {
Device device = new Device();
@@ -389,6 +435,9 @@ public class DeviceControllerTest extends AbstractControllerTest {
@Test
public void testFindDeviceTypesByTenantId() throws Exception {
+ DeviceProfile deviceProfile = createDeviceProfile("typeB");
+ deviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
+
List devices = new ArrayList<>();
int cntEntity = 3;
@@ -399,12 +448,13 @@ public class DeviceControllerTest extends AbstractControllerTest {
Device device = new Device();
device.setName("My device B" + i);
device.setType("typeB");
+ device.setDeviceProfileId(deviceProfile.getId());
devices.add(doPost("/api/device", device, Device.class));
}
- testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Device(), new Device(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Device(), new Device(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, cntEntity);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity);
testNotificationUpdateGatewayNever();
for (int i = 0; i < 7; i++) {
@@ -444,7 +494,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
doDelete("/api/device/" + savedDevice.getId().getId())
.andExpect(status().isOk());
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(),
+ testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(),
tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.DELETED, savedDevice.getId().getId().toString());
testNotificationDeleteGatewayOneTime(savedDevice);
@@ -464,7 +514,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
Device savedDevice = doPost("/api/device", device, Device.class);
Assert.assertEquals("default", savedDevice.getType());
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedDevice, savedDevice.getId(), savedDevice.getId(),
+ testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.ADDED);
testNotificationUpdateGatewayNever();
@@ -504,9 +554,9 @@ public class DeviceControllerTest extends AbstractControllerTest {
+ "/device/" + savedDevice.getId().getId(), Device.class);
Assert.assertEquals(savedCustomer.getId(), assignedDevice.getCustomerId());
- testNotifyEntityAllOneTime(assignedDevice, assignedDevice.getId(), assignedDevice.getId(), savedTenant.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(assignedDevice, assignedDevice.getId(), assignedDevice.getId(), savedTenant.getId(),
savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ASSIGNED_TO_CUSTOMER,
- assignedDevice.getId().getId().toString(), savedCustomer.getId().getId().toString(),
+ ActionType.UPDATED, assignedDevice.getId().getId().toString(), savedCustomer.getId().getId().toString(),
savedCustomer.getTitle());
testNotificationUpdateGatewayNever();
@@ -519,9 +569,9 @@ public class DeviceControllerTest extends AbstractControllerTest {
doDelete("/api/customer/device/" + savedDevice.getId().getId(), Device.class);
Assert.assertEquals(ModelConstants.NULL_UUID, unassignedDevice.getCustomerId().getId());
- testNotifyEntityAllOneTime(unassignedDevice, unassignedDevice.getId(), unassignedDevice.getId(), savedTenant.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(unassignedDevice, unassignedDevice.getId(), unassignedDevice.getId(), savedTenant.getId(),
savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UNASSIGNED_FROM_CUSTOMER,
- unassignedDevice.getId().getId().toString(), savedCustomer.getId().getId().toString(),
+ ActionType.UPDATED, unassignedDevice.getId().getId().toString(), savedCustomer.getId().getId().toString(),
savedCustomer.getTitle());
testNotificationDeleteGatewayNever();
@@ -543,9 +593,9 @@ public class DeviceControllerTest extends AbstractControllerTest {
Customer publicCustomer = doGet("/api/customer/" + assignedDevice.getCustomerId(), Customer.class);
Assert.assertTrue(publicCustomer.isPublic());
- testNotifyEntityAllOneTime(assignedDevice, assignedDevice.getId(), assignedDevice.getId(), savedTenant.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(assignedDevice, assignedDevice.getId(), assignedDevice.getId(), savedTenant.getId(),
publicCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ASSIGNED_TO_CUSTOMER,
- assignedDevice.getId().getId().toString(), publicCustomer.getId().getId().toString(),
+ ActionType.UPDATED, assignedDevice.getId().getId().toString(), publicCustomer.getId().getId().toString(),
publicCustomer.getTitle());
testNotificationUpdateGatewayNever();
@@ -558,9 +608,9 @@ public class DeviceControllerTest extends AbstractControllerTest {
doDelete("/api/customer/device/" + savedDevice.getId().getId(), Device.class);
Assert.assertEquals(ModelConstants.NULL_UUID, unassignedDevice.getCustomerId().getId());
- testNotifyEntityAllOneTime(unassignedDevice, unassignedDevice.getId(), unassignedDevice.getId(), savedTenant.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(unassignedDevice, unassignedDevice.getId(), unassignedDevice.getId(), savedTenant.getId(),
publicCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UNASSIGNED_FROM_CUSTOMER,
- unassignedDevice.getId().getId().toString(), publicCustomer.getId().getId().toString(),
+ ActionType.UPDATED, unassignedDevice.getId().getId().toString(), publicCustomer.getId().getId().toString(),
publicCustomer.getTitle());
testNotificationDeleteGatewayNever();
@@ -795,9 +845,9 @@ public class DeviceControllerTest extends AbstractControllerTest {
List devices = Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS);
- testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Device(), new Device(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Device(), new Device(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, cntEntity);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity);
testNotificationUpdateGatewayNever();
List loadedDevices = new ArrayList<>(cntEntity);
@@ -818,9 +868,9 @@ public class DeviceControllerTest extends AbstractControllerTest {
deleteEntitiesAsync("/api/device/", loadedDevices, executor).get(TIMEOUT, TimeUnit.SECONDS);
- testNotifyManyEntityManyTimeMsgToEdgeServiceNeverAdditionalInfoAny(new Device(), new Device(),
+ testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAnyAdditionalInfoAny(new Device(), new Device(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.DELETED, cntEntity, 1);
+ ActionType.DELETED, ActionType.DELETED, cntEntity, cntEntity,1);
testNotificationUpdateGatewayNever();
}
@@ -1005,7 +1055,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Device(), new Device(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, ActionType.ASSIGNED_TO_CUSTOMER, cntEntity, cntEntity, cntEntity * 2);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity * 2);
Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService);
testNotificationUpdateGatewayNever();
Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService);
@@ -1027,7 +1077,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAnyAdditionalInfoAny(new Device(), new Device(),
savedTenant.getId(), customerId, tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UNASSIGNED_FROM_CUSTOMER, cntEntity, cntEntity, 3);
+ ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UPDATED, cntEntity, cntEntity, 3);
testNotificationUpdateGatewayNever();
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java
index d2bcfe2b88..14b052d93c 100644
--- a/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/DeviceProfileControllerTest.java
@@ -498,7 +498,7 @@ public class DeviceProfileControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new DeviceProfile(), new DeviceProfile(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, ActionType.ADDED, cntEntity, cntEntity, cntEntity);
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity);
Mockito.reset(tbClusterService, auditLogService);
List loadedDeviceProfiles = new ArrayList<>();
@@ -527,7 +527,7 @@ public class DeviceProfileControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(loadedDeviceProfiles.get(0), loadedDeviceProfiles.get(0),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.DELETED, ActionType.DELETED, cntEntity, cntEntity, cntEntity, loadedDeviceProfiles.get(0).getId().getId().toString());
+ ActionType.DELETED, cntEntity, cntEntity, cntEntity, loadedDeviceProfiles.get(0).getId().getId().toString());
pageLink = new PageLink(17);
pageData = doGetTypedWithPageLink("/api/deviceProfiles?",
diff --git a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java
index c8a20a38f5..78729eecf1 100644
--- a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java
@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
+import com.google.protobuf.AbstractMessage;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -45,7 +46,6 @@ import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EdgeId;
-import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
@@ -62,6 +62,8 @@ import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg;
import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg;
+import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg;
+import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.edge.v1.UserCredentialsUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UserUpdateMsg;
@@ -77,6 +79,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
@TestPropertySource(properties = {
"edges.enabled=true",
+ "queue.rule-engine.stats.enabled=false"
})
@ContextConfiguration(classes = {EdgeControllerTest.Config.class})
@DaoSqlTest
@@ -87,10 +90,6 @@ public class EdgeControllerTest extends AbstractControllerTest {
private IdComparator idComparator = new IdComparator<>();
- private Tenant savedTenant;
- private TenantId tenantId;
- private User tenantAdmin;
-
ListeningExecutorService executor;
List> futures;
@@ -107,35 +106,14 @@ public class EdgeControllerTest extends AbstractControllerTest {
}
@Before
- public void beforeTest() throws Exception {
+ public void setupEdgeTest() throws Exception {
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(8, getClass()));
-
- loginSysAdmin();
-
- Tenant tenant = new Tenant();
- tenant.setTitle("My tenant for Edge");
- savedTenant = doPost("/api/tenant", tenant, Tenant.class);
- tenantId = savedTenant.getId();
- Assert.assertNotNull(savedTenant);
-
- tenantAdmin = new User();
- tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
- tenantAdmin.setTenantId(savedTenant.getId());
- tenantAdmin.setEmail("tenant2@thingsboard.org");
- tenantAdmin.setFirstName("Joe");
- tenantAdmin.setLastName("Downs");
-
- tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
+ loginTenantAdmin();
}
@After
- public void afterTest() throws Exception {
+ public void teardownEdgeTest() throws Exception {
executor.shutdownNow();
-
- loginSysAdmin();
-
- doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
- .andExpect(status().isOk());
}
@Test
@@ -149,13 +127,13 @@ public class EdgeControllerTest extends AbstractControllerTest {
Assert.assertNotNull(savedEdge);
Assert.assertNotNull(savedEdge.getId());
Assert.assertTrue(savedEdge.getCreatedTime() > 0);
- Assert.assertEquals(savedTenant.getId(), savedEdge.getTenantId());
+ Assert.assertEquals(tenantId, savedEdge.getTenantId());
Assert.assertNotNull(savedEdge.getCustomerId());
Assert.assertEquals(NULL_UUID, savedEdge.getCustomerId().getId());
Assert.assertEquals(edge.getName(), savedEdge.getName());
testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(savedEdge, savedEdge.getId(), savedEdge.getId(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
+ tenantId, tenantAdminUser.getCustomerId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(),
ActionType.ADDED);
savedEdge.setName("My new edge");
@@ -165,7 +143,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
Assert.assertEquals(foundEdge.getName(), savedEdge.getName());
testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(foundEdge, foundEdge.getId(), foundEdge.getId(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
+ tenantId, tenantAdminUser.getCustomerId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(),
ActionType.UPDATED);
}
@@ -180,8 +158,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString(msgError)));
- testNotifyEntityEqualsOneTimeServiceNeverError(edge, savedTenant.getId(),
- tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
+ testNotifyEntityEqualsOneTimeServiceNeverError(edge, tenantId,
+ tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
Mockito.reset(tbClusterService, auditLogService);
msgError = msgErrorFieldLength("type");
@@ -191,8 +169,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString(msgError)));
- testNotifyEntityEqualsOneTimeServiceNeverError(edge, savedTenant.getId(),
- tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
+ testNotifyEntityEqualsOneTimeServiceNeverError(edge, tenantId,
+ tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
Mockito.reset(tbClusterService, auditLogService);
msgError = msgErrorFieldLength("label");
@@ -202,8 +180,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString(msgError)));
- testNotifyEntityEqualsOneTimeServiceNeverError(edge, savedTenant.getId(),
- tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
+ testNotifyEntityEqualsOneTimeServiceNeverError(edge, tenantId,
+ tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
}
@Test
@@ -229,7 +207,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
}
testNotifyManyEntityManyTimeMsgToEdgeServiceNeverAdditionalInfoAny(new Edge(), new Edge(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
+ tenantId, tenantAdminUser.getCustomerId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(),
ActionType.ADDED, cntEntity, 0);
for (int i = 0; i < 7; i++) {
@@ -262,7 +240,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isOk());
testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(savedEdge, savedEdge.getId(), savedEdge.getId(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
+ tenantId, tenantAdminUser.getCustomerId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(),
ActionType.DELETED, savedEdge.getId().getId().toString());
doGet("/api/edge/" + savedEdge.getId().getId().toString())
@@ -281,8 +259,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString(msgError)));
- testNotifyEntityEqualsOneTimeServiceNeverError(edge, savedTenant.getId(),
- tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
+ testNotifyEntityEqualsOneTimeServiceNeverError(edge, tenantId,
+ tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
}
@Test
@@ -296,8 +274,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString(msgError)));
- testNotifyEntityEqualsOneTimeServiceNeverError(edge, savedTenant.getId(),
- tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
+ testNotifyEntityEqualsOneTimeServiceNeverError(edge, tenantId,
+ tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.ADDED, new DataValidationException(msgError));
}
@Test
@@ -316,8 +294,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
Assert.assertEquals(savedCustomer.getId(), assignedEdge.getCustomerId());
testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(assignedEdge, assignedEdge.getId(), assignedEdge.getId(),
- savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ASSIGNED_TO_CUSTOMER,
- assignedEdge.getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
+ tenantId, savedCustomer.getId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.ASSIGNED_TO_CUSTOMER,
+ ActionType.ASSIGNED_TO_CUSTOMER, assignedEdge.getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
Edge foundEdge = doGet("/api/edge/" + savedEdge.getId().getId().toString(), Edge.class);
Assert.assertEquals(savedCustomer.getId(), foundEdge.getCustomerId());
@@ -327,8 +305,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
Assert.assertEquals(ModelConstants.NULL_UUID, unassignedEdge.getCustomerId().getId());
testNotifyEntityAllOneTimeLogEntityActionEntityEqClass(unassignedEdge, unassignedEdge.getId(), unassignedEdge.getId(),
- savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UNASSIGNED_FROM_CUSTOMER,
- unassignedEdge.getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
+ tenantId, savedCustomer.getId(), tenantAdminUser.getId(), tenantAdminUser.getEmail(), ActionType.UNASSIGNED_FROM_CUSTOMER,
+ ActionType.UNASSIGNED_FROM_CUSTOMER, unassignedEdge.getId().getId().toString(), savedCustomer.getId().getId().toString(), savedCustomer.getTitle());
foundEdge = doGet("/api/edge/" + savedEdge.getId().getId().toString(), Edge.class);
Assert.assertEquals(ModelConstants.NULL_UUID, foundEdge.getCustomerId().getId());
@@ -375,7 +353,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
customer.setTitle("Different customer");
Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
- login(tenantAdmin.getEmail(), "testPassword1");
+ loginTenantAdmin();
Edge edge = constructEdge("My edge", "default");
Edge savedEdge = doPost("/api/edge", edge, Edge.class);
@@ -625,8 +603,8 @@ public class EdgeControllerTest extends AbstractControllerTest {
List edges = new ArrayList<>(Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS));
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new Edge(), new Edge(),
- savedTenant.getId(), customerId, tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ASSIGNED_TO_CUSTOMER, ActionType.ASSIGNED_TO_CUSTOMER, cntEntity, cntEntity, cntEntity * 2,
+ tenantId, customerId, tenantAdminUser.getId(), tenantAdminUser.getEmail(),
+ ActionType.ASSIGNED_TO_CUSTOMER, cntEntity, cntEntity, cntEntity * 2,
new String(), new String(), new String());
List loadedEdges = new ArrayList<>();
@@ -731,7 +709,7 @@ public class EdgeControllerTest extends AbstractControllerTest {
cntEntity = loadedEdgesTitle1.size();
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAnyAdditionalInfoAny(new Edge(), new Edge(),
- savedTenant.getId(), customerId, tenantAdmin.getId(), tenantAdmin.getEmail(),
+ tenantId, customerId, tenantAdminUser.getId(), tenantAdminUser.getEmail(),
ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UNASSIGNED_FROM_CUSTOMER, cntEntity, cntEntity, 3);
pageLink = new PageLink(4, 0, title1);
@@ -857,56 +835,45 @@ public class EdgeControllerTest extends AbstractControllerTest {
@Test
public void testSyncEdge() throws Exception {
- Edge edge = doPost("/api/edge", constructEdge("Test Sync Edge", "test"), Edge.class);
+ Asset asset = new Asset();
+ asset.setName("Test Sync Edge Asset 1");
+ asset.setType("test");
+ Asset savedAsset = doPost("/api/asset", asset, Asset.class);
Device device = new Device();
device.setName("Test Sync Edge Device 1");
device.setType("default");
Device savedDevice = doPost("/api/device", device, Device.class);
+
+ Edge edge = doPost("/api/edge", constructEdge("Test Sync Edge", "test"), Edge.class);
+
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/device/" + savedDevice.getId().getId().toString(), Device.class);
-
- Asset asset = new Asset();
- asset.setName("Test Sync Edge Asset 1");
- asset.setType("test");
- Asset savedAsset = doPost("/api/asset", asset, Asset.class);
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
EdgeImitator edgeImitator = new EdgeImitator(EDGE_HOST, EDGE_PORT, edge.getRoutingKey(), edge.getSecret());
edgeImitator.ignoreType(UserCredentialsUpdateMsg.class);
- edgeImitator.expectMessageAmount(20);
+ edgeImitator.expectMessageAmount(21);
edgeImitator.connect();
assertThat(edgeImitator.waitForMessages()).as("await for messages on first connect").isTrue();
- assertThat(edgeImitator.findAllMessagesByType(QueueUpdateMsg.class)).as("one msg during sync process").hasSize(1);
- List ruleChainUpdateMsgs = edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class);
- assertThat(ruleChainUpdateMsgs).as("one msg during sync process, another from edge creation").hasSize(2);
- assertThat(edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class)).as("one msg during sync process for 'default' device profile").hasSize(3);
- assertThat(edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class)).as("one msg once device assigned to edge").hasSize(2);
- assertThat(edgeImitator.findAllMessagesByType(AssetProfileUpdateMsg.class)).as("two msgs during sync process for 'default' and 'test' asset profiles").hasSize(4);
- assertThat(edgeImitator.findAllMessagesByType(AssetUpdateMsg.class)).as("two msgs - one during sync process, and one more once asset assigned to edge").hasSize(2);
- assertThat(edgeImitator.findAllMessagesByType(UserUpdateMsg.class)).as("one msg during sync process for tenant admin user").hasSize(1);
- assertThat(edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class)).as("admin setting update").hasSize(4);
- assertThat(edgeImitator.findAllMessagesByType(CustomerUpdateMsg.class)).as("one msg during sync process for 'Public' customer").hasSize(1);
- verifyRuleChainMsgsAreRoot(ruleChainUpdateMsgs);
-
- edgeImitator.expectMessageAmount(15);
+ verifyFetchersMsgs(edgeImitator);
+ // verify queue msgs
+ Assert.assertTrue(popRuleChainMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, "Edge Root Rule Chain"));
+ Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default"));
+ Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1"));
+ Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test"));
+ Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1"));
+ Assert.assertTrue(edgeImitator.getDownlinkMsgs().isEmpty());
+
+ edgeImitator.expectMessageAmount(16);
doPost("/api/edge/sync/" + edge.getId());
assertThat(edgeImitator.waitForMessages()).as("await for messages after edge sync rest api call").isTrue();
- assertThat(edgeImitator.findAllMessagesByType(QueueUpdateMsg.class)).as("queue msg").hasSize(1);
- ruleChainUpdateMsgs = edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class);
- assertThat(ruleChainUpdateMsgs).as("rule chain msg").hasSize(1);
- assertThat(edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class)).as("device profile msg").hasSize(2);
- assertThat(edgeImitator.findAllMessagesByType(AssetProfileUpdateMsg.class)).as("asset profile msg").hasSize(3);
- assertThat(edgeImitator.findAllMessagesByType(AssetUpdateMsg.class)).as("asset update msg").hasSize(1);
- assertThat(edgeImitator.findAllMessagesByType(UserUpdateMsg.class)).as("user update msg").hasSize(1);
- assertThat(edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class)).as("admin setting update msg").hasSize(4);
- assertThat(edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class)).as("asset update msg").hasSize(1);
- assertThat(edgeImitator.findAllMessagesByType(CustomerUpdateMsg.class)).as("one msg during sync process for 'Public' customer").hasSize(1);
- verifyRuleChainMsgsAreRoot(ruleChainUpdateMsgs);
+ verifyFetchersMsgs(edgeImitator);
+ Assert.assertTrue(edgeImitator.getDownlinkMsgs().isEmpty());
edgeImitator.allowIgnoredTypes();
try {
@@ -922,23 +889,174 @@ public class EdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isOk());
}
- private void verifyRuleChainMsgsAreRoot(List ruleChainUpdateMsgs) {
- for (RuleChainUpdateMsg ruleChainUpdateMsg : ruleChainUpdateMsgs) {
- Assert.assertTrue(ruleChainUpdateMsg.getRoot());
+ private void verifyFetchersMsgs(EdgeImitator edgeImitator) {
+ Assert.assertTrue(popQueueMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Main"));
+ Assert.assertTrue(popRuleChainMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Edge Root Rule Chain"));
+ Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "mail", true));
+ Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "mail", false));
+ Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "mailTemplates", true));
+ Assert.assertTrue(popAdminSettingsMsg(edgeImitator.getDownlinkMsgs(), "mailTemplates", false));
+ Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default"));
+ Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default"));
+ Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test"));
+ Assert.assertTrue(popUserMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, TENANT_ADMIN_EMAIL, Authority.TENANT_ADMIN));
+ Assert.assertTrue(popCustomerMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Public"));
+ Assert.assertTrue(popDeviceProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "default"));
+ Assert.assertTrue(popDeviceMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Device 1"));
+ Assert.assertTrue(popAssetProfileMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "test"));
+ Assert.assertTrue(popAssetMsg(edgeImitator.getDownlinkMsgs(), UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, "Test Sync Edge Asset 1"));
+ Assert.assertTrue(popSyncCompletedMsg(edgeImitator.getDownlinkMsgs()));
+ }
+
+ private boolean popQueueMsg(List messages, UpdateMsgType msgType, String name) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof QueueUpdateMsg) {
+ QueueUpdateMsg queueUpdateMsg = (QueueUpdateMsg) message;
+ if (msgType.equals(queueUpdateMsg.getMsgType())
+ && name.equals(queueUpdateMsg.getName())) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popRuleChainMsg(List messages, UpdateMsgType msgType, String name) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof RuleChainUpdateMsg) {
+ RuleChainUpdateMsg ruleChainUpdateMsg = (RuleChainUpdateMsg) message;
+ if (msgType.equals(ruleChainUpdateMsg.getMsgType())
+ && name.equals(ruleChainUpdateMsg.getName())
+ && ruleChainUpdateMsg.getRoot()) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popAdminSettingsMsg(List messages, String key, boolean isSystem) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof AdminSettingsUpdateMsg) {
+ AdminSettingsUpdateMsg adminSettingsUpdateMsg = (AdminSettingsUpdateMsg) message;
+ if (key.equals(adminSettingsUpdateMsg.getKey())
+ && isSystem == adminSettingsUpdateMsg.getIsSystem()) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popDeviceProfileMsg(List messages, UpdateMsgType msgType, String name) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof DeviceProfileUpdateMsg) {
+ DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) message;
+ if (msgType.equals(deviceProfileUpdateMsg.getMsgType())
+ && name.equals(deviceProfileUpdateMsg.getName())) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popDeviceMsg(List messages, UpdateMsgType msgType, String name) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof DeviceUpdateMsg) {
+ DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) message;
+ if (msgType.equals(deviceUpdateMsg.getMsgType())
+ && name.equals(deviceUpdateMsg.getName())) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popAssetProfileMsg(List messages, UpdateMsgType msgType, String name) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof AssetProfileUpdateMsg) {
+ AssetProfileUpdateMsg assetProfileUpdateMsg = (AssetProfileUpdateMsg) message;
+ if (msgType.equals(assetProfileUpdateMsg.getMsgType())
+ && name.equals(assetProfileUpdateMsg.getName())) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popAssetMsg(List messages, UpdateMsgType msgType, String name) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof AssetUpdateMsg) {
+ AssetUpdateMsg assetUpdateMsg = (AssetUpdateMsg) message;
+ if (msgType.equals(assetUpdateMsg.getMsgType())
+ && name.equals(assetUpdateMsg.getName())) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popUserMsg(List messages, UpdateMsgType msgType, String email, Authority authority) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof UserUpdateMsg) {
+ UserUpdateMsg userUpdateMsg = (UserUpdateMsg) message;
+ if (msgType.equals(userUpdateMsg.getMsgType())
+ && email.equals(userUpdateMsg.getEmail())
+ && authority.name().equals(userUpdateMsg.getAuthority())) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popCustomerMsg(List messages, UpdateMsgType msgType, String title) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof CustomerUpdateMsg) {
+ CustomerUpdateMsg customerUpdateMsg = (CustomerUpdateMsg) message;
+ if (msgType.equals(customerUpdateMsg.getMsgType())
+ && title.equals(customerUpdateMsg.getTitle())) {
+ messages.remove(message);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean popSyncCompletedMsg(List messages) {
+ for (AbstractMessage message : messages) {
+ if (message instanceof SyncCompletedMsg) {
+ messages.remove(message);
+ return true;
+ }
}
+ return false;
}
@Test
public void testDeleteEdgeWithDeleteRelationsOk() throws Exception {
EdgeId edgeId = savedEdge("Edge for Test WithRelationsOk").getId();
- testEntityDaoWithRelationsOk(savedTenant.getId(), edgeId, "/api/edge/" + edgeId);
+ testEntityDaoWithRelationsOk(tenantId, edgeId, "/api/edge/" + edgeId);
}
@Ignore
@Test
public void testDeleteEdgeExceptionWithRelationsTransactional() throws Exception {
EdgeId edgeId = savedEdge("Edge for Test WithRelations Transactional Exception").getId();
- testEntityDaoWithRelationsTransactionalException(edgeDao, savedTenant.getId(), edgeId, "/api/edge/" + edgeId);
+ testEntityDaoWithRelationsTransactionalException(edgeDao, tenantId, edgeId, "/api/edge/" + edgeId);
}
private Edge savedEdge(String name) {
diff --git a/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java
index 255aa2bdf1..04842df6a0 100644
--- a/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java
@@ -27,8 +27,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.TestPropertySource;
import org.thingsboard.server.common.data.Device;
-import org.thingsboard.server.common.data.Tenant;
-import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
@@ -38,7 +36,6 @@ import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
-import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.edge.EdgeEventDao;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository;
@@ -54,18 +51,15 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@TestPropertySource(properties = {
"edges.enabled=true",
+ "queue.rule-engine.stats.enabled=false"
})
@Slf4j
@DaoSqlTest
public class EdgeEventControllerTest extends AbstractControllerTest {
- private Tenant savedTenant;
- private User tenantAdmin;
-
@Autowired
private EdgeEventDao edgeEventDao;
@SpyBean
@@ -80,33 +74,11 @@ public class EdgeEventControllerTest extends AbstractControllerTest {
@Before
public void beforeTest() throws Exception {
- loginSysAdmin();
-
- Tenant tenant = new Tenant();
- tenant.setTitle("My tenant");
- savedTenant = doPost("/api/tenant", tenant, Tenant.class);
- Assert.assertNotNull(savedTenant);
-
- tenantAdmin = new User();
- tenantAdmin.setAuthority(Authority.TENANT_ADMIN);
- tenantAdmin.setTenantId(savedTenant.getId());
- tenantAdmin.setEmail("tenant2@thingsboard.org");
- tenantAdmin.setFirstName("Joe");
- tenantAdmin.setLastName("Downs");
-
- tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
- // sleep 1 seconds to avoid CREDENTIALS updated message for the user
- // user credentials is going to be stored and updated event pushed to edge notification service
- // while service will be processing this event edge could be already added and additional message will be pushed
- Thread.sleep(1000);
+ loginTenantAdmin();
}
@After
public void afterTest() throws Exception {
- loginSysAdmin();
-
- doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
- .andExpect(status().isOk());
}
@Test
@@ -127,19 +99,37 @@ public class EdgeEventControllerTest extends AbstractControllerTest {
EntityRelation relation = new EntityRelation(savedAsset.getId(), savedDevice.getId(), EntityRelation.CONTAINS_TYPE);
+ awaitForNumberOfEdgeEvents(edgeId, 3);
+
doPost("/api/relation", relation);
+ awaitForNumberOfEdgeEvents(edgeId, 4);
+
+ List edgeEvents = findEdgeEvents(edgeId);
+ Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.RULE_CHAIN)); // root rule chain
+ Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.DEVICE)); // TestDevice
+ Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.ASSET)); // TestAsset
+ Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.RELATION));
+ Assert.assertTrue(edgeEvents.isEmpty());
+ }
+
+ private boolean popEdgeEvent(List edgeEvents, EdgeEventType edgeEventType) {
+ for (EdgeEvent edgeEvent : edgeEvents) {
+ if (edgeEventType.equals(edgeEvent.getType())) {
+ edgeEvents.remove(edgeEvent);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void awaitForNumberOfEdgeEvents(EdgeId edgeId, int expectedNumber) {
Awaitility.await()
.atMost(30, TimeUnit.SECONDS)
.until(() -> {
List edgeEvents = findEdgeEvents(edgeId);
- return edgeEvents.size() == 4;
+ return edgeEvents.size() == expectedNumber;
});
- List edgeEvents = findEdgeEvents(edgeId);
- Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.RULE_CHAIN.equals(ee.getType())));
- Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.DEVICE.equals(ee.getType())));
- Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.ASSET.equals(ee.getType())));
- Assert.assertTrue(edgeEvents.stream().anyMatch(ee -> EdgeEventType.RELATION.equals(ee.getType())));
}
@Test
@@ -195,7 +185,7 @@ public class EdgeEventControllerTest extends AbstractControllerTest {
edgeEvent.setCreatedTime(System.currentTimeMillis());
edgeEvent.setTenantId(tenantId);
edgeEvent.setAction(EdgeEventActionType.ADDED);
- edgeEvent.setEntityId(tenantAdmin.getUuidId());
+ edgeEvent.setEntityId(tenantAdminUser.getUuidId());
edgeEvent.setType(EdgeEventType.ALARM);
try {
edgeEventDao.saveAsync(edgeEvent).get();
diff --git a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java
index a65769f3f1..beabcf77d1 100644
--- a/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/EntityViewControllerTest.java
@@ -43,6 +43,7 @@ import org.springframework.test.web.servlet.ResultActions;
import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.EntityViewInfo;
import org.thingsboard.server.common.data.StringUtils;
@@ -170,7 +171,7 @@ public class EntityViewControllerTest extends AbstractControllerTest {
testBroadcastEntityStateChangeEventTime(foundEntityView.getId(), tenantId, 1);
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(foundEntityView, foundEntityView,
tenantId, tenantAdminCustomerId, tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.ADDED, ActionType.ADDED, 1, 0, 1);
+ ActionType.ADDED, 1, 1, 1);
Mockito.reset(tbClusterService, auditLogService);
savedView.setName("New test entity view");
@@ -183,7 +184,7 @@ public class EntityViewControllerTest extends AbstractControllerTest {
testBroadcastEntityStateChangeEventTime(foundEntityView.getId(), tenantId, 1);
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(foundEntityView, foundEntityView,
tenantId, tenantAdminCustomerId, tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.UPDATED, ActionType.UPDATED, 1, 1, 5);
+ ActionType.UPDATED, 1, 1, 5);
doGet("/api/tenant/entityViews?entityViewName=" + name)
.andExpect(status().isNotFound())
@@ -247,13 +248,13 @@ public class EntityViewControllerTest extends AbstractControllerTest {
doDelete("/api/entityView/" + entityIdStr)
.andExpect(status().isOk());
- testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(savedView, savedView.getId(), savedView.getId(),
+ testNotifyEntityBroadcastEntityStateChangeEventOneTime(savedView, savedView.getId(), savedView.getId(),
tenantId, view.getCustomerId(), tenantAdminUserId, TENANT_ADMIN_EMAIL,
ActionType.DELETED, entityIdStr);
doGet("/api/entityView/" + entityIdStr)
.andExpect(status().isNotFound())
- .andExpect(statusReason(containsString(msgErrorNoFound("Entity view",entityIdStr))));
+ .andExpect(statusReason(containsString(msgErrorNoFound(EntityType.ENTITY_VIEW.getNormalName(), entityIdStr))));
}
@Test
@@ -286,7 +287,7 @@ public class EntityViewControllerTest extends AbstractControllerTest {
testBroadcastEntityStateChangeEventTime(savedView.getId(), tenantId, 1);
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(savedView, savedView,
tenantId, tenantAdminCustomerId, tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.UPDATED, ActionType.UPDATED, 1, 1, 5);
+ ActionType.UPDATED, 1, 1, 5);
Mockito.reset(tbClusterService, auditLogService);
EntityView assignedView = doPost(
@@ -298,9 +299,9 @@ public class EntityViewControllerTest extends AbstractControllerTest {
assertEquals(savedCustomer.getId(), foundView.getCustomerId());
testBroadcastEntityStateChangeEventNever(foundView.getId());
- testNotifyEntityAllOneTime(foundView, foundView.getId(), foundView.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(foundView, foundView.getId(), foundView.getId(),
tenantId, foundView.getCustomerId(), tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.ASSIGNED_TO_CUSTOMER,
+ ActionType.ASSIGNED_TO_CUSTOMER, ActionType.UPDATED,
foundView.getId().getId().toString(), foundView.getCustomerId().getId().toString(), savedCustomer.getTitle());
EntityView unAssignedView = doDelete("/api/customer/entityView/" + savedView.getId().getId().toString(), EntityView.class);
@@ -310,9 +311,9 @@ public class EntityViewControllerTest extends AbstractControllerTest {
assertEquals(ModelConstants.NULL_UUID, foundView.getCustomerId().getId());
testBroadcastEntityStateChangeEventNever(foundView.getId());
- testNotifyEntityAllOneTime(unAssignedView, savedView.getId(), savedView.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(unAssignedView, savedView.getId(), savedView.getId(),
tenantId, savedView.getCustomerId(), tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.UNASSIGNED_FROM_CUSTOMER,
+ ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UPDATED,
assignedView.getId().getId().toString(), savedView.getCustomerId().getId().toString(), savedCustomer.getTitle());
}
@@ -328,9 +329,9 @@ public class EntityViewControllerTest extends AbstractControllerTest {
Assert.assertTrue(publicCustomer.isPublic());
testBroadcastEntityStateChangeEventNever(assignedView.getId());
- testNotifyEntityAllOneTime(assignedView, assignedView.getId(), assignedView.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(assignedView, assignedView.getId(), assignedView.getId(),
tenantId, assignedView.getCustomerId(), tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.ASSIGNED_TO_CUSTOMER,
+ ActionType.ASSIGNED_TO_CUSTOMER, ActionType.UPDATED,
assignedView.getId().getId().toString(), assignedView.getCustomerId().getId().toString(), publicCustomer.getTitle());
EntityView foundView = doGet("/api/entityView/" + savedView.getId().getId().toString(), EntityView.class);
@@ -343,9 +344,9 @@ public class EntityViewControllerTest extends AbstractControllerTest {
assertEquals(ModelConstants.NULL_UUID, foundView.getCustomerId().getId());
testBroadcastEntityStateChangeEventNever(foundView.getId());
- testNotifyEntityAllOneTime(unAssignedView, unAssignedView.getId(), unAssignedView.getId(),
+ testNotifyAssignUnassignEntityAllOneTime(unAssignedView, unAssignedView.getId(), unAssignedView.getId(),
tenantId, publicCustomer.getId(), tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.UNASSIGNED_FROM_CUSTOMER,
+ ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UPDATED,
unAssignedView.getId().getId().toString(), publicCustomer.getId().getId().toString(), publicCustomer.getTitle());
}
@@ -425,11 +426,11 @@ public class EntityViewControllerTest extends AbstractControllerTest {
testNotifyEntityBroadcastEntityStateChangeEventMany(new EntityView(), new EntityView(),
tenantId, tenantAdminCustomerId, tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.ADDED, ActionType.ADDED, cntEntity, 0, cntEntity*2, 0);
+ ActionType.ADDED, ActionType.ADDED, cntEntity, cntEntity, cntEntity * 2, 0);
testNotifyEntityBroadcastEntityStateChangeEventMany(new EntityView(), new EntityView(),
tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.ASSIGNED_TO_CUSTOMER, ActionType.ASSIGNED_TO_CUSTOMER, cntEntity, cntEntity,
+ ActionType.ASSIGNED_TO_CUSTOMER, ActionType.UPDATED, cntEntity, cntEntity,
cntEntity*2, 3);
}
@@ -464,7 +465,7 @@ public class EntityViewControllerTest extends AbstractControllerTest {
testBroadcastEntityStateChangeEventNever(loadedNamesOfView1.get(0).getId());
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAnyAdditionalInfoAny(new EntityView(), new EntityView(),
tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL,
- ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UNASSIGNED_FROM_CUSTOMER, cntEntity, cntEntity, 3);
+ ActionType.UNASSIGNED_FROM_CUSTOMER, ActionType.UPDATED, cntEntity, cntEntity, 3);
PageData pageData = doGetTypedWithPageLink(urlTemplate, PAGE_DATA_ENTITY_VIEW_TYPE_REF,
new PageLink(4, 0, name1));
diff --git a/application/src/test/java/org/thingsboard/server/controller/OtaPackageControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/OtaPackageControllerTest.java
index f4472e83be..3ebbb9ebbc 100644
--- a/application/src/test/java/org/thingsboard/server/controller/OtaPackageControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/OtaPackageControllerTest.java
@@ -339,7 +339,7 @@ public class OtaPackageControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new OtaPackageInfo(), new OtaPackageInfo(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, ActionType.ADDED, cntEntity, 0, (cntEntity*2 - startIndexSaveData));
+ ActionType.ADDED, cntEntity, 0, (cntEntity*2 - startIndexSaveData));
List loadedFirmwares = new ArrayList<>();
PageLink pageLink = new PageLink(24);
diff --git a/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java
index c9eba1dbce..cafeabcf16 100644
--- a/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/RuleChainControllerTest.java
@@ -30,6 +30,8 @@ import org.springframework.test.context.ContextConfiguration;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.action.TbCreateAlarmNode;
import org.thingsboard.rule.engine.action.TbCreateAlarmNodeConfiguration;
+import org.thingsboard.rule.engine.metadata.TbGetRelatedAttributeNode;
+import org.thingsboard.rule.engine.metadata.TbGetRelatedDataNodeConfiguration;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
@@ -48,7 +50,6 @@ import org.thingsboard.server.dao.rule.RuleChainDao;
import org.thingsboard.server.dao.service.DaoSqlTest;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -59,7 +60,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@DaoSqlTest
public class RuleChainControllerTest extends AbstractControllerTest {
- private IdComparator idComparator = new IdComparator<>();
+ private final IdComparator idComparator = new IdComparator<>();
private Tenant savedTenant;
private User tenantAdmin;
@@ -129,6 +130,78 @@ public class RuleChainControllerTest extends AbstractControllerTest {
ActionType.UPDATED);
}
+ @Test
+ public void testSaveRuleChainMetadataWithVersionedNodes() throws Exception {
+ RuleChain ruleChain = new RuleChain();
+ ruleChain.setName("RuleChain");
+
+ RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class);
+ Assert.assertNotNull(savedRuleChain);
+ RuleChainId ruleChainId = savedRuleChain.getId();
+ Assert.assertNotNull(ruleChainId);
+ Assert.assertTrue(savedRuleChain.getCreatedTime() > 0);
+ Assert.assertEquals(ruleChain.getName(), savedRuleChain.getName());
+
+ var annotation = TbGetRelatedAttributeNode.class.getAnnotation(org.thingsboard.rule.engine.api.RuleNode.class);
+ String ruleNodeType = TbGetRelatedAttributeNode.class.getName();
+ int currentVersion = annotation.version();
+
+ String oldConfig = "{\"attrMapping\":{\"serialNumber\":\"sn\"}," +
+ "\"relationsQuery\":{\"direction\":\"FROM\",\"maxLevel\":1," +
+ "\"filters\":[{\"relationType\":\"Contains\",\"entityTypes\":[]}]," +
+ "\"fetchLastLevelOnly\":false},\"telemetry\":false}";
+
+ TbGetRelatedDataNodeConfiguration defaultConfiguration = new TbGetRelatedDataNodeConfiguration().defaultConfiguration();
+ String newConfig = JacksonUtil.toString(defaultConfiguration);
+
+ var ruleChainMetaData = createRuleChainMetadataWithTbVersionedNodes(
+ ruleChainId,
+ ruleNodeType,
+ currentVersion,
+ oldConfig,
+ newConfig
+ );
+ var savedRuleChainMetaData = doPost("/api/ruleChain/metadata", ruleChainMetaData, RuleChainMetaData.class);
+
+ Assert.assertEquals(ruleChainId, savedRuleChainMetaData.getRuleChainId());
+ Assert.assertEquals(2, savedRuleChainMetaData.getNodes().size());
+
+ for (RuleNode ruleNode : savedRuleChainMetaData.getNodes()) {
+ Assert.assertNotNull(ruleNode.getId());
+ Assert.assertEquals(currentVersion, ruleNode.getConfigurationVersion());
+ Assert.assertEquals(defaultConfiguration, JacksonUtil.treeToValue(ruleNode.getConfiguration(), defaultConfiguration.getClass()));
+ }
+ }
+
+ private RuleChainMetaData createRuleChainMetadataWithTbVersionedNodes(
+ RuleChainId ruleChainId,
+ String ruleNodeType,
+ int currentVersion,
+ String oldConfig,
+ String newConfig
+ ) {
+ RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();
+ ruleChainMetaData.setRuleChainId(ruleChainId);
+
+ var ruleNodeWithOldConfig = new RuleNode();
+ ruleNodeWithOldConfig.setName("Old Rule Node");
+ ruleNodeWithOldConfig.setType(ruleNodeType);
+ ruleNodeWithOldConfig.setConfiguration(JacksonUtil.toJsonNode(oldConfig));
+
+ var ruleNodeWithNewConfig = new RuleNode();
+ ruleNodeWithNewConfig.setName("New Rule Node");
+ ruleNodeWithNewConfig.setType(ruleNodeType);
+ ruleNodeWithNewConfig.setConfigurationVersion(currentVersion);
+ ruleNodeWithNewConfig.setConfiguration(JacksonUtil.toJsonNode(newConfig));
+
+ List ruleNodes = new ArrayList<>();
+ ruleNodes.add(ruleNodeWithOldConfig);
+ ruleNodes.add(ruleNodeWithNewConfig);
+ ruleChainMetaData.setFirstNodeIndex(0);
+ ruleChainMetaData.setNodes(ruleNodes);
+ return ruleChainMetaData;
+ }
+
@Test
public void testSaveRuleChainWithViolationOfLengthValidation() throws Exception {
@@ -169,7 +242,7 @@ public class RuleChainControllerTest extends AbstractControllerTest {
doDelete("/api/ruleChain/" + savedRuleChain.getId().getId().toString())
.andExpect(status().isOk());
- testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(savedRuleChain, savedRuleChain.getId(), savedRuleChain.getId(),
+ testNotifyEntityBroadcastEntityStateChangeEventOneTime(savedRuleChain, savedRuleChain.getId(), savedRuleChain.getId(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
ActionType.DELETED, savedRuleChain.getId().getId().toString());
@@ -184,14 +257,13 @@ public class RuleChainControllerTest extends AbstractControllerTest {
Edge savedEdge = doPost("/api/edge", edge, Edge.class);
- List edgeRuleChains = new ArrayList<>();
PageLink pageLink = new PageLink(17);
PageData pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId() + "/ruleChains?",
new TypeReference<>() {
}, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(1, pageData.getTotalElements());
- edgeRuleChains.addAll(pageData.getData());
+ List edgeRuleChains = new ArrayList<>(pageData.getData());
Mockito.reset(tbClusterService, auditLogService);
@@ -208,11 +280,7 @@ public class RuleChainControllerTest extends AbstractControllerTest {
testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new RuleChain(), new RuleChain(),
savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ADDED, ActionType.ADDED, cntEntity, 0, cntEntity * 2);
- testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new RuleChain(), new RuleChain(),
- savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(),
- ActionType.ASSIGNED_TO_EDGE, ActionType.ASSIGNED_TO_EDGE, cntEntity, cntEntity, cntEntity * 2,
- new String(), new String(), new String());
+ ActionType.ADDED, cntEntity, cntEntity, cntEntity * 2);
Mockito.reset(tbClusterService, auditLogService);
List