Browse Source

Merge branch 'master' into feature/rule-chain-versioning

pull/11496/head
Viacheslav Klimov 2 years ago
committed by GitHub
parent
commit
40fc7eacf3
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java
  2. 5
      application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java
  3. 80
      application/src/main/java/org/thingsboard/server/service/edge/RelatedEdgesSourcingListener.java
  4. 8
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java
  5. 4
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java
  6. 16
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessor.java
  7. 16
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java
  8. 10
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java
  9. 2
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/edge/EdgeProcessor.java
  10. 16
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java
  11. 12
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java
  12. 5
      application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java
  13. 4
      application/src/main/java/org/thingsboard/server/service/executors/PubSubRuleNodeExecutorProvider.java
  14. 2
      application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperReprocessingService.java
  15. 2
      application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperService.java
  16. 6
      application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java
  17. 4
      application/src/main/java/org/thingsboard/server/service/subscription/SubscriptionSchedulerComponent.java
  18. 4
      application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
  19. 3
      application/src/main/resources/thingsboard.yml
  20. 4
      application/src/test/java/org/thingsboard/server/cache/CaffeineCacheDefaultConfigurationTest.java
  21. 2
      application/src/test/java/org/thingsboard/server/edge/RelationEdgeTest.java
  22. 414
      application/src/test/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructorTest.java
  23. 563
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessorTest.java
  24. 92
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/asset/AbstractAssetProcessorTest.java
  25. 39
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessorTest.java
  26. 40
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetProfileEdgeProcessorTest.java
  27. 102
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/AbstractDeviceProcessorTest.java
  28. 38
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessorTest.java
  29. 41
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceProfileEdgeProcessorTest.java
  30. 66
      application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/TelemetryEdgeProcessorTest.java
  31. 1
      application/src/test/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcServiceTest.java
  32. 5
      common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java
  33. 4
      common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeCacheEvictEvent.java
  34. 6
      common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeCacheKey.java
  35. 2
      common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeCaffeineCache.java
  36. 3
      common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeRedisCache.java
  37. 45
      common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesCacheKey.java
  38. 37
      common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesCacheValue.java
  39. 32
      common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesCaffeineCache.java
  40. 30
      common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesEvictEvent.java
  41. 35
      common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesRedisCache.java
  42. 5
      common/cache/src/main/java/org/thingsboard/server/cache/resourceInfo/ResourceInfoCacheKey.java
  43. 2
      common/cluster-api/src/main/java/org/thingsboard/server/cluster/TbClusterService.java
  44. 4
      common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java
  45. 30
      common/dao-api/src/main/java/org/thingsboard/server/dao/edge/RelatedEdgesService.java
  46. 1
      common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java
  47. 2
      common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java
  48. 1
      common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseAttributeKvEntry.java
  49. 1
      common/data/src/main/java/org/thingsboard/server/common/data/kv/BasicTsKvEntry.java
  50. 2
      common/data/src/main/java/org/thingsboard/server/common/data/page/PageDataIterableByTenantIdEntityId.java
  51. 2
      common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaSettings.java
  52. 1
      common/queue/src/test/java/org/thingsboard/server/queue/discovery/ZkDiscoveryServiceTest.java
  53. 1
      common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java
  54. 2
      common/script/script-api/src/main/java/org/thingsboard/script/api/ScriptStatCallback.java
  55. 4
      common/script/script-api/src/main/java/org/thingsboard/script/api/js/NashornJsInvokeService.java
  56. 5
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java
  57. 2
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetCacheKey.java
  58. 3
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java
  59. 4
      dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java
  60. 1
      dao/src/main/java/org/thingsboard/server/dao/attributes/BaseAttributesService.java
  61. 10
      dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java
  62. 3
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java
  63. 8
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
  64. 62
      dao/src/main/java/org/thingsboard/server/dao/edge/BaseRelatedEdgesService.java
  65. 112
      dao/src/main/java/org/thingsboard/server/dao/edge/EdgeDao.java
  66. 38
      dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java
  67. 2
      dao/src/main/java/org/thingsboard/server/dao/entity/EntityCountCacheKey.java
  68. 4
      dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java
  69. 6
      dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
  70. 4
      dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCacheKey.java
  71. 2
      dao/src/main/java/org/thingsboard/server/dao/relation/RelationCacheKey.java
  72. 2
      dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java
  73. 11
      dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeRepository.java
  74. 13
      dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java
  75. 3
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileCacheKey.java
  76. 4
      dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java
  77. 4
      dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
  78. 10
      dao/src/test/java/org/thingsboard/server/dao/service/EntityServiceTest.java
  79. 2
      dao/src/test/java/org/thingsboard/server/dao/service/QueueStatsServiceTest.java
  80. 3
      dao/src/test/resources/application-test.properties
  81. 6
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java
  82. 2
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/aws/sns/TbSnsNodeTest.java
  83. 2
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNodeTest.java
  84. 2
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java
  85. 5
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNodeTest.java
  86. 1
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNodeTest.java
  87. 1
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java
  88. 1
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java
  89. 2
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java
  90. 1
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java
  91. 1
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java

2
application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java

@ -18,6 +18,7 @@ package org.thingsboard.server.controller.plugin;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalCause;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.websocket.RemoteEndpoint;
import jakarta.websocket.SendHandler;
@ -65,7 +66,6 @@ import org.thingsboard.server.service.ws.WsCommandsWrapper;
import org.thingsboard.server.service.ws.notification.cmd.NotificationCmdsWrapper;
import org.thingsboard.server.service.ws.telemetry.cmd.TelemetryCmdsWrapper;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.Optional;

5
application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java

@ -17,6 +17,7 @@ package org.thingsboard.server.service.edge;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -49,8 +50,6 @@ import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.user.UserServiceImpl;
import javax.annotation.PostConstruct;
/**
* 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
@ -76,7 +75,7 @@ public class EdgeEventSourcingListener {
@PostConstruct
public void init() {
log.info("EdgeEventSourcingListener initiated");
log.debug("EdgeEventSourcingListener initiated");
}
@TransactionalEventListener(fallbackExecution = true)

80
application/src/main/java/org/thingsboard/server/service/edge/RelatedEdgesSourcingListener.java

@ -0,0 +1,80 @@
/**
* Copyright © 2016-2024 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 jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.dao.edge.RelatedEdgesService;
import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent;
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Component
@RequiredArgsConstructor
@Slf4j
public class RelatedEdgesSourcingListener {
private final RelatedEdgesService relatedEdgesService;
private ExecutorService executorService;
@PostConstruct
public void init() {
log.debug("RelatedEdgesSourcingListener initiated");
executorService = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("related-edges-listener"));
}
@PreDestroy
public void destroy() {
log.debug("RelatedEdgesSourcingListener destroy");
if (executorService != null && !executorService.isShutdown()) {
executorService.shutdown();
}
}
@TransactionalEventListener(fallbackExecution = true)
public void handleEvent(ActionEntityEvent<?> event) {
executorService.submit(() -> {
try {
switch (event.getActionType()) {
case ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE ->
relatedEdgesService.publishRelatedEdgeIdsEvictEvent(event.getTenantId(), event.getEntityId());
}
} catch (Exception e) {
log.error("[{}] failed to process ActionEntityEvent: {}", event.getTenantId(), event, e);
}
});
}
@TransactionalEventListener(fallbackExecution = true)
public void handleEvent(DeleteEntityEvent<?> event) {
executorService.submit(() -> {
try {
relatedEdgesService.publishRelatedEdgeIdsEvictEvent(event.getTenantId(), event.getEntityId());
} catch (Exception e) {
log.error("[{}] failed to process DeleteEntityEvent: {}", event.getTenantId(), event, e);
}
});
}
}

8
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java

@ -133,14 +133,14 @@ import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static org.thingsboard.server.dao.edge.BaseRelatedEdgesService.RELATED_EDGES_CACHE_ITEMS;
@Slf4j
public abstract class BaseEdgeProcessor {
protected static final Lock deviceCreationLock = new ReentrantLock();
protected static final Lock assetCreationLock = new ReentrantLock();
protected static final int DEFAULT_PAGE_SIZE = 100;
@Autowired
protected TelemetrySubscriptionService tsSubService;
@ -507,7 +507,7 @@ public abstract class BaseEdgeProcessor {
EdgeEventActionType actionType, EdgeId sourceEdgeId) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
PageDataIterableByTenantIdEntityId<EdgeId> edgeIds =
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE);
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, RELATED_EDGES_CACHE_ITEMS);
for (EdgeId relatedEdgeId : edgeIds) {
if (!relatedEdgeId.equals(sourceEdgeId)) {
futures.add(saveEdgeEvent(tenantId, relatedEdgeId, type, actionType, entityId, null));
@ -653,7 +653,7 @@ public abstract class BaseEdgeProcessor {
private boolean isEntityNotAssignedToEdge(TenantId tenantId, EntityId entityId, EdgeId edgeId) {
PageDataIterableByTenantIdEntityId<EdgeId> edgeIds =
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE);
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, RELATED_EDGES_CACHE_ITEMS);
for (EdgeId edgeId1 : edgeIds) {
if (edgeId1.equals(edgeId)) {
return false;

4
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java

@ -43,6 +43,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static org.thingsboard.server.dao.edge.BaseRelatedEdgesService.RELATED_EDGES_CACHE_ITEMS;
@Slf4j
public abstract class AlarmEdgeProcessor extends BaseAlarmProcessor implements AlarmProcessor {
@ -148,7 +150,7 @@ public abstract class AlarmEdgeProcessor extends BaseAlarmProcessor implements A
EdgeEventType edgeEventType) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
PageDataIterableByTenantIdEntityId<EdgeId> edgeIds =
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, originatorId, DEFAULT_PAGE_SIZE);
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, originatorId, RELATED_EDGES_CACHE_ITEMS);
for (EdgeId relatedEdgeId : edgeIds) {
if (!relatedEdgeId.equals(sourceEdgeId)) {
futures.add(saveEdgeEvent(tenantId, relatedEdgeId, edgeEventType, actionType, alarmId, body));

16
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessor.java

@ -107,6 +107,7 @@ public abstract class AssetEdgeProcessor extends BaseAssetProcessor implements A
public DownlinkMsg convertAssetEventToDownlink(EdgeEvent edgeEvent, EdgeId edgeId, EdgeVersion edgeVersion) {
AssetId assetId = new AssetId(edgeEvent.getEntityId());
DownlinkMsg downlinkMsg = null;
var msgConstructor = (AssetMsgConstructor) assetMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion);
switch (edgeEvent.getAction()) {
case ADDED, UPDATED, ASSIGNED_TO_EDGE, ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER -> {
Asset asset = assetService.findAssetById(edgeEvent.getTenantId(), assetId);
@ -120,20 +121,15 @@ public abstract class AssetEdgeProcessor extends BaseAssetProcessor implements A
if (UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE.equals(msgType)) {
AssetProfile assetProfile = assetProfileService.findAssetProfileById(edgeEvent.getTenantId(), asset.getAssetProfileId());
assetProfile = checkIfAssetProfileDefaultFieldsAssignedToEdge(edgeEvent.getTenantId(), edgeId, assetProfile, edgeVersion);
builder.addAssetProfileUpdateMsg(((AssetMsgConstructor) assetMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion))
.constructAssetProfileUpdatedMsg(msgType, assetProfile));
builder.addAssetProfileUpdateMsg(msgConstructor.constructAssetProfileUpdatedMsg(msgType, assetProfile));
}
downlinkMsg = builder.build();
}
}
case DELETED, UNASSIGNED_FROM_EDGE -> {
AssetUpdateMsg assetUpdateMsg = ((AssetMsgConstructor)
assetMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructAssetDeleteMsg(assetId);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addAssetUpdateMsg(assetUpdateMsg)
.build();
}
case DELETED, UNASSIGNED_FROM_EDGE -> downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addAssetUpdateMsg(msgConstructor.constructAssetDeleteMsg(assetId))
.build();
}
return downlinkMsg;
}

16
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/dashboard/DashboardEdgeProcessor.java

@ -100,27 +100,23 @@ public abstract class DashboardEdgeProcessor extends BaseDashboardProcessor impl
public DownlinkMsg convertDashboardEventToDownlink(EdgeEvent edgeEvent, EdgeVersion edgeVersion) {
DashboardId dashboardId = new DashboardId(edgeEvent.getEntityId());
DownlinkMsg downlinkMsg = null;
var msgConstructor = (DashboardMsgConstructor) dashboardMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion);
switch (edgeEvent.getAction()) {
case ADDED, UPDATED, ASSIGNED_TO_EDGE, ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER -> {
Dashboard dashboard = dashboardService.findDashboardById(edgeEvent.getTenantId(), dashboardId);
if (dashboard != null) {
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
DashboardUpdateMsg dashboardUpdateMsg = ((DashboardMsgConstructor)
dashboardMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructDashboardUpdatedMsg(msgType, dashboard);
DashboardUpdateMsg dashboardUpdateMsg = msgConstructor.constructDashboardUpdatedMsg(msgType, dashboard);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addDashboardUpdateMsg(dashboardUpdateMsg)
.build();
}
}
case DELETED, UNASSIGNED_FROM_EDGE -> {
DashboardUpdateMsg dashboardUpdateMsg = ((DashboardMsgConstructor)
dashboardMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructDashboardDeleteMsg(dashboardId);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addDashboardUpdateMsg(dashboardUpdateMsg)
.build();
}
case DELETED, UNASSIGNED_FROM_EDGE -> downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addDashboardUpdateMsg(msgConstructor.constructDashboardDeleteMsg(dashboardId))
.build();
}
return downlinkMsg;
}

10
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessor.java

@ -226,9 +226,7 @@ public abstract class DeviceEdgeProcessor extends BaseDeviceProcessor implements
Device device = deviceService.findDeviceById(edgeEvent.getTenantId(), deviceId);
if (device != null) {
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
DeviceUpdateMsg deviceUpdateMsg = ((DeviceMsgConstructor)
deviceMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion))
.constructDeviceUpdatedMsg(msgType, device);
DeviceUpdateMsg deviceUpdateMsg = msgConstructor.constructDeviceUpdatedMsg(msgType, device);
DownlinkMsg.Builder builder = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addDeviceUpdateMsg(deviceUpdateMsg);
@ -247,19 +245,17 @@ public abstract class DeviceEdgeProcessor extends BaseDeviceProcessor implements
break;
case DELETED:
case UNASSIGNED_FROM_EDGE:
DeviceUpdateMsg deviceUpdateMsg = msgConstructor.constructDeviceDeleteMsg(deviceId);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addDeviceUpdateMsg(deviceUpdateMsg)
.addDeviceUpdateMsg(msgConstructor.constructDeviceDeleteMsg(deviceId))
.build();
break;
case CREDENTIALS_UPDATED:
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(edgeEvent.getTenantId(), deviceId);
if (deviceCredentials != null) {
DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = msgConstructor.constructDeviceCredentialsUpdatedMsg(deviceCredentials);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addDeviceCredentialsUpdateMsg(deviceCredentialsUpdateMsg)
.addDeviceCredentialsUpdateMsg(msgConstructor.constructDeviceCredentialsUpdatedMsg(deviceCredentials))
.build();
}
break;

2
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/edge/EdgeProcessor.java

@ -79,7 +79,7 @@ public class EdgeProcessor extends BaseEdgeProcessor {
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null));
futures.add(saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.EDGE, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, edgeId, null));
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE);
PageLink pageLink = new PageLink(1000);
PageData<User> pageData;
do {
pageData = userService.findCustomerUsers(tenantId, customerId, pageLink);

16
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/entityview/EntityViewEdgeProcessor.java

@ -104,27 +104,23 @@ public abstract class EntityViewEdgeProcessor extends BaseEntityViewProcessor im
public DownlinkMsg convertEntityViewEventToDownlink(EdgeEvent edgeEvent, EdgeVersion edgeVersion) {
EntityViewId entityViewId = new EntityViewId(edgeEvent.getEntityId());
DownlinkMsg downlinkMsg = null;
var msgConstructor = (EntityViewMsgConstructor) entityViewMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion);
switch (edgeEvent.getAction()) {
case ADDED, UPDATED, ASSIGNED_TO_EDGE, ASSIGNED_TO_CUSTOMER, UNASSIGNED_FROM_CUSTOMER -> {
EntityView entityView = entityViewService.findEntityViewById(edgeEvent.getTenantId(), entityViewId);
if (entityView != null) {
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
EntityViewUpdateMsg entityViewUpdateMsg = ((EntityViewMsgConstructor)
entityViewMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructEntityViewUpdatedMsg(msgType, entityView);
EntityViewUpdateMsg entityViewUpdateMsg = msgConstructor.constructEntityViewUpdatedMsg(msgType, entityView);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addEntityViewUpdateMsg(entityViewUpdateMsg)
.build();
}
}
case DELETED, UNASSIGNED_FROM_EDGE -> {
EntityViewUpdateMsg entityViewUpdateMsg = ((EntityViewMsgConstructor)
entityViewMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion)).constructEntityViewDeleteMsg(entityViewId);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addEntityViewUpdateMsg(entityViewUpdateMsg)
.build();
}
case DELETED, UNASSIGNED_FROM_EDGE -> downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addEntityViewUpdateMsg(msgConstructor.constructEntityViewDeleteMsg(entityViewId))
.build();
}
return downlinkMsg;
}

12
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/rule/RuleChainEdgeProcessor.java

@ -42,6 +42,7 @@ public class RuleChainEdgeProcessor extends BaseEdgeProcessor {
public DownlinkMsg convertRuleChainEventToDownlink(EdgeEvent edgeEvent, EdgeVersion edgeVersion) {
RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId());
DownlinkMsg downlinkMsg = null;
var msgConstructor = (RuleChainMsgConstructor) ruleChainMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion);
switch (edgeEvent.getAction()) {
case ADDED, UPDATED, ASSIGNED_TO_EDGE -> {
RuleChain ruleChain = ruleChainService.findRuleChainById(edgeEvent.getTenantId(), ruleChainId);
@ -58,9 +59,7 @@ public class RuleChainEdgeProcessor extends BaseEdgeProcessor {
isRoot = edge.getRootRuleChainId().equals(ruleChainId);
}
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
RuleChainUpdateMsg ruleChainUpdateMsg = ((RuleChainMsgConstructor)
ruleChainMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion))
.constructRuleChainUpdatedMsg(msgType, ruleChain, isRoot);
RuleChainUpdateMsg ruleChainUpdateMsg = msgConstructor.constructRuleChainUpdatedMsg(msgType, ruleChain, isRoot);
DownlinkMsg.Builder builder = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
@ -78,8 +77,7 @@ public class RuleChainEdgeProcessor extends BaseEdgeProcessor {
}
case DELETED, UNASSIGNED_FROM_EDGE -> downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addRuleChainUpdateMsg(((RuleChainMsgConstructor) ruleChainMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion))
.constructRuleChainDeleteMsg(ruleChainId))
.addRuleChainUpdateMsg(msgConstructor.constructRuleChainDeleteMsg(ruleChainId))
.build();
}
return downlinkMsg;
@ -89,11 +87,11 @@ public class RuleChainEdgeProcessor extends BaseEdgeProcessor {
RuleChainId ruleChainId = new RuleChainId(edgeEvent.getEntityId());
RuleChain ruleChain = ruleChainService.findRuleChainById(edgeEvent.getTenantId(), ruleChainId);
DownlinkMsg downlinkMsg = null;
var msgConstructor = (RuleChainMsgConstructor) ruleChainMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion);
if (ruleChain != null) {
RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(edgeEvent.getTenantId(), ruleChainId);
UpdateMsgType msgType = getUpdateMsgType(edgeEvent.getAction());
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = ((RuleChainMsgConstructor)
ruleChainMsgConstructorFactory.getMsgConstructorByEdgeVersion(edgeVersion))
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = msgConstructor
.constructRuleChainMetadataUpdatedMsg(edgeEvent.getTenantId(), msgType, ruleChainMetaData, edgeVersion);
if (ruleChainMetadataUpdateMsg != null) {
downlinkMsg = DownlinkMsg.newBuilder()

5
application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java

@ -16,6 +16,7 @@
package org.thingsboard.server.service.entitiy;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -53,7 +54,6 @@ import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.tenant.TenantService;
import javax.annotation.PostConstruct;
import java.util.Set;
@Component
@ -66,7 +66,7 @@ public class EntityStateSourcingListener {
@PostConstruct
public void init() {
log.info("EntityStateSourcingListener initiated");
log.debug("EntityStateSourcingListener initiated");
}
@TransactionalEventListener(fallbackExecution = true)
@ -264,4 +264,5 @@ public class EntityStateSourcingListener {
metaData.putValue("assignedFromTenantName", tenant.getName());
return metaData;
}
}

4
application/src/main/java/org/thingsboard/server/service/executors/PubSubRuleNodeExecutorProvider.java

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.service.executors;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@ -22,8 +24,6 @@ import org.thingsboard.common.util.ExecutorProvider;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.queue.util.TbRuleEngineComponent;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

2
application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperReprocessingService.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.service.housekeeper;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.context.annotation.Lazy;
@ -33,7 +34,6 @@ import org.thingsboard.server.queue.provider.TbCoreQueueFactory;
import org.thingsboard.server.queue.util.AfterStartUp;
import org.thingsboard.server.queue.util.TbCoreComponent;
import javax.annotation.PreDestroy;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

2
application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperService.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.service.housekeeper;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@ -35,7 +36,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.housekeeper.processor.HousekeeperTaskProcessor;
import org.thingsboard.server.service.housekeeper.stats.HousekeeperStatsService;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;
import java.util.Optional;

6
application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java

@ -17,6 +17,7 @@ package org.thingsboard.server.service.notification;
import com.google.common.util.concurrent.ListenableFuture;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -41,7 +42,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.executors.NotificationExecutorService;
import org.thingsboard.server.service.partition.AbstractPartitionBasedService;
import javax.annotation.PreDestroy;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -75,9 +75,7 @@ public class DefaultNotificationSchedulerService extends AbstractPartitionBasedS
@Override
protected Map<TopicPartitionInfo, List<ListenableFuture<?>>> onAddedPartitions(Set<TopicPartitionInfo> addedPartitions) {
PageDataIterable<NotificationRequest> notificationRequests = new PageDataIterable<>(pageLink -> {
return notificationRequestService.findScheduledNotificationRequests(pageLink);
}, 1000);
PageDataIterable<NotificationRequest> notificationRequests = new PageDataIterable<>(notificationRequestService::findScheduledNotificationRequests, 1000);
for (NotificationRequest notificationRequest : notificationRequests) {
TopicPartitionInfo requestPartition = partitionService.resolve(ServiceType.TB_CORE, notificationRequest.getTenantId(), notificationRequest.getId());
if (addedPartitions.contains(requestPartition)) {

4
application/src/main/java/org/thingsboard/server/service/subscription/SubscriptionSchedulerComponent.java

@ -15,13 +15,13 @@
*/
package org.thingsboard.server.service.subscription;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.Getter;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.queue.util.TbCoreComponent;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;

4
application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java

@ -22,6 +22,8 @@ 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.ByteString;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@ -102,8 +104,6 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;

3
application/src/main/resources/thingsboard.yml

@ -572,6 +572,9 @@ cache:
edges:
timeToLiveInMinutes: "${CACHE_SPECS_EDGES_TTL:1440}" # Edges cache TTL
maxSize: "${CACHE_SPECS_EDGES_MAX_SIZE:10000}" # 0 means the cache is disabled
relatedEdges:
timeToLiveInMinutes: "${CACHE_SPECS_RELATED_EDGES_TTL:1440}" # Related Edges cache TTL
maxSize: "${CACHE_SPECS_RELATED_EDGES_MAX_SIZE:10000}" # 0 means the cache is disabled
repositorySettings:
timeToLiveInMinutes: "${CACHE_SPECS_REPOSITORY_SETTINGS_TTL:1440}" # Repository settings cache TTL
maxSize: "${CACHE_SPECS_REPOSITORY_SETTINGS_MAX_SIZE:10000}" # 0 means the cache is disabled

4
application/src/test/java/org/thingsboard/server/cache/CaffeineCacheDefaultConfigurationTest.java

@ -41,10 +41,10 @@ public class CaffeineCacheDefaultConfigurationTest {
@Test
public void verifyTransactionAwareCacheManagerProxy() {
assertThat(cacheSpecsMap.getSpecs()).as("specs").isNotNull();
cacheSpecsMap.getSpecs().forEach((name, cacheSpecs)->assertThat(cacheSpecs).as("cache %s specs", name).isNotNull());
cacheSpecsMap.getSpecs().forEach((name, cacheSpecs) -> assertThat(cacheSpecs).as("cache %s specs", name).isNotNull());
SoftAssertions softly = new SoftAssertions();
cacheSpecsMap.getSpecs().forEach((name, cacheSpecs)->{
cacheSpecsMap.getSpecs().forEach((name, cacheSpecs) -> {
softly.assertThat(name).as("cache name").isNotEmpty();
softly.assertThat(cacheSpecs.getTimeToLiveInMinutes()).as("cache %s time to live", name).isGreaterThan(0);
softly.assertThat(cacheSpecs.getMaxSize()).as("cache %s max size", name).isGreaterThan(0);

2
application/src/test/java/org/thingsboard/server/edge/RelationEdgeTest.java

@ -31,8 +31,6 @@ import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.edge.v1.UplinkMsg;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@DaoSqlTest
public class RelationEdgeTest extends AbstractEdgeTest {

414
application/src/test/java/org/thingsboard/server/service/edge/rpc/constructor/RuleChainMsgConstructorTest.java

@ -1,414 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.constructor;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
import org.thingsboard.server.gen.edge.v1.RuleChainConnectionInfoProto;
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
import org.thingsboard.server.gen.edge.v1.RuleNodeProto;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMsgConstructorV1;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Slf4j
@ExtendWith(MockitoExtension.class)
public class RuleChainMsgConstructorTest {
private static final String RPC_CONNECTION_TYPE = "RPC";
private RuleChainMsgConstructorV1 ruleChainMsgConstructorV1;
private TenantId tenantId;
@BeforeEach
public void setup() {
ruleChainMsgConstructorV1 = new RuleChainMsgConstructorV1();
tenantId = new TenantId(UUID.randomUUID());
}
@Test
public void testConstructRuleChainMetadataUpdatedMsg_V_3_4_0() {
RuleChainId ruleChainId = new RuleChainId(UUID.randomUUID());
RuleChainMetaData ruleChainMetaData = createRuleChainMetaData(
ruleChainId, 3, createRuleNodes(ruleChainId), createConnections());
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =
ruleChainMsgConstructorV1.constructRuleChainMetadataUpdatedMsg(
tenantId,
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
ruleChainMetaData,
EdgeVersion.V_3_4_0);
assetV_3_3_3_and_V_3_4_0(ruleChainMetadataUpdateMsg);
assertCheckpointRuleNodeConfiguration(
ruleChainMetadataUpdateMsg.getNodesList(),
"{\"queueName\":\"HighPriority\"}");
}
@Test
public void testConstructRuleChainMetadataUpdatedMsg_V_3_3_3() {
RuleChainId ruleChainId = new RuleChainId(UUID.randomUUID());
RuleChainMetaData ruleChainMetaData = createRuleChainMetaData(
ruleChainId, 3, createRuleNodes(ruleChainId), createConnections());
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =
ruleChainMsgConstructorV1.constructRuleChainMetadataUpdatedMsg(
tenantId,
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
ruleChainMetaData,
EdgeVersion.V_3_3_3);
assetV_3_3_3_and_V_3_4_0(ruleChainMetadataUpdateMsg);
assertCheckpointRuleNodeConfiguration(
ruleChainMetadataUpdateMsg.getNodesList(),
"{\"queueName\":\"HighPriority\"}");
}
private void assetV_3_3_3_and_V_3_4_0(RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg) {
Assertions.assertEquals(3, ruleChainMetadataUpdateMsg.getFirstNodeIndex(), "First rule node index incorrect!");
Assertions.assertEquals(12, ruleChainMetadataUpdateMsg.getNodesCount(), "Nodes count incorrect!");
Assertions.assertEquals(13, ruleChainMetadataUpdateMsg.getConnectionsCount(), "Connections count incorrect!");
Assertions.assertEquals(0, ruleChainMetadataUpdateMsg.getRuleChainConnectionsCount(), "Rule chain connections count incorrect!");
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(3, 6, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(0));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(3, 10, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(1));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(3, 0, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(2));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 11, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(3));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 11, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(4));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 11, TbMsgType.ATTRIBUTES_UPDATED.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(5));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 7, TbMsgType.TO_SERVER_RPC_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(6));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 4, TbMsgType.POST_TELEMETRY_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(7));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 5, TbMsgType.POST_ATTRIBUTES_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(8));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 8, TbNodeConnectionType.OTHER), ruleChainMetadataUpdateMsg.getConnections(9));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 9, TbMsgType.RPC_CALL_FROM_SERVER_TO_DEVICE.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(10));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(7, 11, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(11));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(10, 9, RPC_CONNECTION_TYPE), ruleChainMetadataUpdateMsg.getConnections(12));
}
@Test
public void testConstructRuleChainMetadataUpdatedMsg_V_3_3_0() {
RuleChainId ruleChainId = new RuleChainId(UUID.randomUUID());
RuleChainMetaData ruleChainMetaData = createRuleChainMetaData(ruleChainId, 3, createRuleNodes(ruleChainId), createConnections());
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =
ruleChainMsgConstructorV1.constructRuleChainMetadataUpdatedMsg(
tenantId,
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
ruleChainMetaData,
EdgeVersion.V_3_3_0);
Assertions.assertEquals(2, ruleChainMetadataUpdateMsg.getFirstNodeIndex(),"First rule node index incorrect!");
Assertions.assertEquals(10, ruleChainMetadataUpdateMsg.getNodesCount(), "Nodes count incorrect!");
Assertions.assertEquals(10, ruleChainMetadataUpdateMsg.getConnectionsCount(),"Connections count incorrect!");
Assertions.assertEquals(1, ruleChainMetadataUpdateMsg.getRuleChainConnectionsCount(), "Rule chain connections count incorrect!");
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(2, 5, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(0));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(3, 9, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(1));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 9, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(2));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 9, TbMsgType.ATTRIBUTES_UPDATED.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(3));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 6, TbMsgType.TO_SERVER_RPC_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(4));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 3, TbMsgType.POST_TELEMETRY_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(5));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 4, TbMsgType.POST_ATTRIBUTES_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(6));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 7, TbNodeConnectionType.OTHER), ruleChainMetadataUpdateMsg.getConnections(7));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 8, TbMsgType.RPC_CALL_FROM_SERVER_TO_DEVICE.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(8));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 9, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(9));
RuleChainConnectionInfoProto ruleChainConnection = ruleChainMetadataUpdateMsg.getRuleChainConnections(0);
Assertions.assertEquals(2, ruleChainConnection.getFromIndex(), "From index incorrect!");
Assertions.assertEquals(TbNodeConnectionType.SUCCESS, ruleChainConnection.getType(), "Type index incorrect!");
Assertions.assertEquals("{\"description\":\"\",\"layoutX\":477,\"layoutY\":560,\"ruleChainNodeId\":\"rule-chain-node-UNDEFINED\"}",
ruleChainConnection.getAdditionalInfo(),"Additional info incorrect!");
Assertions.assertTrue(ruleChainConnection.getTargetRuleChainIdMSB() != 0,"Target rule chain id MSB incorrect!");
Assertions.assertTrue(ruleChainConnection.getTargetRuleChainIdLSB() != 0,"Target rule chain id LSB incorrect!");
assertCheckpointRuleNodeConfiguration(
ruleChainMetadataUpdateMsg.getNodesList(),
"{\"queueName\":\"HighPriority\"}");
}
@Test
public void testConstructRuleChainMetadataUpdatedMsg_V_3_3_0_inDifferentOrder() {
// same rule chain metadata, but different order of rule nodes
RuleChainId ruleChainId = new RuleChainId(UUID.randomUUID());
RuleChainMetaData ruleChainMetaData1 = createRuleChainMetaData(ruleChainId, 8, createRuleNodesInDifferentOrder(ruleChainId), createConnectionsInDifferentOrder());
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg =
ruleChainMsgConstructorV1.constructRuleChainMetadataUpdatedMsg(
tenantId,
UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE,
ruleChainMetaData1,
EdgeVersion.V_3_3_0);
Assertions.assertEquals(7, ruleChainMetadataUpdateMsg.getFirstNodeIndex(), "First rule node index incorrect!");
Assertions.assertEquals(10, ruleChainMetadataUpdateMsg.getNodesCount(),"Nodes count incorrect!");
Assertions.assertEquals(10, ruleChainMetadataUpdateMsg.getConnectionsCount(),"Connections count incorrect!");
Assertions.assertEquals(1, ruleChainMetadataUpdateMsg.getRuleChainConnectionsCount(),"Rule chain connections count incorrect!");
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(3, 0, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(0));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 0, TbMsgType.ATTRIBUTES_UPDATED.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(1));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 3, TbMsgType.TO_SERVER_RPC_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(2));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 6, TbMsgType.POST_TELEMETRY_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(3));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 5, TbMsgType.POST_ATTRIBUTES_REQUEST.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(4));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 2, TbNodeConnectionType.OTHER), ruleChainMetadataUpdateMsg.getConnections(5));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(4, 1, TbMsgType.RPC_CALL_FROM_SERVER_TO_DEVICE.getRuleNodeConnection()), ruleChainMetadataUpdateMsg.getConnections(6));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(5, 0, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(7));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(6, 0, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(8));
compareNodeConnectionInfoAndProto(createNodeConnectionInfo(7, 4, TbNodeConnectionType.SUCCESS), ruleChainMetadataUpdateMsg.getConnections(9));
RuleChainConnectionInfoProto ruleChainConnection = ruleChainMetadataUpdateMsg.getRuleChainConnections(0);
Assertions.assertEquals(7, ruleChainConnection.getFromIndex(),"From index incorrect!");
Assertions.assertEquals(TbNodeConnectionType.SUCCESS, ruleChainConnection.getType(), "Type index incorrect!");
Assertions.assertEquals( "{\"description\":\"\",\"layoutX\":477,\"layoutY\":560,\"ruleChainNodeId\":\"rule-chain-node-UNDEFINED\"}",
ruleChainConnection.getAdditionalInfo(), "Additional info incorrect!");
Assertions.assertTrue(ruleChainConnection.getTargetRuleChainIdMSB() != 0, "Target rule chain id MSB incorrect!");
Assertions.assertTrue(ruleChainConnection.getTargetRuleChainIdLSB() != 0, "Target rule chain id LSB incorrect!");
assertCheckpointRuleNodeConfiguration(
ruleChainMetadataUpdateMsg.getNodesList(),
"{\"queueName\":\"HighPriority\"}");
}
private void assertCheckpointRuleNodeConfiguration(List<RuleNodeProto> nodesList,
String expectedConfiguration) {
Optional<RuleNodeProto> checkpointRuleNodeOpt = nodesList.stream()
.filter(rn -> "org.thingsboard.rule.engine.flow.TbCheckpointNode".equals(rn.getType()))
.findFirst();
Assertions.assertTrue(checkpointRuleNodeOpt.isPresent());
RuleNodeProto checkpointRuleNode = checkpointRuleNodeOpt.get();
Assertions.assertEquals(expectedConfiguration, checkpointRuleNode.getConfiguration());
}
private void compareNodeConnectionInfoAndProto(NodeConnectionInfo expected, org.thingsboard.server.gen.edge.v1.NodeConnectionInfoProto actual) {
Assertions.assertEquals(expected.getFromIndex(), actual.getFromIndex());
Assertions.assertEquals(expected.getToIndex(), actual.getToIndex());
Assertions.assertEquals(expected.getType(), actual.getType());
}
private RuleChainMetaData createRuleChainMetaData(RuleChainId ruleChainId, Integer firstNodeIndex, List<RuleNode> nodes, List<NodeConnectionInfo> connections) {
RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();
ruleChainMetaData.setRuleChainId(ruleChainId);
ruleChainMetaData.setFirstNodeIndex(firstNodeIndex);
ruleChainMetaData.setNodes(nodes);
ruleChainMetaData.setConnections(connections);
ruleChainMetaData.setRuleChainConnections(null);
return ruleChainMetaData;
}
private List<NodeConnectionInfo> createConnections() {
List<NodeConnectionInfo> result = new ArrayList<>();
result.add(createNodeConnectionInfo(3, 6, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(3, 10, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(3, 0, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(4, 11, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(5, 11, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(6, 11, TbMsgType.ATTRIBUTES_UPDATED.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(6, 7, TbMsgType.TO_SERVER_RPC_REQUEST.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(6, 4, TbMsgType.POST_TELEMETRY_REQUEST.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(6, 5, TbMsgType.POST_ATTRIBUTES_REQUEST.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(6, 8, TbNodeConnectionType.OTHER));
result.add(createNodeConnectionInfo(6, 9, TbMsgType.RPC_CALL_FROM_SERVER_TO_DEVICE.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(7, 11, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(10, 9, RPC_CONNECTION_TYPE));
return result;
}
private NodeConnectionInfo createNodeConnectionInfo(int fromIndex, int toIndex, String type) {
NodeConnectionInfo result = new NodeConnectionInfo();
result.setFromIndex(fromIndex);
result.setToIndex(toIndex);
result.setType(type);
return result;
}
private List<RuleNode> createRuleNodes(RuleChainId ruleChainId) {
List<RuleNode> result = new ArrayList<>();
result.add(getOutputNode(ruleChainId));
result.add(getAcknowledgeNode(ruleChainId));
result.add(getCheckpointNode(ruleChainId));
result.add(getDeviceProfileNode(ruleChainId));
result.add(getSaveTimeSeriesNode(ruleChainId));
result.add(getSaveClientAttributesNode(ruleChainId));
result.add(getMessageTypeSwitchNode(ruleChainId));
result.add(getLogRpcFromDeviceNode(ruleChainId));
result.add(getLogOtherNode(ruleChainId));
result.add(getRpcCallRequestNode(ruleChainId));
result.add(getPushToAnalyticsNode(ruleChainId));
result.add(getPushToCloudNode(ruleChainId));
return result;
}
private RuleNode createRuleNode(RuleChainId ruleChainId, String type, String name, JsonNode configuration, JsonNode additionalInfo) {
RuleNode e = new RuleNode();
e.setRuleChainId(ruleChainId);
e.setType(type);
e.setName(name);
e.setDebugMode(false);
e.setConfiguration(configuration);
e.setAdditionalInfo(additionalInfo);
e.setId(new RuleNodeId(UUID.randomUUID()));
return e;
}
private List<NodeConnectionInfo> createConnectionsInDifferentOrder() {
List<NodeConnectionInfo> result = new ArrayList<>();
result.add(createNodeConnectionInfo(0, 2, RPC_CONNECTION_TYPE));
result.add(createNodeConnectionInfo(4, 1, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(5, 1, TbMsgType.ATTRIBUTES_UPDATED.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(5, 4, TbMsgType.TO_SERVER_RPC_REQUEST.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(5, 7, TbMsgType.POST_TELEMETRY_REQUEST.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(5, 6, TbMsgType.POST_ATTRIBUTES_REQUEST.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(5, 3, TbNodeConnectionType.OTHER));
result.add(createNodeConnectionInfo(5, 2, TbMsgType.RPC_CALL_FROM_SERVER_TO_DEVICE.getRuleNodeConnection()));
result.add(createNodeConnectionInfo(6, 1, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(7, 1, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(8, 11, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(8, 5, TbNodeConnectionType.SUCCESS));
result.add(createNodeConnectionInfo(8, 0, TbNodeConnectionType.SUCCESS));
return result;
}
private List<RuleNode> createRuleNodesInDifferentOrder(RuleChainId ruleChainId) {
List<RuleNode> result = new ArrayList<>();
result.add(getPushToAnalyticsNode(ruleChainId));
result.add(getPushToCloudNode(ruleChainId));
result.add(getRpcCallRequestNode(ruleChainId));
result.add(getLogOtherNode(ruleChainId));
result.add(getLogRpcFromDeviceNode(ruleChainId));
result.add(getMessageTypeSwitchNode(ruleChainId));
result.add(getSaveClientAttributesNode(ruleChainId));
result.add(getSaveTimeSeriesNode(ruleChainId));
result.add(getDeviceProfileNode(ruleChainId));
result.add(getCheckpointNode(ruleChainId));
result.add(getAcknowledgeNode(ruleChainId));
result.add(getOutputNode(ruleChainId));
return result;
}
private RuleNode getOutputNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.flow.TbRuleChainOutputNode",
"Output node",
JacksonUtil.toJsonNode("{\"version\":0}"),
JacksonUtil.toJsonNode("{\"description\":\"\",\"layoutX\":178,\"layoutY\":592}"));
}
private RuleNode getCheckpointNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.flow.TbCheckpointNode",
"Checkpoint node",
JacksonUtil.toJsonNode("{\"queueName\":\"HighPriority\"}"),
JacksonUtil.toJsonNode("{\"description\":\"\",\"layoutX\":178,\"layoutY\":647}"));
}
private RuleNode getSaveTimeSeriesNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
"Save Timeseries",
JacksonUtil.toJsonNode("{\"defaultTTL\":0}"),
JacksonUtil.toJsonNode("{\"layoutX\":823,\"layoutY\":157}"));
}
private RuleNode getMessageTypeSwitchNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
"Message Type Switch",
JacksonUtil.toJsonNode("{\"version\":0}"),
JacksonUtil.toJsonNode("{\"layoutX\":347,\"layoutY\":149}"));
}
private RuleNode getLogOtherNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.action.TbLogNode",
"Log Other",
JacksonUtil.toJsonNode("{\"jsScript\":\"return '\\\\nIncoming message:\\\\n' + JSON.stringify(msg) + '\\\\nIncoming metadata:\\\\n' + JSON.stringify(metadata);\"}"),
JacksonUtil.toJsonNode("{\"layoutX\":824,\"layoutY\":378}"));
}
private RuleNode getPushToCloudNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode",
"Push to cloud",
JacksonUtil.toJsonNode("{\"scope\":\"SERVER_SCOPE\"}"),
JacksonUtil.toJsonNode("{\"layoutX\":1129,\"layoutY\":52}"));
}
private RuleNode getAcknowledgeNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.flow.TbAckNode",
"Acknowledge node",
JacksonUtil.toJsonNode("{\"version\":0}"),
JacksonUtil.toJsonNode("{\"description\":\"\",\"layoutX\":177,\"layoutY\":703}"));
}
private RuleNode getDeviceProfileNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.profile.TbDeviceProfileNode",
"Device Profile Node",
JacksonUtil.toJsonNode("{\"persistAlarmRulesState\":false,\"fetchAlarmRulesStateOnStart\":false}"),
JacksonUtil.toJsonNode("{\"description\":\"Process incoming messages from devices with the alarm rules defined in the device profile. Dispatch all incoming messages with \\\"Success\\\" relation type.\",\"layoutX\":187,\"layoutY\":468}"));
}
private RuleNode getSaveClientAttributesNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
"Save Client Attributes",
JacksonUtil.toJsonNode("{\"scope\":\"CLIENT_SCOPE\"}"),
JacksonUtil.toJsonNode("{\"layoutX\":824,\"layoutY\":52}"));
}
private RuleNode getLogRpcFromDeviceNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.action.TbLogNode",
"Log RPC from Device",
JacksonUtil.toJsonNode("{\"jsScript\":\"return '\\\\nIncoming message:\\\\n' + JSON.stringify(msg) + '\\\\nIncoming metadata:\\\\n' + JSON.stringify(metadata);\"}"),
JacksonUtil.toJsonNode("{\"layoutX\":825,\"layoutY\":266}"));
}
private RuleNode getRpcCallRequestNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode",
"RPC Call Request",
JacksonUtil.toJsonNode("{\"timeoutInSeconds\":60}"),
JacksonUtil.toJsonNode("{\"layoutX\":824,\"layoutY\":466}"));
}
private RuleNode getPushToAnalyticsNode(RuleChainId ruleChainId) {
return createRuleNode(ruleChainId,
"org.thingsboard.rule.engine.flow.TbRuleChainInputNode",
"Push to Analytics",
JacksonUtil.toJsonNode("{\"ruleChainId\":\"af588000-6c7c-11ec-bafd-c9a47a5c8d99\"}"),
JacksonUtil.toJsonNode("{\"description\":\"\",\"layoutX\":477,\"layoutY\":560}"));
}
}

563
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessorTest.java

@ -1,563 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor;
import org.junit.jupiter.params.provider.Arguments;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.context.annotation.Lazy;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.TbResource;
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.DashboardId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.alarm.AlarmCommentService;
import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.asset.AssetProfileService;
import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceCredentialsService;
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.notification.NotificationRuleService;
import org.thingsboard.server.dao.notification.NotificationTargetService;
import org.thingsboard.server.dao.notification.NotificationTemplateService;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
import org.thingsboard.server.dao.ota.OtaPackageService;
import org.thingsboard.server.dao.queue.QueueService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.resource.ImageService;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.service.DataValidator;
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.dao.user.UserService;
import org.thingsboard.server.dao.widget.WidgetTypeService;
import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.service.edge.rpc.constructor.alarm.AlarmMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.alarm.AlarmMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.alarm.AlarmMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.asset.AssetMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.asset.AssetMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.asset.AssetMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.customer.CustomerMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.customer.CustomerMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.customer.CustomerMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.dashboard.DashboardMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.dashboard.DashboardMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.dashboard.DashboardMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.device.DeviceMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.device.DeviceMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.device.DeviceMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.edge.EdgeMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.entityview.EntityViewMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.entityview.EntityViewMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.entityview.EntityViewMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.notification.NotificationMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.oauth2.OAuth2MsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.ota.OtaPackageMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.ota.OtaPackageMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.ota.OtaPackageMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.queue.QueueMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.queue.QueueMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.queue.QueueMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.relation.RelationMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.relation.RelationMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.relation.RelationMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.resource.ResourceMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.resource.ResourceMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.resource.ResourceMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.rule.RuleChainMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.settings.AdminSettingsMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.settings.AdminSettingsMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.settings.AdminSettingsMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.telemetry.EntityDataMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.tenant.TenantMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.tenant.TenantMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.tenant.TenantMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.user.UserMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.user.UserMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.user.UserMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.constructor.widget.WidgetMsgConstructorFactory;
import org.thingsboard.server.service.edge.rpc.constructor.widget.WidgetMsgConstructorV1;
import org.thingsboard.server.service.edge.rpc.constructor.widget.WidgetMsgConstructorV2;
import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.alarm.AlarmEdgeProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.asset.AssetEdgeProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.asset.profile.AssetProfileEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.asset.profile.AssetProfileEdgeProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.dashboard.DashboardEdgeProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.device.DeviceEdgeProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileEdgeProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.entityview.EntityViewProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.notification.NotificationEdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.oauth2.OAuth2EdgeProcessor;
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.relation.RelationEdgeProcessorV2;
import org.thingsboard.server.service.edge.rpc.processor.resource.ResourceEdgeProcessorFactory;
import org.thingsboard.server.service.edge.rpc.processor.resource.ResourceEdgeProcessorV1;
import org.thingsboard.server.service.edge.rpc.processor.resource.ResourceEdgeProcessorV2;
import org.thingsboard.server.service.entitiy.TbLogEntityActionService;
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.service.profile.TbAssetProfileCache;
import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.state.DeviceStateService;
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
import java.util.UUID;
import java.util.stream.Stream;
public abstract class BaseEdgeProcessorTest {
@MockBean
protected TelemetrySubscriptionService tsSubService;
@MockBean
protected TbLogEntityActionService logEntityActionService;
@MockBean
protected RuleChainService ruleChainService;
@MockBean
protected AlarmService alarmService;
@MockBean
protected AlarmCommentService alarmCommentService;
@MockBean
protected DeviceService deviceService;
@MockBean
protected TbDeviceProfileCache deviceProfileCache;
@MockBean
protected TbAssetProfileCache assetProfileCache;
@MockBean
protected DashboardService dashboardService;
@MockBean
protected AssetService assetService;
@MockBean
protected EntityViewService entityViewService;
@MockBean
protected TenantService tenantService;
@MockBean
protected TenantProfileService tenantProfileService;
@MockBean
protected EdgeService edgeService;
@MockBean
protected CustomerService customerService;
@MockBean
protected UserService userService;
@MockBean
protected NotificationRuleService notificationRuleService;
@MockBean
protected NotificationTargetService notificationTargetService;
@MockBean
protected NotificationTemplateService notificationTemplateService;
@MockBean
protected DeviceProfileService deviceProfileService;
@MockBean
protected AssetProfileService assetProfileService;
@MockBean
protected RelationService relationService;
@MockBean
protected DeviceCredentialsService deviceCredentialsService;
@MockBean
protected AttributesService attributesService;
@MockBean
protected TimeseriesService timeseriesService;
@MockBean
protected TbClusterService tbClusterService;
@MockBean
protected DeviceStateService deviceStateService;
@MockBean
protected EdgeEventService edgeEventService;
@MockBean
protected WidgetsBundleService widgetsBundleService;
@MockBean
protected WidgetTypeService widgetTypeService;
@MockBean
protected OtaPackageService otaPackageService;
@MockBean
protected QueueService queueService;
@MockBean
protected PartitionService partitionService;
@MockBean
protected ResourceService resourceService;
@MockBean
protected OAuth2ClientService oAuth2ClientService;
@MockBean
@Lazy
protected TbQueueProducerProvider producerProvider;
@MockBean
protected DataValidator<Device> deviceValidator;
@MockBean
protected DataValidator<DeviceProfile> deviceProfileValidator;
@MockBean
protected DataValidator<Asset> assetValidator;
@MockBean
protected DataValidator<AssetProfile> assetProfileValidator;
@MockBean
protected DataValidator<Dashboard> dashboardValidator;
@MockBean
protected DataValidator<EntityView> entityViewValidator;
@MockBean
protected DataValidator<TbResource> resourceValidator;
@MockBean
protected EdgeMsgConstructor edgeMsgConstructor;
@MockBean
protected EntityDataMsgConstructor entityDataMsgConstructor;
@MockBean
protected AdminSettingsMsgConstructorV1 adminSettingsMsgConstructorV1;
@MockBean
protected AdminSettingsMsgConstructorV2 adminSettingsMsgConstructorV2;
@MockBean
protected AlarmMsgConstructorV1 alarmMsgConstructorV1;
@MockBean
protected AlarmMsgConstructorV2 alarmMsgConstructorV2;
@SpyBean
protected AssetMsgConstructorV1 assetMsgConstructorV1;
@SpyBean
protected AssetMsgConstructorV2 assetMsgConstructorV2;
@MockBean
protected CustomerMsgConstructorV1 customerMsgConstructorV1;
@MockBean
protected CustomerMsgConstructorV2 customerMsgConstructorV2;
@MockBean
protected DashboardMsgConstructorV1 dashboardMsgConstructorV1;
@MockBean
protected DashboardMsgConstructorV2 dashboardMsgConstructorV2;
@SpyBean
protected DeviceMsgConstructorV1 deviceMsgConstructorV1;
@SpyBean
protected DeviceMsgConstructorV2 deviceMsgConstructorV2;
@MockBean
protected EntityViewMsgConstructorV1 entityViewMsgConstructorV1;
@MockBean
protected EntityViewMsgConstructorV2 entityViewMsgConstructorV2;
@MockBean
protected OtaPackageMsgConstructorV1 otaPackageMsgConstructorV1;
@MockBean
protected OtaPackageMsgConstructorV2 otaPackageMsgConstructorV2;
@MockBean
protected QueueMsgConstructorV1 queueMsgConstructorV1;
@MockBean
protected QueueMsgConstructorV2 queueMsgConstructorV2;
@MockBean
protected RelationMsgConstructorV1 relationMsgConstructorV1;
@MockBean
protected RelationMsgConstructorV2 relationMsgConstructorV2;
@MockBean
protected ResourceMsgConstructorV1 resourceMsgConstructorV1;
@MockBean
protected ResourceMsgConstructorV2 resourceMsgConstructorV2;
@SpyBean
protected RuleChainMsgConstructorV1 ruleChainMsgConstructorV1;
@SpyBean
protected RuleChainMsgConstructorV2 ruleChainMsgConstructorV2;
@MockBean
protected TenantMsgConstructorV1 tenantMsgConstructorV1;
@MockBean
protected TenantMsgConstructorV2 tenantMsgConstructorV2;
@MockBean
protected UserMsgConstructorV1 userMsgConstructorV1;
@MockBean
protected UserMsgConstructorV2 userMsgConstructorV2;
@MockBean
protected WidgetMsgConstructorV1 widgetMsgConstructorV1;
@MockBean
protected WidgetMsgConstructorV2 widgetMsgConstructorV2;
@MockBean
protected NotificationMsgConstructor notificationMsgConstructor;
@MockBean
protected OAuth2MsgConstructor oAuth2MsgConstructor;
@MockBean
protected AlarmEdgeProcessorV1 alarmProcessorV1;
@MockBean
protected AlarmEdgeProcessorV2 alarmProcessorV2;
@SpyBean
protected AssetEdgeProcessorV1 assetProcessorV1;
@SpyBean
protected AssetEdgeProcessorV2 assetProcessorV2;
@SpyBean
protected AssetProfileEdgeProcessorV1 assetProfileProcessorV1;
@SpyBean
protected AssetProfileEdgeProcessorV2 assetProfileProcessorV2;
@MockBean
protected DashboardEdgeProcessorV1 dashboardProcessorV1;
@MockBean
protected DashboardEdgeProcessorV2 dashboardProcessorV2;
@MockBean
protected ImageService imageService;
@SpyBean
protected DeviceEdgeProcessorV1 deviceEdgeProcessorV1;
@SpyBean
protected DeviceEdgeProcessorV2 deviceEdgeProcessorV2;
@SpyBean
protected DeviceProfileEdgeProcessorV1 deviceProfileProcessorV1;
@SpyBean
protected DeviceProfileEdgeProcessorV2 deviceProfileProcessorV2;
@MockBean
protected EntityViewProcessorV1 entityViewProcessorV1;
@MockBean
protected EntityViewProcessorV2 entityViewProcessorV2;
@MockBean
protected ResourceEdgeProcessorV1 resourceEdgeProcessorV1;
@MockBean
protected ResourceEdgeProcessorV2 resourceEdgeProcessorV2;
@MockBean
protected RelationEdgeProcessorV1 relationEdgeProcessorV1;
@MockBean
protected RelationEdgeProcessorV2 relationEdgeProcessorV2;
@MockBean
protected OAuth2EdgeProcessor oAuth2EdgeProcessor;
@MockBean
protected NotificationEdgeProcessor notificationEdgeProcessor;
@SpyBean
protected RuleChainMsgConstructorFactory ruleChainMsgConstructorFactory;
@MockBean
protected AlarmMsgConstructorFactory alarmMsgConstructorFactory;
@SpyBean
protected DeviceMsgConstructorFactory deviceMsgConstructorFactory;
@SpyBean
protected AssetMsgConstructorFactory assetMsgConstructorFactory;
@MockBean
protected DashboardMsgConstructorFactory dashboardMsgConstructorFactory;
@MockBean
protected EntityViewMsgConstructorFactory entityViewMsgConstructorFactory;
@MockBean
protected RelationMsgConstructorFactory relationMsgConstructorFactory;
@MockBean
protected UserMsgConstructorFactory userMsgConstructorFactory;
@MockBean
protected CustomerMsgConstructorFactory customerMsgConstructorFactory;
@MockBean
protected TenantMsgConstructorFactory tenantMsgConstructorFactory;
@MockBean
protected WidgetMsgConstructorFactory widgetBundleMsgConstructorFactory;
@MockBean
protected AdminSettingsMsgConstructorFactory adminSettingsMsgConstructorFactory;
@MockBean
protected OtaPackageMsgConstructorFactory otaPackageMsgConstructorFactory;
@MockBean
protected QueueMsgConstructorFactory queueMsgConstructorFactory;
@MockBean
protected ResourceMsgConstructorFactory resourceMsgConstructorFactory;
@MockBean
protected AlarmEdgeProcessorFactory alarmEdgeProcessorFactory;
@SpyBean
protected AssetEdgeProcessorFactory assetEdgeProcessorFactory;
@MockBean
protected DashboardEdgeProcessorFactory dashboardEdgeProcessorFactory;
@SpyBean
protected DeviceEdgeProcessorFactory deviceEdgeProcessorFactory;
@MockBean
protected EntityViewProcessorFactory entityViewProcessorFactory;
@MockBean
protected RelationEdgeProcessorFactory relationEdgeProcessorFactory;
@MockBean
protected ResourceEdgeProcessorFactory resourceEdgeProcessorFactory;
@MockBean
protected EdgeSynchronizationManager edgeSynchronizationManager;
@MockBean
protected DbCallbackExecutorService dbCallbackExecutorService;
protected EdgeId edgeId;
protected TenantId tenantId;
protected EdgeEvent edgeEvent;
protected DashboardId getDashboardId(long expectedDashboardIdMSB, long expectedDashboardIdLSB) {
DashboardId dashboardId;
if (expectedDashboardIdMSB != 0 && expectedDashboardIdLSB != 0) {
dashboardId = new DashboardId(new UUID(expectedDashboardIdMSB, expectedDashboardIdLSB));
} else {
dashboardId = new DashboardId(UUID.randomUUID());
}
return dashboardId;
}
protected RuleChainId getRuleChainId(long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
RuleChainId ruleChainId;
if (expectedRuleChainIdMSB != 0 && expectedRuleChainIdLSB != 0) {
ruleChainId = new RuleChainId(new UUID(expectedRuleChainIdMSB, expectedRuleChainIdLSB));
} else {
ruleChainId = new RuleChainId(UUID.randomUUID());
}
return ruleChainId;
}
protected static Stream<Arguments> provideParameters() {
UUID dashboardUUID = UUID.randomUUID();
UUID ruleChainUUID = UUID.randomUUID();
return Stream.of(
Arguments.of(EdgeVersion.V_3_3_0, 0, 0, 0, 0),
Arguments.of(EdgeVersion.V_3_3_3, 0, 0, 0, 0),
Arguments.of(EdgeVersion.V_3_4_0, 0, 0, 0, 0),
Arguments.of(EdgeVersion.V_3_6_0,
dashboardUUID.getMostSignificantBits(),
dashboardUUID.getLeastSignificantBits(),
ruleChainUUID.getMostSignificantBits(),
ruleChainUUID.getLeastSignificantBits())
);
}
}

92
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/asset/AbstractAssetProcessorTest.java

@ -1,92 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor.asset;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
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.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.AssetProfileId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.RuleChainId;
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.service.edge.rpc.processor.BaseEdgeProcessorTest;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.BDDMockito.willReturn;
public abstract class AbstractAssetProcessorTest extends BaseEdgeProcessorTest {
protected AssetId assetId;
protected AssetProfileId assetProfileId;
protected AssetProfile assetProfile;
@BeforeEach
public void setUp() {
edgeId = new EdgeId(UUID.randomUUID());
tenantId = new TenantId(UUID.randomUUID());
assetId = new AssetId(UUID.randomUUID());
assetProfileId = new AssetProfileId(UUID.randomUUID());
assetProfile = new AssetProfile();
assetProfile.setId(assetProfileId);
assetProfile.setName("AssetProfile");
assetProfile.setDefault(true);
Asset asset = new Asset();
asset.setAssetProfileId(assetProfileId);
asset.setId(assetId);
asset.setName("Asset");
asset.setType(assetProfile.getName());
edgeEvent = new EdgeEvent();
edgeEvent.setTenantId(tenantId);
edgeEvent.setAction(EdgeEventActionType.ADDED);
willReturn(asset).given(assetService).findAssetById(tenantId, assetId);
willReturn(assetProfile).given(assetProfileService).findAssetProfileById(tenantId, assetProfileId);
}
protected void updateAssetProfileDefaultFields(long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
DashboardId dashboardId = getDashboardId(expectedDashboardIdMSB, expectedDashboardIdLSB);
RuleChainId ruleChainId = getRuleChainId(expectedRuleChainIdMSB, expectedRuleChainIdLSB);
assetProfile.setDefaultDashboardId(dashboardId);
assetProfile.setDefaultEdgeRuleChainId(ruleChainId);
}
protected void verify(DownlinkMsg downlinkMsg, long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
AssetProfileUpdateMsg assetProfileUpdateMsg = downlinkMsg.getAssetProfileUpdateMsgList().get(0);
assertNotNull(assetProfileUpdateMsg);
Assertions.assertThat(assetProfileUpdateMsg.getDefaultDashboardIdMSB()).isEqualTo(expectedDashboardIdMSB);
Assertions.assertThat(assetProfileUpdateMsg.getDefaultDashboardIdLSB()).isEqualTo(expectedDashboardIdLSB);
Assertions.assertThat(assetProfileUpdateMsg.getDefaultRuleChainIdMSB()).isEqualTo(expectedRuleChainIdMSB);
Assertions.assertThat(assetProfileUpdateMsg.getDefaultRuleChainIdLSB()).isEqualTo(expectedRuleChainIdLSB);
}
}

39
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetEdgeProcessorTest.java

@ -1,39 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor.asset;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.boot.test.context.SpringBootTest;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
@SpringBootTest(classes = {AssetEdgeProcessorV1.class})
class AssetEdgeProcessorTest extends AbstractAssetProcessorTest {
@ParameterizedTest
@MethodSource("provideParameters")
public void testAssetProfileDefaultFields_notSendToEdgeOlder3_6_0IfNotAssigned(EdgeVersion edgeVersion, long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
updateAssetProfileDefaultFields(expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
edgeEvent.setEntityId(assetId.getId());
DownlinkMsg downlinkMsg = assetProcessorV1.convertAssetEventToDownlink(edgeEvent, edgeId, edgeVersion);
verify(downlinkMsg, expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
}
}

40
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/asset/AssetProfileEdgeProcessorTest.java

@ -1,40 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor.asset;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.boot.test.context.SpringBootTest;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
@SpringBootTest(classes = {AssetEdgeProcessorV1.class})
class AssetProfileEdgeProcessorTest extends AbstractAssetProcessorTest{
@ParameterizedTest
@MethodSource("provideParameters")
public void testAssetProfileDefaultFields_notSendToEdgeOlder3_6_0IfNotAssigned(EdgeVersion edgeVersion, long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
updateAssetProfileDefaultFields(expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
edgeEvent.setEntityId(assetProfileId.getId());
DownlinkMsg downlinkMsg = assetProfileProcessorV1.convertAssetProfileEventToDownlink(edgeEvent, edgeId, edgeVersion);
verify(downlinkMsg, expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
}
}

102
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/AbstractDeviceProcessorTest.java

@ -1,102 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor.device;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
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.device.profile.DeviceProfileData;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessorTest;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.BDDMockito.willReturn;
public abstract class AbstractDeviceProcessorTest extends BaseEdgeProcessorTest {
protected DeviceId deviceId;
protected DeviceProfileId deviceProfileId;
protected DeviceProfile deviceProfile;
@BeforeEach
public void setUp() {
edgeId = new EdgeId(UUID.randomUUID());
tenantId = new TenantId(UUID.randomUUID());
deviceId = new DeviceId(UUID.randomUUID());
deviceProfileId = new DeviceProfileId(UUID.randomUUID());
deviceProfile = new DeviceProfile();
deviceProfile.setId(deviceProfileId);
deviceProfile.setName("DeviceProfile");
deviceProfile.setDefault(true);
deviceProfile.setType(DeviceProfileType.DEFAULT);
DeviceProfileData deviceProfileData = new DeviceProfileData();
deviceProfile.setProfileData(deviceProfileData);
deviceProfile.setTransportType(DeviceTransportType.DEFAULT);
DeviceCredentials deviceCredentials = new DeviceCredentials();
deviceCredentials.setDeviceId(deviceId);
Device device = new Device();
device.setDeviceProfileId(deviceProfileId);
device.setId(deviceId);
device.setName("Device");
device.setType(deviceProfile.getName());
edgeEvent = new EdgeEvent();
edgeEvent.setTenantId(tenantId);
edgeEvent.setAction(EdgeEventActionType.ADDED);
willReturn(device).given(deviceService).findDeviceById(tenantId, deviceId);
willReturn(deviceProfile).given(deviceProfileService).findDeviceProfileById(tenantId, deviceProfileId);
willReturn(deviceCredentials).given(deviceCredentialsService).findDeviceCredentialsByDeviceId(tenantId, deviceId);
}
protected void updateDeviceProfileDefaultFields(long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
DashboardId dashboardId = getDashboardId(expectedDashboardIdMSB, expectedDashboardIdLSB);
RuleChainId ruleChainId = getRuleChainId(expectedRuleChainIdMSB, expectedRuleChainIdLSB);
deviceProfile.setDefaultDashboardId(dashboardId);
deviceProfile.setDefaultEdgeRuleChainId(ruleChainId);
}
protected void verify(DownlinkMsg downlinkMsg, long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
DeviceProfileUpdateMsg deviceProfileUpdateMsg = downlinkMsg.getDeviceProfileUpdateMsgList().get(0);
assertNotNull(deviceProfileUpdateMsg);
Assertions.assertThat(deviceProfileUpdateMsg.getDefaultDashboardIdMSB()).isEqualTo(expectedDashboardIdMSB);
Assertions.assertThat(deviceProfileUpdateMsg.getDefaultDashboardIdLSB()).isEqualTo(expectedDashboardIdLSB);
Assertions.assertThat(deviceProfileUpdateMsg.getDefaultRuleChainIdMSB()).isEqualTo(expectedRuleChainIdMSB);
Assertions.assertThat(deviceProfileUpdateMsg.getDefaultRuleChainIdLSB()).isEqualTo(expectedRuleChainIdLSB);
}
}

38
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceEdgeProcessorTest.java

@ -1,38 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor.device;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.boot.test.context.SpringBootTest;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
@SpringBootTest(classes = {DeviceEdgeProcessorV1.class})
class DeviceEdgeProcessorTest extends AbstractDeviceProcessorTest {
@ParameterizedTest
@MethodSource("provideParameters")
public void testDeviceProfileDefaultFields_notSendToEdgeOlder3_6_0IfNotAssigned(EdgeVersion edgeVersion, long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
updateDeviceProfileDefaultFields(expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
edgeEvent.setEntityId(deviceId.getId());
DownlinkMsg downlinkMsg = deviceEdgeProcessorV1.convertDeviceEventToDownlink(edgeEvent, edgeId, edgeVersion);
verify(downlinkMsg, expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
}
}

41
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/device/DeviceProfileEdgeProcessorTest.java

@ -1,41 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor.device;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.boot.test.context.SpringBootTest;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.EdgeVersion;
import org.thingsboard.server.service.edge.rpc.processor.device.profile.DeviceProfileEdgeProcessorV1;
@SpringBootTest(classes = {DeviceProfileEdgeProcessorV1.class})
class DeviceProfileEdgeProcessorTest extends AbstractDeviceProcessorTest {
@ParameterizedTest
@MethodSource("provideParameters")
public void testDeviceProfileDefaultFields_notSendToEdgeOlder3_6_0IfNotAssigned(EdgeVersion edgeVersion, long expectedDashboardIdMSB, long expectedDashboardIdLSB,
long expectedRuleChainIdMSB, long expectedRuleChainIdLSB) {
updateDeviceProfileDefaultFields(expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
edgeEvent.setEntityId(deviceProfileId.getId());
DownlinkMsg downlinkMsg = deviceProfileProcessorV1.convertDeviceProfileEventToDownlink(edgeEvent, edgeId, edgeVersion);
verify(downlinkMsg, expectedDashboardIdMSB, expectedDashboardIdLSB, expectedRuleChainIdMSB, expectedRuleChainIdLSB);
}
}

66
application/src/test/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/TelemetryEdgeProcessorTest.java

@ -1,66 +0,0 @@
/**
* Copyright © 2016-2024 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.rpc.processor.telemetry;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessorTest;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {TelemetryEdgeProcessor.class})
@TestPropertySource(properties = {
"edges.rpc.max_telemetry_message_size=1000"
})
public class TelemetryEdgeProcessorTest extends BaseEdgeProcessorTest {
@SpyBean
private TelemetryEdgeProcessor telemetryEdgeProcessor;
@MockBean
private NotificationRuleProcessor notificationRuleProcessor;
@Test
public void testConvert_maxSizeLimit() {
Edge edge = new Edge();
EdgeEvent edgeEvent = new EdgeEvent();
ObjectNode body = JacksonUtil.newObjectNode();
body.put("value", StringUtils.randomAlphanumeric(1000));
edgeEvent.setBody(body);
DownlinkMsg downlinkMsg = telemetryEdgeProcessor.convertTelemetryEventToDownlink(edge, edgeEvent);
Assert.assertNull(downlinkMsg);
verify(notificationRuleProcessor, Mockito.times(1)).process(any());
}
}

1
application/src/test/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcServiceTest.java

@ -26,6 +26,7 @@ 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.gen.transport.TransportProtos;
import java.util.UUID;
import static org.mockito.BDDMockito.then;

5
common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java

@ -22,6 +22,7 @@ import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@ -30,6 +31,9 @@ import java.io.Serializable;
@Builder
public class DeviceCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 6366389552842340207L;
private final TenantId tenantId;
private final DeviceId deviceId;
private final String deviceName;
@ -56,4 +60,5 @@ public class DeviceCacheKey implements Serializable {
return tenantId + "_" + deviceId;
}
}
}

4
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeCacheEvictEvent.java → common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeCacheEvictEvent.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.edge;
package org.thingsboard.server.cache.edge;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@ -21,7 +21,7 @@ import org.thingsboard.server.common.data.id.TenantId;
@Data
@RequiredArgsConstructor
class EdgeCacheEvictEvent {
public class EdgeCacheEvictEvent {
private final TenantId tenantId;
private final String newName;

6
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeCacheKey.java → common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeCacheKey.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.edge;
package org.thingsboard.server.cache.edge;
import lombok.Builder;
import lombok.EqualsAndHashCode;
@ -21,6 +21,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@ -29,6 +30,9 @@ import java.io.Serializable;
@Builder
public class EdgeCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = -2299543993746815287L;
private final TenantId tenantId;
private final String name;

2
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeCaffeineCache.java → common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeCaffeineCache.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.edge;
package org.thingsboard.server.cache.edge;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;

3
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeRedisCache.java → common/cache/src/main/java/org/thingsboard/server/cache/edge/EdgeRedisCache.java

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.edge;
package org.thingsboard.server.cache.edge;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@ -32,4 +32,5 @@ public class EdgeRedisCache extends RedisTbTransactionalCache<EdgeCacheKey, Edge
public EdgeRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.EDGE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJsonRedisSerializer<>(Edge.class));
}
}

45
common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesCacheKey.java

@ -0,0 +1,45 @@
/**
* Copyright © 2016-2024 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.cache.edge;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@EqualsAndHashCode
@RequiredArgsConstructor
@Builder
public class RelatedEdgesCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 5118170671697650121L;
private final TenantId tenantId;
private final EntityId entityId;
@Override
public String toString() {
return tenantId + "_" + entityId;
}
}

37
common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesCacheValue.java

@ -0,0 +1,37 @@
/**
* Copyright © 2016-2024 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.cache.edge;
import lombok.Data;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.page.PageData;
import java.io.Serial;
import java.io.Serializable;
@Data
public class RelatedEdgesCacheValue implements Serializable {
@Serial
private static final long serialVersionUID = -2765080094748518572L;
private final PageData<EdgeId> pageData;
public RelatedEdgesCacheValue(PageData<EdgeId> pageData) {
this.pageData = pageData;
}
}

32
common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesCaffeineCache.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2024 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.cache.edge;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CaffeineTbTransactionalCache;
import org.thingsboard.server.common.data.CacheConstants;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@Service("RelatedEdgeIdsCache")
public class RelatedEdgesCaffeineCache extends CaffeineTbTransactionalCache<RelatedEdgesCacheKey, RelatedEdgesCacheValue> {
public RelatedEdgesCaffeineCache(CacheManager cacheManager) {
super(cacheManager, CacheConstants.RELATED_EDGES_CACHE);
}
}

30
common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesEvictEvent.java

@ -0,0 +1,30 @@
/**
* Copyright © 2016-2024 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.cache.edge;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
@Data
@RequiredArgsConstructor
public class RelatedEdgesEvictEvent {
private final TenantId tenantId;
private final EntityId entityId;
}

35
common/cache/src/main/java/org/thingsboard/server/cache/edge/RelatedEdgesRedisCache.java

@ -0,0 +1,35 @@
/**
* Copyright © 2016-2024 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.cache.edge;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CacheSpecsMap;
import org.thingsboard.server.cache.RedisTbTransactionalCache;
import org.thingsboard.server.cache.TBRedisCacheConfiguration;
import org.thingsboard.server.cache.TbJsonRedisSerializer;
import org.thingsboard.server.common.data.CacheConstants;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@Service("RelatedEdgeIdsCache")
public class RelatedEdgesRedisCache extends RedisTbTransactionalCache<RelatedEdgesCacheKey, RelatedEdgesCacheValue> {
public RelatedEdgesRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.RELATED_EDGES_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJsonRedisSerializer<>(RelatedEdgesCacheValue.class));
}
}

5
common/cache/src/main/java/org/thingsboard/server/cache/resourceInfo/ResourceInfoCacheKey.java

@ -22,6 +22,7 @@ import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.TbResourceId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@ -30,6 +31,9 @@ import java.io.Serializable;
@Builder
public class ResourceInfoCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 2100510964692846992L;
private final TenantId tenantId;
private final TbResourceId tbResourceId;
@ -37,4 +41,5 @@ public class ResourceInfoCacheKey implements Serializable {
public String toString() {
return tenantId + "_" + tbResourceId;
}
}

2
common/cluster-api/src/main/java/org/thingsboard/server/cluster/TbClusterService.java

@ -34,11 +34,11 @@ import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.RestApiCallResponseMsgProto;
import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.RestApiCallResponseMsgProto;
import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.queue.TbQueueClusterService;

4
common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java

@ -31,6 +31,7 @@ import org.thingsboard.server.dao.entity.EntityDaoService;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public interface EdgeService extends EntityDaoService {
@ -86,6 +87,8 @@ public interface EdgeService extends EntityDaoService {
PageData<Edge> findEdgesByTenantIdAndEntityId(TenantId tenantId, EntityId ruleChainId, PageLink pageLink);
PageData<EdgeId> findEdgeIdsByTenantIdAndEntityId(TenantId tenantId, EntityId ruleChainId, PageLink pageLink);
PageData<Edge> findEdgesByTenantProfileId(TenantProfileId tenantProfileId, PageLink pageLink);
List<EdgeId> findAllRelatedEdgeIds(TenantId tenantId, EntityId entityId);
@ -95,4 +98,5 @@ public interface EdgeService extends EntityDaoService {
String findMissingToRelatedRuleChains(TenantId tenantId, EdgeId edgeId, String tbRuleChainInputNodeClassName);
ListenableFuture<Boolean> isEdgeActiveAsync(TenantId tenantId, EdgeId edgeId, String activityState);
}

30
common/dao-api/src/main/java/org/thingsboard/server/dao/edge/RelatedEdgesService.java

@ -0,0 +1,30 @@
/**
* Copyright © 2016-2024 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.dao.edge;
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;
public interface RelatedEdgesService {
PageData<EdgeId> findEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, PageLink pageLink);
void publishRelatedEdgeIdsEvictEvent(TenantId tenantId, EntityId entityId);
}

1
common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java

@ -25,6 +25,7 @@ public class CacheConstants {
public static final String USER_CACHE = "users";
public static final String ENTITY_VIEW_CACHE = "entityViews";
public static final String EDGE_CACHE = "edges";
public static final String RELATED_EDGES_CACHE = "relatedEdges";
public static final String CLAIM_DEVICES_CACHE = "claimDevices";
public static final String SECURITY_SETTINGS_CACHE = "securitySettings";
public static final String TENANT_PROFILE_CACHE = "tenantProfiles";

2
common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java

@ -55,7 +55,7 @@ public class DataConstants {
public static final String TB_IMAGE_PREFIX = "tb-image;";
public static final String[] allScopes() {
public static String[] allScopes() {
return new String[]{CLIENT_SCOPE, SHARED_SCOPE, SERVER_SCOPE};
}

1
common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseAttributeKvEntry.java

@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.kv;
import jakarta.validation.Valid;
import lombok.Data;
import java.util.Optional;
/**

1
common/data/src/main/java/org/thingsboard/server/common/data/kv/BasicTsKvEntry.java

@ -18,7 +18,6 @@ package org.thingsboard.server.common.data.kv;
import jakarta.validation.Valid;
import lombok.Data;
import java.util.Objects;
import java.util.Optional;
@Data

2
common/data/src/main/java/org/thingsboard/server/common/data/page/PageDataIterableByTenantIdEntityId.java

@ -29,7 +29,6 @@ public class PageDataIterableByTenantIdEntityId<T> extends BasePageDataIterable<
this.function = function;
this.tenantId = tenantId;
this.entityId = entityId;
}
@Override
@ -40,4 +39,5 @@ public class PageDataIterableByTenantIdEntityId<T> extends BasePageDataIterable<
public interface FetchFunction<T> {
PageData<T> fetch(TenantId tenantId, EntityId entityId, PageLink link);
}
}

2
common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaSettings.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.queue.kafka;
import jakarta.annotation.PreDestroy;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@ -35,7 +36,6 @@ import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.TbProperty;
import org.thingsboard.server.queue.util.PropertyUtils;
import javax.annotation.PreDestroy;
import java.util.Collections;
import java.util.List;
import java.util.Map;

1
common/queue/src/test/java/org/thingsboard/server/queue/discovery/ZkDiscoveryServiceTest.java

@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.test.util.ReflectionTestUtils;

1
common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java

@ -22,7 +22,6 @@ import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.common.data.ApiUsageRecordKey;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;

2
common/script/script-api/src/main/java/org/thingsboard/script/api/ScriptStatCallback.java

@ -16,10 +16,10 @@
package org.thingsboard.script.api;
import com.google.common.util.concurrent.FutureCallback;
import jakarta.annotation.Nullable;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import jakarta.annotation.Nullable;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

4
common/script/script-api/src/main/java/org/thingsboard/script/api/js/NashornJsInvokeService.java

@ -20,6 +20,8 @@ import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import delight.nashornsandbox.NashornSandbox;
import delight.nashornsandbox.NashornSandboxes;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@ -31,8 +33,6 @@ import org.thingsboard.script.api.TbScriptException;
import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.common.stats.TbApiUsageStateClient;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

5
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java

@ -22,10 +22,11 @@ import com.google.common.hash.Hashing;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.mvel2.CompileException;
import org.mvel2.ExecutionContext;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
@ -46,8 +47,6 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.common.stats.TbApiUsageStateClient;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;

2
dao/src/main/java/org/thingsboard/server/dao/asset/AssetCacheKey.java

@ -21,6 +21,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@ -29,6 +30,7 @@ import java.io.Serializable;
@Builder
public class AssetCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 4196610233744512673L;
private final TenantId tenantId;

3
dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java

@ -19,11 +19,13 @@ import lombok.Data;
import org.thingsboard.server.common.data.id.AssetProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Data
public class AssetProfileCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 8220455917177676472L;
private final TenantId tenantId;
@ -60,4 +62,5 @@ public class AssetProfileCacheKey implements Serializable {
return tenantId + "_" + name;
}
}
}

4
dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java

@ -21,12 +21,15 @@ import lombok.Getter;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.id.EntityId;
import java.io.Serial;
import java.io.Serializable;
@EqualsAndHashCode
@Getter
@AllArgsConstructor
public class AttributeCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 2013369077925351881L;
private final AttributeScope scope;
@ -37,4 +40,5 @@ public class AttributeCacheKey implements Serializable {
public String toString() {
return "{" + entityId + "}" + scope + "_" + key;
}
}

1
dao/src/main/java/org/thingsboard/server/dao/attributes/BaseAttributesService.java

@ -24,7 +24,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EntityId;

10
dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java

@ -304,7 +304,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
if (customer == null) {
throw new DataValidationException("Can't unassign dashboards from non-existent customer!");
}
new CustomerDashboardsUnassigner(customer).removeEntities(tenantId, customer);
new CustomerDashboardsRemover(customer).removeEntities(tenantId, customer);
}
@Override
@ -413,11 +413,11 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
return EntityType.DASHBOARD;
}
private class CustomerDashboardsUnassigner extends PaginatedRemover<Customer, DashboardInfo> {
private class CustomerDashboardsRemover extends PaginatedRemover<Customer, DashboardInfo> {
private Customer customer;
private final Customer customer;
CustomerDashboardsUnassigner(Customer customer) {
CustomerDashboardsRemover(Customer customer) {
this.customer = customer;
}
@ -435,7 +435,7 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
private class CustomerDashboardsUpdater extends PaginatedRemover<Customer, DashboardInfo> {
private Customer customer;
private final Customer customer;
CustomerDashboardsUpdater(Customer customer) {
this.customer = customer;

3
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java

@ -20,11 +20,13 @@ import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Data
public class DeviceProfileCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 8220455917177676472L;
private final TenantId tenantId;
@ -71,4 +73,5 @@ public class DeviceProfileCacheKey implements Serializable {
}
return tenantId + "_" + name;
}
}

8
dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java

@ -612,12 +612,12 @@ public class DeviceServiceImpl extends CachedVersionedEntityService<DeviceCacheK
}
try {
createRelation(tenantId, new EntityRelation(edgeId, deviceId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE));
eventPublisher.publishEvent(ActionEntityEvent.builder().tenantId(tenantId).edgeId(edgeId).entityId(deviceId)
.actionType(ActionType.ASSIGNED_TO_EDGE).build());
} catch (Exception e) {
log.warn("[{}] Failed to create device relation. Edge Id: [{}]", deviceId, edgeId);
throw new RuntimeException(e);
}
eventPublisher.publishEvent(ActionEntityEvent.builder().tenantId(tenantId).edgeId(edgeId).entityId(deviceId)
.actionType(ActionType.ASSIGNED_TO_EDGE).build());
return device;
}
@ -633,12 +633,12 @@ public class DeviceServiceImpl extends CachedVersionedEntityService<DeviceCacheK
try {
deleteRelation(tenantId, new EntityRelation(edgeId, deviceId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE));
eventPublisher.publishEvent(ActionEntityEvent.builder().tenantId(tenantId).edgeId(edgeId).entityId(deviceId)
.actionType(ActionType.UNASSIGNED_FROM_EDGE).build());
} catch (Exception e) {
log.warn("[{}] Failed to delete device relation. Edge Id: [{}]", deviceId, edgeId);
throw new RuntimeException(e);
}
eventPublisher.publishEvent(ActionEntityEvent.builder().tenantId(tenantId).edgeId(edgeId).entityId(deviceId)
.actionType(ActionType.UNASSIGNED_FROM_EDGE).build());
return device;
}

62
dao/src/main/java/org/thingsboard/server/dao/edge/BaseRelatedEdgesService.java

@ -0,0 +1,62 @@
/**
* Copyright © 2016-2024 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.dao.edge;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.server.cache.edge.RelatedEdgesCacheKey;
import org.thingsboard.server.cache.edge.RelatedEdgesCacheValue;
import org.thingsboard.server.cache.edge.RelatedEdgesEvictEvent;
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;
import org.thingsboard.server.dao.entity.AbstractCachedEntityService;
@Service
public class BaseRelatedEdgesService extends AbstractCachedEntityService<RelatedEdgesCacheKey, RelatedEdgesCacheValue, RelatedEdgesEvictEvent> implements RelatedEdgesService {
public static final int RELATED_EDGES_CACHE_ITEMS = 1000;
public static final PageLink FIRST_PAGE = new PageLink(RELATED_EDGES_CACHE_ITEMS);
@Autowired
@Lazy
private EdgeService edgeService;
@TransactionalEventListener(classes = RelatedEdgesEvictEvent.class)
@Override
public void handleEvictEvent(RelatedEdgesEvictEvent event) {
cache.evict(new RelatedEdgesCacheKey(event.getTenantId(), event.getEntityId()));
}
@Override
public PageData<EdgeId> findEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, PageLink pageLink) {
if (!pageLink.equals(FIRST_PAGE)) {
return edgeService.findEdgeIdsByTenantIdAndEntityId(tenantId, entityId, pageLink);
}
return cache.getAndPutInTransaction(new RelatedEdgesCacheKey(tenantId, entityId),
() -> new RelatedEdgesCacheValue(edgeService.findEdgeIdsByTenantIdAndEntityId(tenantId, entityId, pageLink)), false).getPageData();
}
@Override
public void publishRelatedEdgeIdsEvictEvent(TenantId tenantId, EntityId entityId) {
publishEvictEvent(new RelatedEdgesEvictEvent(tenantId, entityId));
}
}

112
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeDao.java

@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeInfo;
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;
@ -35,147 +36,40 @@ import java.util.UUID;
*/
public interface EdgeDao extends Dao<Edge> {
/**
* Save or update edge object
*
* @param edge the edge object
* @return saved edge object
*/
Edge save(TenantId tenantId, Edge edge);
/**
* Find edge info by id.
*
* @param tenantId the tenant id
* @param edgeId the edge id
* @return the edge info object
*/
EdgeInfo findEdgeInfoById(TenantId tenantId, UUID edgeId);
/**
* Find edges by tenantId and page link.
*
* @param tenantId the tenantId
* @param pageLink the page link
* @return the list of edge objects
*/
PageData<Edge> findEdgesByTenantId(UUID tenantId, PageLink pageLink);
/**
* Find edges by tenantId, type and page link.
*
* @param tenantId the tenantId
* @param type the type
* @param pageLink the page link
* @return the list of edge objects
*/
PageData<Edge> findEdgesByTenantIdAndType(UUID tenantId, String type, PageLink pageLink);
/**
* Find edges by tenantId and edges Ids.
*
* @param tenantId the tenantId
* @param edgeIds the edge Ids
* @return the list of edge objects
*/
ListenableFuture<List<Edge>> findEdgesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> edgeIds);
/**
* Find edges by tenantId, customerId and page link.
*
* @param tenantId the tenantId
* @param customerId the customerId
* @param pageLink the page link
* @return the list of edge objects
*/
PageData<Edge> findEdgesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink);
/**
* Find edges by tenantId, customerId, type and page link.
*
* @param tenantId the tenantId
* @param customerId the customerId
* @param type the type
* @param pageLink the page link
* @return the list of edge objects
*/
PageData<Edge> findEdgesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink);
/**
* Find edge infos by tenantId, customerId and page link.
*
* @param tenantId the tenantId
* @param customerId the customerId
* @param pageLink the page link
* @return the list of edge info objects
*/
PageData<EdgeInfo> findEdgeInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink);
/**
* Find edge infos by tenantId, customerId, type and page link.
*
* @param tenantId the tenantId
* @param customerId the customerId
* @param type the type
* @param pageLink the page link
* @return the list of edge info objects
*/
PageData<EdgeInfo> findEdgeInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink);
/**
* Find edges by tenantId, customerId and edges Ids.
*
* @param tenantId the tenantId
* @param customerId the customerId
* @param edgeIds the edge Ids
* @return the list of edge objects
*/
ListenableFuture<List<Edge>> findEdgesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> edgeIds);
/**
* Find edges by tenantId and edge name.
*
* @param tenantId the tenantId
* @param name the edge name
* @return the optional edge object
*/
Optional<Edge> findEdgeByTenantIdAndName(UUID tenantId, String name);
/**
* Find tenants edge types.
*
* @return the list of tenant edge type objects
*/
ListenableFuture<List<EntitySubtype>> findTenantEdgeTypesAsync(UUID tenantId);
/**
* Find edge by routing Key.
*
* @param routingKey the edge routingKey
* @return the optional edge object
*/
Optional<Edge> findByRoutingKey(UUID tenantId, String routingKey);
PageData<EdgeInfo> findEdgeInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink);
PageData<EdgeInfo> findEdgeInfosByTenantId(UUID tenantId, PageLink pageLink);
/**
* Find edges by tenantId and entityId.
*
* @param tenantId the tenantId
* @param entityId the entityId
* @param entityType the entityType
* @return the list of edge objects
*/
PageData<Edge> findEdgesByTenantIdAndEntityId(UUID tenantId, UUID entityId, EntityType entityType, PageLink pageLink);
/**
* Find edges by tenantProfileId.
*
* @param tenantProfileId the tenantProfileId
* @return the list of edge objects
*/
PageData<EdgeId> findEdgeIdsByTenantIdAndEntityId(UUID tenantId, UUID entityId, EntityType entityType, PageLink pageLink);
PageData<Edge> findEdgesByTenantProfileId(UUID tenantProfileId, PageLink pageLink);
}

38
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java

@ -32,6 +32,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.edge.EdgeCacheEvictEvent;
import org.thingsboard.server.cache.edge.EdgeCacheKey;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
@ -82,6 +84,7 @@ import java.util.UUID;
import java.util.stream.Collectors;
import static org.thingsboard.server.dao.DaoUtil.toUUIDs;
import static org.thingsboard.server.dao.edge.BaseRelatedEdgesService.RELATED_EDGES_CACHE_ITEMS;
import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validateIds;
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
@ -122,6 +125,10 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
@Autowired
private JpaExecutorService executor;
@Autowired
@Lazy
private RelatedEdgesService relatedEdgesService;
@Value("${edges.enabled}")
@Getter
private boolean edgesEnabled;
@ -363,7 +370,7 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
log.trace("Executing unassignCustomerEdges, tenantId [{}], customerId [{}]", tenantId, customerId);
validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
validateId(customerId, id -> INCORRECT_CUSTOMER_ID + id);
customerEdgeUnassigner.removeEntities(tenantId, customerId);
customerEdgeRemover.removeEntities(tenantId, customerId);
}
@Override
@ -433,6 +440,14 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
return edgeDao.findEdgesByTenantIdAndEntityId(tenantId.getId(), entityId.getId(), entityId.getEntityType(), pageLink);
}
@Override
public PageData<EdgeId> findEdgeIdsByTenantIdAndEntityId(TenantId tenantId, EntityId entityId, PageLink pageLink) {
log.trace("Executing findEdgeIdsByTenantIdAndEntityId, tenantId [{}], entityId [{}], pageLink [{}]", tenantId, entityId, pageLink);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
validatePageLink(pageLink);
return edgeDao.findEdgeIdsByTenantIdAndEntityId(tenantId.getId(), entityId.getId(), entityId.getEntityType(), pageLink);
}
@Override
public PageData<Edge> findEdgesByTenantProfileId(TenantProfileId tenantProfileId, PageLink pageLink) {
log.trace("Executing findEdgesByTenantProfileId, tenantProfileId [{}], pageLink [{}]", tenantProfileId, pageLink);
@ -441,7 +456,7 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
return edgeDao.findEdgesByTenantProfileId(tenantProfileId.getId(), pageLink);
}
private PaginatedRemover<TenantId, Edge> tenantEdgesRemover =
private final PaginatedRemover<TenantId, Edge> tenantEdgesRemover =
new PaginatedRemover<>() {
@Override
@ -455,7 +470,7 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
}
};
private PaginatedRemover<CustomerId, Edge> customerEdgeUnassigner = new PaginatedRemover<>() {
private final PaginatedRemover<CustomerId, Edge> customerEdgeRemover = new PaginatedRemover<>() {
@Override
protected PageData<Edge> findEntities(TenantId tenantId, CustomerId id, PageLink pageLink) {
@ -477,7 +492,7 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
return Collections.singletonList(new EdgeId(entityId.getId()));
}
PageDataIterableByTenantIdEntityId<EdgeId> relatedEdgeIdsIterator =
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE);
new PageDataIterableByTenantIdEntityId<>(this::findRelatedEdgeIdsByEntityId, tenantId, entityId, RELATED_EDGES_CACHE_ITEMS);
List<EdgeId> result = new ArrayList<>();
for (EdgeId edgeId : relatedEdgeIdsIterator) {
result.add(edgeId);
@ -497,18 +512,17 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
case CUSTOMER:
return convertToEdgeIds(findEdgesByTenantIdAndCustomerId(tenantId, new CustomerId(entityId.getId()), pageLink));
case EDGE:
List<EdgeId> edgeIds = Collections.singletonList(new EdgeId(entityId.getId()));
return new PageData<>(edgeIds, 1, 1, false);
return new PageData<>(List.of(new EdgeId(entityId.getId())), 1, 1, false);
case DEVICE:
case ASSET:
case ENTITY_VIEW:
case DASHBOARD:
case RULE_CHAIN:
return convertToEdgeIds(findEdgesByTenantIdAndEntityId(tenantId, entityId, pageLink));
return relatedEdgesService.findEdgeIdsByEntityId(tenantId, entityId, pageLink);
case USER:
User userById = userService.findUserById(tenantId, new UserId(entityId.getId()));
if (userById == null) {
return createEmptyEdgeIdPageData();
return PageData.emptyPageData();
}
if (userById.getCustomerId() == null || userById.getCustomerId().isNullUid()) {
return convertToEdgeIds(findEdgesByTenantId(tenantId, pageLink));
@ -519,17 +533,13 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
return convertToEdgeIds(findEdgesByTenantProfileId(new TenantProfileId(entityId.getId()), pageLink));
default:
log.warn("[{}] Unsupported entity type {}", tenantId, entityId.getEntityType());
return createEmptyEdgeIdPageData();
return PageData.emptyPageData();
}
}
private PageData<EdgeId> createEmptyEdgeIdPageData() {
return new PageData<>(new ArrayList<>(), 0, 0, false);
}
private PageData<EdgeId> convertToEdgeIds(PageData<Edge> pageData) {
if (pageData == null) {
return createEmptyEdgeIdPageData();
return PageData.emptyPageData();
}
List<EdgeId> edgeIds = new ArrayList<>();
if (pageData.getData() != null && !pageData.getData().isEmpty()) {

2
dao/src/main/java/org/thingsboard/server/dao/entity/EntityCountCacheKey.java

@ -21,6 +21,7 @@ import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@ -28,6 +29,7 @@ import java.io.Serializable;
@RequiredArgsConstructor
public class EntityCountCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = -1992105662738434178L;
private final TenantId tenantId;

4
dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java

@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@ -29,6 +30,9 @@ import java.io.Serializable;
@Builder
public class EntityViewCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 5986277528222738163L;
private final TenantId tenantId;
private final String name;
private final EntityId entityId;

6
dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java

@ -157,7 +157,7 @@ public class EntityViewServiceImpl extends CachedVersionedEntityService<EntityVi
log.trace("Executing unassignCustomerEntityViews, tenantId [{}], customerId [{}]", tenantId, customerId);
validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
validateId(customerId, id -> INCORRECT_CUSTOMER_ID + id);
customerEntityViewsUnAssigner.removeEntities(tenantId, customerId);
customerEntityViewsRemover.removeEntities(tenantId, customerId);
}
@Override
@ -450,7 +450,7 @@ public class EntityViewServiceImpl extends CachedVersionedEntityService<EntityVi
return entityViewDao.findEntityViewsByTenantIdAndEdgeIdAndType(tenantId.getId(), edgeId.getId(), type, pageLink);
}
private PaginatedRemover<TenantId, EntityView> tenantEntityViewRemover = new PaginatedRemover<TenantId, EntityView>() {
private final PaginatedRemover<TenantId, EntityView> tenantEntityViewRemover = new PaginatedRemover<>() {
@Override
protected PageData<EntityView> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
return entityViewDao.findEntityViewsByTenantId(id.getId(), pageLink);
@ -462,7 +462,7 @@ public class EntityViewServiceImpl extends CachedVersionedEntityService<EntityVi
}
};
private PaginatedRemover<CustomerId, EntityView> customerEntityViewsUnAssigner = new PaginatedRemover<CustomerId, EntityView>() {
private final PaginatedRemover<CustomerId, EntityView> customerEntityViewsRemover = new PaginatedRemover<>() {
@Override
protected PageData<EntityView> findEntities(TenantId tenantId, CustomerId id, PageLink pageLink) {
return entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(), id.getId(), pageLink);

4
dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageCacheKey.java

@ -21,6 +21,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.OtaPackageId;
import java.io.Serial;
import java.io.Serializable;
@Getter
@ -29,6 +30,9 @@ import java.io.Serializable;
@Builder
public class OtaPackageCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 6733960018642945642L;
private final OtaPackageId id;
@Override

2
dao/src/main/java/org/thingsboard/server/dao/relation/RelationCacheKey.java

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import java.io.Serial;
import java.io.Serializable;
@EqualsAndHashCode
@ -31,6 +32,7 @@ import java.io.Serializable;
@Builder
public class RelationCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 3911151843961657570L;
private final EntityId from;

2
dao/src/main/java/org/thingsboard/server/dao/relation/RelationDao.java

@ -22,7 +22,6 @@ import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.RuleChainType;
import java.util.Collection;
import java.util.List;
/**
@ -71,4 +70,5 @@ public interface RelationDao {
List<EntityRelation> deleteInboundRelations(TenantId tenantId, EntityId entity, RelationTypeGroup relationTypeGroup);
List<EntityRelation> findRuleNodeToRuleChainRelations(RuleChainType ruleChainType, int limit);
}

11
dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeRepository.java

@ -120,6 +120,16 @@ public interface EdgeRepository extends JpaRepository<EdgeEntity, UUID> {
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT ee.id FROM EdgeEntity ee, RelationEntity re WHERE ee.tenantId = :tenantId " +
"AND ee.id = re.fromId AND re.fromType = 'EDGE' AND re.relationTypeGroup = 'EDGE' " +
"AND re.relationType = 'Contains' AND re.toId = :entityId AND re.toType = :entityType " +
"AND (:textSearch IS NULL OR ilike(ee.name, CONCAT('%', :textSearch, '%')) = true)")
Page<UUID> findIdsByTenantIdAndEntityId(@Param("tenantId") UUID tenantId,
@Param("entityId") UUID entityId,
@Param("entityType") String entityType,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT ee FROM EdgeEntity ee, TenantEntity te WHERE ee.tenantId = te.id AND te.tenantProfileId = :tenantProfileId ")
Page<EdgeEntity> findByTenantProfileId(@Param("tenantProfileId") UUID tenantProfileId,
Pageable pageable);
@ -134,4 +144,5 @@ public interface EdgeRepository extends JpaRepository<EdgeEntity, UUID> {
List<EdgeEntity> findEdgesByTenantIdAndIdIn(UUID tenantId, List<UUID> edgeIds);
EdgeEntity findByRoutingKey(String routingKey);
}

13
dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java

@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeInfo;
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;
@ -183,6 +184,18 @@ public class JpaEdgeDao extends JpaAbstractDao<EdgeEntity, Edge> implements Edge
DaoUtil.toPageable(pageLink)));
}
@Override
public PageData<EdgeId> findEdgeIdsByTenantIdAndEntityId(UUID tenantId, UUID entityId, EntityType entityType, PageLink pageLink) {
log.debug("Try to find edge ids by tenantId [{}], entityId [{}], entityType [{}], pageLink [{}]", tenantId, entityId, entityType, pageLink);
return DaoUtil.pageToPageData(
edgeRepository.findIdsByTenantIdAndEntityId(
tenantId,
entityId,
entityType.name(),
pageLink.getTextSearch(),
DaoUtil.toPageable(pageLink))).mapData(EdgeId::fromUUID);
}
@Override
public PageData<Edge> findEdgesByTenantProfileId(UUID tenantProfileId, PageLink pageLink) {
log.debug("Try to find edges by tenantProfileId [{}], pageLink [{}]", tenantProfileId, pageLink);

3
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileCacheKey.java

@ -18,11 +18,13 @@ package org.thingsboard.server.dao.tenant;
import lombok.Data;
import org.thingsboard.server.common.data.id.TenantProfileId;
import java.io.Serial;
import java.io.Serializable;
@Data
public class TenantProfileCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 8220455917177676472L;
private final TenantProfileId tenantProfileId;
@ -50,4 +52,5 @@ public class TenantProfileCacheKey implements Serializable {
return tenantProfileId.toString();
}
}
}

4
dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java

@ -18,7 +18,6 @@ package org.thingsboard.server.dao.timeseries;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.id.EntityId;
import java.io.Serial;
@ -28,6 +27,8 @@ import java.io.Serializable;
@Getter
@AllArgsConstructor
public class TsLatestCacheKey implements Serializable {
@Serial
private static final long serialVersionUID = 2024369077925351881L;
private final EntityId entityId;
@ -37,4 +38,5 @@ public class TsLatestCacheKey implements Serializable {
public String toString() {
return "{" + entityId + "}" + key;
}
}

4
dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java

@ -42,8 +42,8 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTra
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.event.RuleNodeDebugEvent;
import org.thingsboard.server.common.data.housekeeper.TenantEntitiesDeletionHousekeeperTask;
import org.thingsboard.server.common.data.housekeeper.HousekeeperTaskType;
import org.thingsboard.server.common.data.housekeeper.TenantEntitiesDeletionHousekeeperTask;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
@ -55,12 +55,12 @@ import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.msg.housekeeper.HousekeeperClient;
import org.thingsboard.server.dao.audit.AuditLogLevelFilter;
import org.thingsboard.server.dao.audit.AuditLogLevelMask;
import org.thingsboard.server.dao.audit.AuditLogLevelProperties;
import org.thingsboard.server.dao.entity.EntityDaoService;
import org.thingsboard.server.dao.entity.EntityServiceRegistry;
import org.thingsboard.server.common.msg.housekeeper.HousekeeperClient;
import org.thingsboard.server.dao.tenant.TenantService;
import java.io.IOException;

10
dao/src/test/java/org/thingsboard/server/dao/service/EntityServiceTest.java

@ -18,28 +18,19 @@ package org.thingsboard.server.dao.service;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
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.StringUtils;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
@ -108,7 +99,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

2
dao/src/test/java/org/thingsboard/server/dao/service/QueueStatsServiceTest.java

@ -30,8 +30,6 @@ import org.thingsboard.server.common.data.queue.QueueStats;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.queue.QueueStatsService;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;

3
dao/src/test/resources/application-test.properties

@ -75,6 +75,9 @@ cache.specs.otaPackagesData.maxSize=100000
cache.specs.edges.timeToLiveInMinutes=1440
cache.specs.edges.maxSize=100000
cache.specs.relatedEdges.timeToLiveInMinutes=1440
cache.specs.relatedEdges.maxSize=100000
cache.specs.notificationRules.timeToLiveInMinutes=1440
cache.specs.notificationRules.maxSize=10000

6
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java

@ -40,6 +40,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static org.thingsboard.server.dao.edge.BaseRelatedEdgesService.RELATED_EDGES_CACHE_ITEMS;
@Slf4j
@RuleNode(
type = ComponentType.ACTION,
@ -66,8 +68,6 @@ import java.util.UUID;
)
public class TbMsgPushToEdgeNode extends AbstractTbMsgPushNode<TbMsgPushToEdgeNodeConfiguration, EdgeEvent, EdgeEventType> {
static final int DEFAULT_PAGE_SIZE = 100;
@Override
EdgeEvent buildEvent(TenantId tenantId, EdgeEventActionType eventAction, UUID entityId,
EdgeEventType eventType, JsonNode entityBody) {
@ -122,7 +122,7 @@ public class TbMsgPushToEdgeNode extends AbstractTbMsgPushNode<TbMsgPushToEdgeNo
} else {
List<ListenableFuture<Void>> futures = new ArrayList<>();
PageDataIterableByTenantIdEntityId<EdgeId> edgeIds = new PageDataIterableByTenantIdEntityId<>(
ctx.getEdgeService()::findRelatedEdgeIdsByEntityId, ctx.getTenantId(), msg.getOriginator(), DEFAULT_PAGE_SIZE);
ctx.getEdgeService()::findRelatedEdgeIdsByEntityId, ctx.getTenantId(), msg.getOriginator(), RELATED_EDGES_CACHE_ITEMS);
for (EdgeId edgeId : edgeIds) {
EdgeEvent edgeEvent = buildEvent(msg, ctx);
futures.add(notifyEdge(ctx, edgeEvent, edgeId));

2
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/aws/sns/TbSnsNodeTest.java

@ -50,9 +50,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.never;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.verifyNoMoreInteractions;
@ExtendWith(MockitoExtension.class)

2
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNodeTest.java

@ -54,9 +54,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.mock;
import static org.mockito.BDDMockito.never;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.verifyNoMoreInteractions;
@ExtendWith(MockitoExtension.class)

2
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java

@ -16,8 +16,8 @@
package org.thingsboard.rule.engine.credentials;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

5
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNodeTest.java

@ -49,6 +49,7 @@ import java.util.UUID;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.thingsboard.server.dao.edge.BaseRelatedEdgesService.RELATED_EDGES_CACHE_ITEMS;
@ExtendWith(MockitoExtension.class)
public class TbMsgPushToEdgeNodeTest {
@ -82,7 +83,7 @@ public class TbMsgPushToEdgeNodeTest {
public void ackMsgInCaseNoEdgeRelated() {
Mockito.when(ctx.getTenantId()).thenReturn(tenantId);
Mockito.when(ctx.getEdgeService()).thenReturn(edgeService);
Mockito.when(edgeService.findRelatedEdgeIdsByEntityId(tenantId, deviceId, new PageLink(TbMsgPushToEdgeNode.DEFAULT_PAGE_SIZE))).thenReturn(new PageData<>());
Mockito.when(edgeService.findRelatedEdgeIdsByEntityId(tenantId, deviceId, new PageLink(RELATED_EDGES_CACHE_ITEMS))).thenReturn(new PageData<>());
TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, deviceId, TbMsgMetaData.EMPTY,
TbMsgDataType.JSON, TbMsg.EMPTY_JSON_OBJECT, null, null);
@ -103,7 +104,7 @@ public class TbMsgPushToEdgeNodeTest {
UserId userId = new UserId(UUID.randomUUID());
EdgeId edgeId = new EdgeId(UUID.randomUUID());
PageData<EdgeId> edgePageData = new PageData<>(List.of(edgeId), 1, 1, false);
Mockito.when(edgeService.findRelatedEdgeIdsByEntityId(tenantId, userId, new PageLink(TbMsgPushToEdgeNode.DEFAULT_PAGE_SIZE))).thenReturn(edgePageData);
Mockito.when(edgeService.findRelatedEdgeIdsByEntityId(tenantId, userId, new PageLink(RELATED_EDGES_CACHE_ITEMS))).thenReturn(edgePageData);
TbMsg msg = TbMsg.newMsg(TbMsgType.ATTRIBUTES_UPDATED, userId, TbMsgMetaData.EMPTY,
TbMsgDataType.JSON, TbMsg.EMPTY_JSON_OBJECT, null, null);

1
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNodeTest.java

@ -17,6 +17,7 @@ package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.Futures;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

1
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java

@ -35,7 +35,6 @@ import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.util.TbMsgSource;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;

1
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java

@ -37,7 +37,6 @@ import org.thingsboard.rule.engine.util.TbMsgSource;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.Tenant;

2
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java

@ -15,9 +15,9 @@
*/
package org.thingsboard.rule.engine.metadata;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.api.TbNodeConfiguration;

1
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java

@ -33,7 +33,6 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration;
import org.thingsboard.rule.engine.api.TbNodeException;
import org.thingsboard.rule.engine.util.TbMsgSource;
import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId;

1
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java

@ -53,7 +53,6 @@ import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.willCallRealMethod;
import static org.mockito.Mockito.mock;

Loading…
Cancel
Save