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
This commit is contained in:
yefimov-andrey 2019-08-16 12:29:54 +03:00 committed by Igor Kulikov
parent 2945655d6e
commit d0295ef353
8 changed files with 19 additions and 13 deletions

View File

@ -35,17 +35,19 @@ public class RelationsSearchParameters {
private EntitySearchDirection direction; private EntitySearchDirection direction;
private RelationTypeGroup relationTypeGroup; private RelationTypeGroup relationTypeGroup;
private int maxLevel = 1; private int maxLevel = 1;
private boolean fetchLastLevelOnly;
public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel) { public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, boolean fetchLastLevelOnly) {
this(entityId, direction, maxLevel, RelationTypeGroup.COMMON); this(entityId, direction, maxLevel, RelationTypeGroup.COMMON, fetchLastLevelOnly);
} }
public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, RelationTypeGroup relationTypeGroup) { public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, RelationTypeGroup relationTypeGroup, boolean fetchLastLevelOnly) {
this.rootId = entityId.getId(); this.rootId = entityId.getId();
this.rootType = entityId.getEntityType(); this.rootType = entityId.getEntityType();
this.direction = direction; this.direction = direction;
this.maxLevel = maxLevel; this.maxLevel = maxLevel;
this.relationTypeGroup = relationTypeGroup; this.relationTypeGroup = relationTypeGroup;
this.fetchLastLevelOnly = fetchLastLevelOnly;
} }
public EntityId getEntityId() { public EntityId getEntityId() {

View File

@ -153,7 +153,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
private List<EntityId> getParentEntities(Alarm alarm) throws InterruptedException, ExecutionException { private List<EntityId> getParentEntities(Alarm alarm) throws InterruptedException, ExecutionException {
EntityRelationsQuery query = new EntityRelationsQuery(); EntityRelationsQuery query = new EntityRelationsQuery();
query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE, false));
return relationService.findByQuery(alarm.getTenantId(), query).get().stream().map(EntityRelation::getFrom).collect(Collectors.toList()); return relationService.findByQuery(alarm.getTenantId(), query).get().stream().map(EntityRelation::getFrom).collect(Collectors.toList());
} }

View File

@ -26,7 +26,6 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching; import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
@ -443,6 +442,7 @@ public class BaseRelationService implements RelationService {
@Override @Override
public ListenableFuture<List<EntityRelation>> findByQuery(TenantId tenantId, EntityRelationsQuery query) { public ListenableFuture<List<EntityRelation>> findByQuery(TenantId tenantId, EntityRelationsQuery query) {
//boolean fetchLastLevelOnly = true;
log.trace("Executing findByQuery [{}]", query); log.trace("Executing findByQuery [{}]", query);
RelationsSearchParameters params = query.getParameters(); RelationsSearchParameters params = query.getParameters();
final List<EntityTypeFilter> filters = query.getFilters(); final List<EntityTypeFilter> filters = query.getFilters();
@ -453,7 +453,7 @@ public class BaseRelationService implements RelationService {
int maxLvl = params.getMaxLevel() > 0 ? params.getMaxLevel() : Integer.MAX_VALUE; int maxLvl = params.getMaxLevel() > 0 ? params.getMaxLevel() : Integer.MAX_VALUE;
try { try {
ListenableFuture<Set<EntityRelation>> relationSet = findRelationsRecursively(tenantId, params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, new ConcurrentHashMap<>()); ListenableFuture<Set<EntityRelation>> relationSet = findRelationsRecursively(tenantId, params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, params.isFetchLastLevelOnly(), new ConcurrentHashMap<>());
return Futures.transform(relationSet, input -> { return Futures.transform(relationSet, input -> {
List<EntityRelation> relations = new ArrayList<>(); List<EntityRelation> relations = new ArrayList<>();
if (filters == null || filters.isEmpty()) { if (filters == null || filters.isEmpty()) {
@ -570,7 +570,7 @@ public class BaseRelationService implements RelationService {
} }
private ListenableFuture<Set<EntityRelation>> findRelationsRecursively(final TenantId tenantId, final EntityId rootId, final EntitySearchDirection direction, private ListenableFuture<Set<EntityRelation>> findRelationsRecursively(final TenantId tenantId, final EntityId rootId, final EntitySearchDirection direction,
RelationTypeGroup relationTypeGroup, int lvl, RelationTypeGroup relationTypeGroup, int lvl, boolean fetchLastLevelOnly,
final ConcurrentHashMap<EntityId, Boolean> uniqueMap) throws Exception { final ConcurrentHashMap<EntityId, Boolean> uniqueMap) throws Exception {
if (lvl == 0) { if (lvl == 0) {
return Futures.immediateFuture(Collections.emptySet()); return Futures.immediateFuture(Collections.emptySet());
@ -596,10 +596,13 @@ public class BaseRelationService implements RelationService {
} }
List<ListenableFuture<Set<EntityRelation>>> futures = new ArrayList<>(); List<ListenableFuture<Set<EntityRelation>>> futures = new ArrayList<>();
for (EntityId entityId : childrenIds) { for (EntityId entityId : childrenIds) {
futures.add(findRelationsRecursively(tenantId, entityId, direction, relationTypeGroup, lvl, uniqueMap)); futures.add(findRelationsRecursively(tenantId, entityId, direction, relationTypeGroup, lvl, fetchLastLevelOnly, uniqueMap));
} }
//TODO: try to remove this blocking operation //TODO: try to remove this blocking operation
List<Set<EntityRelation>> relations = Futures.successfulAsList(futures).get(); List<Set<EntityRelation>> relations = Futures.successfulAsList(futures).get();
if (fetchLastLevelOnly && lvl > 0){
children.clear();
}
relations.forEach(r -> r.forEach(children::add)); relations.forEach(r -> r.forEach(children::add));
return Futures.immediateFuture(children); return Futures.immediateFuture(children);
} }

View File

@ -220,7 +220,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
saveRelation(relationC); saveRelation(relationC);
EntityRelationsQuery query = new EntityRelationsQuery(); EntityRelationsQuery query = new EntityRelationsQuery();
query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1)); query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1, false));
query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET)))); query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET))));
List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get(); List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get();
Assert.assertEquals(3, relations.size()); Assert.assertEquals(3, relations.size());
@ -254,7 +254,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
saveRelation(relationBD); saveRelation(relationBD);
EntityRelationsQuery query = new EntityRelationsQuery(); EntityRelationsQuery query = new EntityRelationsQuery();
query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1)); query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1, false));
query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET)))); query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET))));
List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get(); List<EntityRelation> relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get();
Assert.assertEquals(2, relations.size()); Assert.assertEquals(2, relations.size());

View File

@ -26,4 +26,5 @@ public class DeviceRelationsQuery {
private int maxLevel = 1; private int maxLevel = 1;
private String relationType; private String relationType;
private List<String> deviceTypes; private List<String> deviceTypes;
private boolean fetchLastLevelOnly;
} }

View File

@ -27,5 +27,5 @@ public class RelationsQuery {
private EntitySearchDirection direction; private EntitySearchDirection direction;
private int maxLevel = 1; private int maxLevel = 1;
private List<EntityTypeFilter> filters; private List<EntityTypeFilter> filters;
private boolean fetchLastLevelOnly = false;
} }

View File

@ -46,7 +46,7 @@ public class EntitiesRelatedDeviceIdAsyncLoader {
private static DeviceSearchQuery buildQuery(EntityId originator, DeviceRelationsQuery deviceRelationsQuery) { private static DeviceSearchQuery buildQuery(EntityId originator, DeviceRelationsQuery deviceRelationsQuery) {
DeviceSearchQuery query = new DeviceSearchQuery(); DeviceSearchQuery query = new DeviceSearchQuery();
RelationsSearchParameters parameters = new RelationsSearchParameters(originator, RelationsSearchParameters parameters = new RelationsSearchParameters(originator,
deviceRelationsQuery.getDirection(), deviceRelationsQuery.getMaxLevel()); deviceRelationsQuery.getDirection(), deviceRelationsQuery.getMaxLevel(), deviceRelationsQuery.isFetchLastLevelOnly());
query.setParameters(parameters); query.setParameters(parameters);
query.setRelationType(deviceRelationsQuery.getRelationType()); query.setRelationType(deviceRelationsQuery.getRelationType());
query.setDeviceTypes(deviceRelationsQuery.getDeviceTypes()); query.setDeviceTypes(deviceRelationsQuery.getDeviceTypes());

View File

@ -50,7 +50,7 @@ public class EntitiesRelatedEntityIdAsyncLoader {
private static EntityRelationsQuery buildQuery(EntityId originator, RelationsQuery relationsQuery) { private static EntityRelationsQuery buildQuery(EntityId originator, RelationsQuery relationsQuery) {
EntityRelationsQuery query = new EntityRelationsQuery(); EntityRelationsQuery query = new EntityRelationsQuery();
RelationsSearchParameters parameters = new RelationsSearchParameters(originator, RelationsSearchParameters parameters = new RelationsSearchParameters(originator,
relationsQuery.getDirection(), relationsQuery.getMaxLevel()); relationsQuery.getDirection(), relationsQuery.getMaxLevel(), relationsQuery.isFetchLastLevelOnly());
query.setParameters(parameters); query.setParameters(parameters);
query.setFilters(relationsQuery.getFilters()); query.setFilters(relationsQuery.getFilters());
return query; return query;