thingsboard-aplcache

Improve Relation Service

5/17/2018 7:45:06 AM

Details

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 7b2b391..ac5bfb2 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) {
+    public void deleteEntityRelations(EntityId entityId) throws ExecutionException, InterruptedException {
+        deleteEntityRelationsAsync(entityId).get();
+    }
+
+    @Override
+    public ListenableFuture<Void> deleteEntityRelationsAsync(EntityId entityId) {
         Cache cache = cacheManager.getCache(RELATIONS_CACHE);
-        log.trace("Executing deleteEntityRelations [{}]", entity);
-        validate(entity);
+        log.trace("Executing deleteEntityRelationsAsync [{}]", entityId);
+        validate(entityId);
         List<ListenableFuture<List<EntityRelation>>> inboundRelationsList = new ArrayList<>();
         for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
-            inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup));
+            inboundRelationsList.add(relationDao.findAllByTo(entityId, typeGroup));
         }
-        ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
-        ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelations, relations ->
-                getBooleans(relations, cache, true));
 
-        ListenableFuture<Boolean> inboundFuture = Futures.transform(inboundDeletions, getListToBooleanFunction());
-        boolean inboundDeleteResult = false;
-        try {
-            inboundDeleteResult = inboundFuture.get();
-        } catch (InterruptedException | ExecutionException e) {
-            log.error("Error deleting entity inbound relations", e);
-        }
+        ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
 
         List<ListenableFuture<List<EntityRelation>>> outboundRelationsList = new ArrayList<>();
         for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
-            outboundRelationsList.add(relationDao.findAllByFrom(entity, typeGroup));
+            outboundRelationsList.add(relationDao.findAllByFrom(entityId, typeGroup));
         }
-        ListenableFuture<List<List<EntityRelation>>> outboundRelations = Futures.allAsList(outboundRelationsList);
-        Futures.transform(outboundRelations, relations -> getBooleans(relations, cache, false));
 
-        boolean outboundDeleteResult = relationDao.deleteOutboundRelations(entity);
-        return inboundDeleteResult && outboundDeleteResult;
-    }
-
-    private List<Boolean> getBooleans(List<List<EntityRelation>> relations, Cache cache, boolean isRemove) {
-        List<Boolean> results = new ArrayList<>();
-        for (List<EntityRelation> relationList : relations) {
-            relationList.forEach(relation -> checkFromDeleteSync(cache, results, relation, isRemove));
-        }
-        return results;
-    }
-
-    private void checkFromDeleteSync(Cache cache, List<Boolean> results, EntityRelation relation, boolean isRemove) {
-        if (isRemove) {
-            results.add(relationDao.deleteRelation(relation));
-        }
-        cacheEviction(relation, cache);
-    }
+        ListenableFuture<List<List<EntityRelation>>> outboundRelations = Futures.allAsList(outboundRelationsList);
 
-    @Override
-    public ListenableFuture<Boolean> deleteEntityRelationsAsync(EntityId entity) {
-        Cache cache = cacheManager.getCache(RELATIONS_CACHE);
-        log.trace("Executing deleteEntityRelationsAsync [{}]", entity);
-        validate(entity);
-        List<ListenableFuture<List<EntityRelation>>> inboundRelationsList = new ArrayList<>();
-        for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
-            inboundRelationsList.add(relationDao.findAllByTo(entity, typeGroup));
-        }
-        ListenableFuture<List<List<EntityRelation>>> inboundRelations = Futures.allAsList(inboundRelationsList);
         ListenableFuture<List<Boolean>> inboundDeletions = Futures.transformAsync(inboundRelations,
                 relations -> {
-                    List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, true);
+                    List<ListenableFuture<Boolean>> results = deleteRelationGroupsAsync(relations, cache, true);
                     return Futures.allAsList(results);
                 });
 
-        ListenableFuture<Boolean> inboundFuture = Futures.transform(inboundDeletions, getListToBooleanFunction());
+        ListenableFuture<List<Boolean>> outboundDeletions = Futures.transformAsync(outboundRelations,
+                relations -> {
+                    List<ListenableFuture<Boolean>> results = deleteRelationGroupsAsync(relations, cache, false);
+                    return Futures.allAsList(results);
+                });
 
-        List<ListenableFuture<List<EntityRelation>>> outboundRelationsList = new ArrayList<>();
-        for (RelationTypeGroup typeGroup : RelationTypeGroup.values()) {
-            outboundRelationsList.add(relationDao.findAllByFrom(entity, typeGroup));
-        }
-        ListenableFuture<List<List<EntityRelation>>> outboundRelations = Futures.allAsList(outboundRelationsList);
-        Futures.transformAsync(outboundRelations, relations -> {
-            List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, false);
-            return Futures.allAsList(results);
-        });
+        ListenableFuture<List<List<Boolean>>> deletionsFuture = Futures.allAsList(inboundDeletions, outboundDeletions);
 
-        ListenableFuture<Boolean> outboundFuture = relationDao.deleteOutboundRelationsAsync(entity);
-        return Futures.transform(Futures.allAsList(Arrays.asList(inboundFuture, outboundFuture)), getListToBooleanFunction());
+        return Futures.transformAsync(deletionsFuture, (deletions) -> {
+            relationDao.deleteOutboundRelationsAsync(entityId);
+            return null;
+        });
     }
 
-    private List<ListenableFuture<Boolean>> getListenableFutures(List<List<EntityRelation>> relations, Cache cache, boolean isRemove) {
+    private List<ListenableFuture<Boolean>> deleteRelationGroupsAsync(List<List<EntityRelation>> relations, Cache cache, boolean deleteFromDb) {
         List<ListenableFuture<Boolean>> results = new ArrayList<>();
         for (List<EntityRelation> 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<ListenableFuture<Boolean>> results, EntityRelation relation, boolean isRemove) {
-        if (isRemove) {
-            results.add(relationDao.deleteRelationAsync(relation));
-        }
+    private ListenableFuture<Boolean> 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 ca1b959..bd945f1 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<Boolean> deleteRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
 
-    boolean deleteEntityRelations(EntityId entity);
+    void deleteEntityRelations(EntityId entity) throws ExecutionException, InterruptedException;
 
-    ListenableFuture<Boolean> deleteEntityRelationsAsync(EntityId entity);
+    ListenableFuture<Void> deleteEntityRelationsAsync(EntityId entity);
 
     List<EntityRelation> 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 6776f56..2a25bb0 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<Boolean> 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<Boolean> 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;
                 });
     }