From 9175aba24fa2ffded90de35e78939e889a5c1a07 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 17 May 2018 13:45:06 +0300 Subject: [PATCH] Improve Relation Service --- .../dao/relation/BaseRelationService.java | 106 ++++++------------ .../server/dao/relation/RelationService.java | 5 +- .../dao/sql/relation/JpaRelationDao.java | 36 +++--- 3 files changed, 58 insertions(+), 89 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java index 7b2b391b10..ac5bfb29b5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.relation; import com.google.common.base.Function; +import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; @@ -176,97 +177,64 @@ public class BaseRelationService implements RelationService { } @Override - public boolean deleteEntityRelations(EntityId entity) { - Cache cache = cacheManager.getCache(RELATIONS_CACHE); - log.trace("Executing deleteEntityRelations [{}]", entity); - validate(entity); - List>> inboundRelationsList = new ArrayList<>(); - for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) { - inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup)); - } - ListenableFuture>> inboundRelations = Futures.allAsList(inboundRelationsList); - ListenableFuture> inboundDeletions = Futures.transform(inboundRelations, relations -> - getBooleans(relations, cache, true)); - - ListenableFuture inboundFuture = Futures.transform(inboundDeletions, getListToBooleanFunction()); - boolean inboundDeleteResult = false; - try { - inboundDeleteResult = inboundFuture.get(); - } catch (InterruptedException | ExecutionException e) { - log.error("Error deleting entity inbound relations", e); - } - - List>> outboundRelationsList = new ArrayList<>(); - for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) { - outboundRelationsList.add(relationDao.findAllByFrom(entity, typeGroup)); - } - ListenableFuture>> outboundRelations = Futures.allAsList(outboundRelationsList); - Futures.transform(outboundRelations, relations -> getBooleans(relations, cache, false)); - - boolean outboundDeleteResult = relationDao.deleteOutboundRelations(entity); - return inboundDeleteResult && outboundDeleteResult; - } - - private List getBooleans(List> relations, Cache cache, boolean isRemove) { - List results = new ArrayList<>(); - for (List relationList : relations) { - relationList.forEach(relation -> checkFromDeleteSync(cache, results, relation, isRemove)); - } - return results; - } - - private void checkFromDeleteSync(Cache cache, List results, EntityRelation relation, boolean isRemove) { - if (isRemove) { - results.add(relationDao.deleteRelation(relation)); - } - cacheEviction(relation, cache); + public void deleteEntityRelations(EntityId entityId) throws ExecutionException, InterruptedException { + deleteEntityRelationsAsync(entityId).get(); } @Override - public ListenableFuture deleteEntityRelationsAsync(EntityId entity) { + public ListenableFuture deleteEntityRelationsAsync(EntityId entityId) { Cache cache = cacheManager.getCache(RELATIONS_CACHE); - log.trace("Executing deleteEntityRelationsAsync [{}]", entity); - validate(entity); + log.trace("Executing deleteEntityRelationsAsync [{}]", entityId); + validate(entityId); List>> inboundRelationsList = new ArrayList<>(); for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) { - inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup)); + inboundRelationsList.add(relationDao.findAllByTo(entityId, typeGroup)); } - ListenableFuture>> inboundRelations = Futures.allAsList(inboundRelationsList); - ListenableFuture> inboundDeletions = Futures.transformAsync(inboundRelations, - relations -> { - List> results = getListenableFutures(relations, cache, true); - return Futures.allAsList(results); - }); - ListenableFuture inboundFuture = Futures.transform(inboundDeletions, getListToBooleanFunction()); + ListenableFuture>> inboundRelations = Futures.allAsList(inboundRelationsList); List>> outboundRelationsList = new ArrayList<>(); for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) { - outboundRelationsList.add(relationDao.findAllByFrom(entity, typeGroup)); + outboundRelationsList.add(relationDao.findAllByFrom(entityId, typeGroup)); } - ListenableFuture>> outboundRelations = Futures.allAsList(outboundRelationsList); - Futures.transformAsync(outboundRelations, relations -> { - List> results = getListenableFutures(relations, cache, false); - return Futures.allAsList(results); - }); - ListenableFuture outboundFuture = relationDao.deleteOutboundRelationsAsync(entity); - return Futures.transform(Futures.allAsList(Arrays.asList(inboundFuture, outboundFuture)), getListToBooleanFunction()); + ListenableFuture>> outboundRelations = Futures.allAsList(outboundRelationsList); + + ListenableFuture> inboundDeletions = Futures.transformAsync(inboundRelations, + relations -> { + List> results = deleteRelationGroupsAsync(relations, cache, true); + return Futures.allAsList(results); + }); + + ListenableFuture> outboundDeletions = Futures.transformAsync(outboundRelations, + relations -> { + List> results = deleteRelationGroupsAsync(relations, cache, false); + return Futures.allAsList(results); + }); + + ListenableFuture>> deletionsFuture = Futures.allAsList(inboundDeletions, outboundDeletions); + + return Futures.transformAsync(deletionsFuture, (deletions) -> { + relationDao.deleteOutboundRelationsAsync(entityId); + return null; + }); } - private List> getListenableFutures(List> relations, Cache cache, boolean isRemove) { + private List> deleteRelationGroupsAsync(List> relations, Cache cache, boolean deleteFromDb) { List> results = new ArrayList<>(); for (List relationList : relations) { - relationList.forEach(relation -> checkFromDeleteAsync(cache, results, relation, isRemove)); + relationList.forEach(relation -> results.add(deleteAsync(cache, relation, deleteFromDb))); } return results; } - private void checkFromDeleteAsync(Cache cache, List> results, EntityRelation relation, boolean isRemove) { - if (isRemove) { - results.add(relationDao.deleteRelationAsync(relation)); - } + private ListenableFuture deleteAsync(Cache cache, EntityRelation relation, boolean deleteFromDb) { cacheEviction(relation, cache); + if (deleteFromDb) { + return relationDao.deleteRelationAsync(relation); + } else { + return Futures.immediateFuture(false); + } } private void cacheEviction(EntityRelation relation, Cache cache) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java index ca1b959c95..bd945f1586 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import java.util.List; +import java.util.concurrent.ExecutionException; /** * Created by ashvayka on 27.04.17. @@ -47,9 +48,9 @@ public interface RelationService { ListenableFuture deleteRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); - boolean deleteEntityRelations(EntityId entity); + void deleteEntityRelations(EntityId entity) throws ExecutionException, InterruptedException; - ListenableFuture deleteEntityRelationsAsync(EntityId entity); + ListenableFuture deleteEntityRelationsAsync(EntityId entity); List findByFrom(EntityId from, RelationTypeGroup typeGroup); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java index 6776f562bc..2a25bb0eb4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java @@ -132,39 +132,35 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple @Override public boolean deleteRelation(EntityRelation relation) { RelationCompositeKey key = new RelationCompositeKey(relation); - boolean relationExistsBeforeDelete = relationRepository.exists(key); - relationRepository.delete(key); - return relationExistsBeforeDelete; + return deleteRelationIfExists(key); } @Override public ListenableFuture deleteRelationAsync(EntityRelation relation) { RelationCompositeKey key = new RelationCompositeKey(relation); return service.submit( - () -> { - boolean relationExistsBeforeDelete = relationRepository.exists(key); - relationRepository.delete(key); - return relationExistsBeforeDelete; - }); + () -> deleteRelationIfExists(key)); } @Override public boolean deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { RelationCompositeKey key = getRelationCompositeKey(from, to, relationType, typeGroup); - boolean relationExistsBeforeDelete = relationRepository.exists(key); - relationRepository.delete(key); - return relationExistsBeforeDelete; + return deleteRelationIfExists(key); } @Override public ListenableFuture deleteRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { RelationCompositeKey key = getRelationCompositeKey(from, to, relationType, typeGroup); return service.submit( - () -> { - boolean relationExistsBeforeDelete = relationRepository.exists(key); - relationRepository.delete(key); - return relationExistsBeforeDelete; - }); + () -> deleteRelationIfExists(key)); + } + + private boolean deleteRelationIfExists(RelationCompositeKey key) { + boolean relationExistsBeforeDelete = relationRepository.exists(key); + if (relationExistsBeforeDelete) { + relationRepository.delete(key); + } + return relationExistsBeforeDelete; } @Override @@ -172,7 +168,9 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple boolean relationExistsBeforeDelete = relationRepository .findAllByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()) .size() > 0; - relationRepository.deleteByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()); + if (relationExistsBeforeDelete) { + relationRepository.deleteByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()); + } return relationExistsBeforeDelete; } @@ -183,7 +181,9 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple boolean relationExistsBeforeDelete = relationRepository .findAllByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()) .size() > 0; - relationRepository.deleteByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()); + if (relationExistsBeforeDelete) { + relationRepository.deleteByFromIdAndFromType(UUIDConverter.fromTimeUUID(entity.getId()), entity.getEntityType().name()); + } return relationExistsBeforeDelete; }); }