Commit d0295ef3530c812b3be404a1a82db4d23e912212

Authored by yefimov-andrey
Committed by Igor Kulikov
1 parent 2945655d

Feature/fetch last level only (#1922)

* adding fetching only last level of relations

* further implementaion of fetching last level

* implementation of fetching last level

* implementation of fetching last level

* draft of fetching only last level

* removal of unnecessary new method

* cleanup and formatting

* cleanup and formatting

* formatting

* formatting

* formatting

* final version of fetching only last level, the boolean added to the relation search parameters

* fetchLastLevelOnly added to some more search queries

* fixed tests to include fetchLastLevelOnly parameter

* removed unnecessary use of fetchLastLevelOnly parameter

* removed default value of fetchLastLevelOnly
@@ -35,17 +35,19 @@ public class RelationsSearchParameters { @@ -35,17 +35,19 @@ public class RelationsSearchParameters {
35 private EntitySearchDirection direction; 35 private EntitySearchDirection direction;
36 private RelationTypeGroup relationTypeGroup; 36 private RelationTypeGroup relationTypeGroup;
37 private int maxLevel = 1; 37 private int maxLevel = 1;
  38 + private boolean fetchLastLevelOnly;
38 39
39 - public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel) {  
40 - this(entityId, direction, maxLevel, RelationTypeGroup.COMMON); 40 + public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, boolean fetchLastLevelOnly) {
  41 + this(entityId, direction, maxLevel, RelationTypeGroup.COMMON, fetchLastLevelOnly);
41 } 42 }
42 43
43 - public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, RelationTypeGroup relationTypeGroup) { 44 + public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, RelationTypeGroup relationTypeGroup, boolean fetchLastLevelOnly) {
44 this.rootId = entityId.getId(); 45 this.rootId = entityId.getId();
45 this.rootType = entityId.getEntityType(); 46 this.rootType = entityId.getEntityType();
46 this.direction = direction; 47 this.direction = direction;
47 this.maxLevel = maxLevel; 48 this.maxLevel = maxLevel;
48 this.relationTypeGroup = relationTypeGroup; 49 this.relationTypeGroup = relationTypeGroup;
  50 + this.fetchLastLevelOnly = fetchLastLevelOnly;
49 } 51 }
50 52
51 public EntityId getEntityId() { 53 public EntityId getEntityId() {
@@ -153,7 +153,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ @@ -153,7 +153,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
153 153
154 private List<EntityId> getParentEntities(Alarm alarm) throws InterruptedException, ExecutionException { 154 private List<EntityId> getParentEntities(Alarm alarm) throws InterruptedException, ExecutionException {
155 EntityRelationsQuery query = new EntityRelationsQuery(); 155 EntityRelationsQuery query = new EntityRelationsQuery();
156 - query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); 156 + query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE, false));
157 return relationService.findByQuery(alarm.getTenantId(), query).get().stream().map(EntityRelation::getFrom).collect(Collectors.toList()); 157 return relationService.findByQuery(alarm.getTenantId(), query).get().stream().map(EntityRelation::getFrom).collect(Collectors.toList());
158 } 158 }
159 159
@@ -26,7 +26,6 @@ import org.springframework.cache.annotation.Cacheable; @@ -26,7 +26,6 @@ import org.springframework.cache.annotation.Cacheable;
26 import org.springframework.cache.annotation.Caching; 26 import org.springframework.cache.annotation.Caching;
27 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
28 import org.springframework.util.StringUtils; 28 import org.springframework.util.StringUtils;
29 -import org.thingsboard.server.common.data.Tenant;  
30 import org.thingsboard.server.common.data.id.EntityId; 29 import org.thingsboard.server.common.data.id.EntityId;
31 import org.thingsboard.server.common.data.id.TenantId; 30 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.common.data.relation.EntityRelation; 31 import org.thingsboard.server.common.data.relation.EntityRelation;
@@ -443,6 +442,7 @@ public class BaseRelationService implements RelationService { @@ -443,6 +442,7 @@ public class BaseRelationService implements RelationService {
443 442
444 @Override 443 @Override
445 public ListenableFuture<List<EntityRelation>> findByQuery(TenantId tenantId, EntityRelationsQuery query) { 444 public ListenableFuture<List<EntityRelation>> findByQuery(TenantId tenantId, EntityRelationsQuery query) {
  445 + //boolean fetchLastLevelOnly = true;
446 log.trace("Executing findByQuery [{}]", query); 446 log.trace("Executing findByQuery [{}]", query);
447 RelationsSearchParameters params = query.getParameters(); 447 RelationsSearchParameters params = query.getParameters();
448 final List<EntityTypeFilter> filters = query.getFilters(); 448 final List<EntityTypeFilter> filters = query.getFilters();
@@ -453,7 +453,7 @@ public class BaseRelationService implements RelationService { @@ -453,7 +453,7 @@ public class BaseRelationService implements RelationService {
453 int maxLvl = params.getMaxLevel() > 0 ? params.getMaxLevel() : Integer.MAX_VALUE; 453 int maxLvl = params.getMaxLevel() > 0 ? params.getMaxLevel() : Integer.MAX_VALUE;
454 454
455 try { 455 try {
456 - ListenableFuture<Set<EntityRelation>> relationSet = findRelationsRecursively(tenantId, params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, new ConcurrentHashMap<>()); 456 + ListenableFuture<Set<EntityRelation>> relationSet = findRelationsRecursively(tenantId, params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, params.isFetchLastLevelOnly(), new ConcurrentHashMap<>());
457 return Futures.transform(relationSet, input -> { 457 return Futures.transform(relationSet, input -> {
458 List<EntityRelation> relations = new ArrayList<>(); 458 List<EntityRelation> relations = new ArrayList<>();
459 if (filters == null || filters.isEmpty()) { 459 if (filters == null || filters.isEmpty()) {
@@ -570,7 +570,7 @@ public class BaseRelationService implements RelationService { @@ -570,7 +570,7 @@ public class BaseRelationService implements RelationService {
570 } 570 }
571 571
572 private ListenableFuture<Set<EntityRelation>> findRelationsRecursively(final TenantId tenantId, final EntityId rootId, final EntitySearchDirection direction, 572 private ListenableFuture<Set<EntityRelation>> findRelationsRecursively(final TenantId tenantId, final EntityId rootId, final EntitySearchDirection direction,
573 - RelationTypeGroup relationTypeGroup, int lvl, 573 + RelationTypeGroup relationTypeGroup, int lvl, boolean fetchLastLevelOnly,
574 final ConcurrentHashMap<EntityId, Boolean> uniqueMap) throws Exception { 574 final ConcurrentHashMap<EntityId, Boolean> uniqueMap) throws Exception {
575 if (lvl == 0) { 575 if (lvl == 0) {
576 return Futures.immediateFuture(Collections.emptySet()); 576 return Futures.immediateFuture(Collections.emptySet());
@@ -596,10 +596,13 @@ public class BaseRelationService implements RelationService { @@ -596,10 +596,13 @@ public class BaseRelationService implements RelationService {
596 } 596 }
597 List<ListenableFuture<Set<EntityRelation>>> futures = new ArrayList<>(); 597 List<ListenableFuture<Set<EntityRelation>>> futures = new ArrayList<>();
598 for (EntityId entityId : childrenIds) { 598 for (EntityId entityId : childrenIds) {
599 - futures.add(findRelationsRecursively(tenantId, entityId, direction, relationTypeGroup, lvl, uniqueMap)); 599 + futures.add(findRelationsRecursively(tenantId, entityId, direction, relationTypeGroup, lvl, fetchLastLevelOnly, uniqueMap));
600 } 600 }
601 //TODO: try to remove this blocking operation 601 //TODO: try to remove this blocking operation
602 List<Set<EntityRelation>> relations = Futures.successfulAsList(futures).get(); 602 List<Set<EntityRelation>> relations = Futures.successfulAsList(futures).get();
  603 + if (fetchLastLevelOnly && lvl > 0){
  604 + children.clear();
  605 + }
603 relations.forEach(r -> r.forEach(children::add)); 606 relations.forEach(r -> r.forEach(children::add));
604 return Futures.immediateFuture(children); 607 return Futures.immediateFuture(children);
605 } 608 }
@@ -220,7 +220,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { @@ -220,7 +220,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
220 saveRelation(relationC); 220 saveRelation(relationC);
221 221
222 EntityRelationsQuery query = new EntityRelationsQuery(); 222 EntityRelationsQuery query = new EntityRelationsQuery();
223 - query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1)); 223 + query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1, false));
224 query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET)))); 224 query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET))));
225 List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get(); 225 List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get();
226 Assert.assertEquals(3, relations.size()); 226 Assert.assertEquals(3, relations.size());
@@ -254,7 +254,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { @@ -254,7 +254,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
254 saveRelation(relationBD); 254 saveRelation(relationBD);
255 255
256 EntityRelationsQuery query = new EntityRelationsQuery(); 256 EntityRelationsQuery query = new EntityRelationsQuery();
257 - query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1)); 257 + query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1, false));
258 query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET)))); 258 query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET))));
259 List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get(); 259 List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get();
260 Assert.assertEquals(2, relations.size()); 260 Assert.assertEquals(2, relations.size());
@@ -26,4 +26,5 @@ public class DeviceRelationsQuery { @@ -26,4 +26,5 @@ public class DeviceRelationsQuery {
26 private int maxLevel = 1; 26 private int maxLevel = 1;
27 private String relationType; 27 private String relationType;
28 private List<String> deviceTypes; 28 private List<String> deviceTypes;
  29 + private boolean fetchLastLevelOnly;
29 } 30 }
@@ -27,5 +27,5 @@ public class RelationsQuery { @@ -27,5 +27,5 @@ public class RelationsQuery {
27 private EntitySearchDirection direction; 27 private EntitySearchDirection direction;
28 private int maxLevel = 1; 28 private int maxLevel = 1;
29 private List<EntityTypeFilter> filters; 29 private List<EntityTypeFilter> filters;
30 - 30 + private boolean fetchLastLevelOnly = false;
31 } 31 }
@@ -46,7 +46,7 @@ public class EntitiesRelatedDeviceIdAsyncLoader { @@ -46,7 +46,7 @@ public class EntitiesRelatedDeviceIdAsyncLoader {
46 private static DeviceSearchQuery buildQuery(EntityId originator, DeviceRelationsQuery deviceRelationsQuery) { 46 private static DeviceSearchQuery buildQuery(EntityId originator, DeviceRelationsQuery deviceRelationsQuery) {
47 DeviceSearchQuery query = new DeviceSearchQuery(); 47 DeviceSearchQuery query = new DeviceSearchQuery();
48 RelationsSearchParameters parameters = new RelationsSearchParameters(originator, 48 RelationsSearchParameters parameters = new RelationsSearchParameters(originator,
49 - deviceRelationsQuery.getDirection(), deviceRelationsQuery.getMaxLevel()); 49 + deviceRelationsQuery.getDirection(), deviceRelationsQuery.getMaxLevel(), deviceRelationsQuery.isFetchLastLevelOnly());
50 query.setParameters(parameters); 50 query.setParameters(parameters);
51 query.setRelationType(deviceRelationsQuery.getRelationType()); 51 query.setRelationType(deviceRelationsQuery.getRelationType());
52 query.setDeviceTypes(deviceRelationsQuery.getDeviceTypes()); 52 query.setDeviceTypes(deviceRelationsQuery.getDeviceTypes());
@@ -50,7 +50,7 @@ public class EntitiesRelatedEntityIdAsyncLoader { @@ -50,7 +50,7 @@ public class EntitiesRelatedEntityIdAsyncLoader {
50 private static EntityRelationsQuery buildQuery(EntityId originator, RelationsQuery relationsQuery) { 50 private static EntityRelationsQuery buildQuery(EntityId originator, RelationsQuery relationsQuery) {
51 EntityRelationsQuery query = new EntityRelationsQuery(); 51 EntityRelationsQuery query = new EntityRelationsQuery();
52 RelationsSearchParameters parameters = new RelationsSearchParameters(originator, 52 RelationsSearchParameters parameters = new RelationsSearchParameters(originator,
53 - relationsQuery.getDirection(), relationsQuery.getMaxLevel()); 53 + relationsQuery.getDirection(), relationsQuery.getMaxLevel(), relationsQuery.isFetchLastLevelOnly());
54 query.setParameters(parameters); 54 query.setParameters(parameters);
55 query.setFilters(relationsQuery.getFilters()); 55 query.setFilters(relationsQuery.getFilters());
56 return query; 56 return query;