From 279389bbdfff2180a2b5be8b20fda8b663b33b1f Mon Sep 17 00:00:00 2001 From: desoliture Date: Fri, 14 Jan 2022 16:09:02 +0200 Subject: [PATCH] refactor async methods used in tenant deletion transaction tenant deleting should be transactional, but some services use async methods, what corrupting transaction execution. Withal most of the refactored methods are using instant .get() after getting future, and it is the same if we use non-async methods. Add non-async methods in interfaces of services and dao and use it for tenant deletion process --- .../dao/entityview/EntityViewService.java | 2 ++ .../server/dao/asset/BaseAssetService.java | 11 +++------- .../server/dao/device/DeviceServiceImpl.java | 22 +++++-------------- .../dao/entity/AbstractEntityService.java | 2 +- .../server/dao/entityview/EntityViewDao.java | 1 + .../dao/entityview/EntityViewServiceImpl.java | 21 ++++++++++++++++++ .../dao/sql/entityview/JpaEntityViewDao.java | 8 +++++++ 7 files changed, 42 insertions(+), 25 deletions(-) diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java index 832a7822ee..abb79e48fa 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java @@ -72,6 +72,8 @@ public interface EntityViewService { ListenableFuture> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId); + List findEntityViewsByTenantIdAndEntityId(TenantId tenantId, EntityId entityId); + void deleteEntityView(TenantId tenantId, EntityViewId entityViewId); void deleteEntityViewsByTenantId(TenantId tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java index 94477635af..3e178919f6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java @@ -168,14 +168,9 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ deleteEntityRelations(tenantId, assetId); Asset asset = assetDao.findById(tenantId, assetId.getId()); - try { - List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(asset.getTenantId(), assetId).get(); - if (entityViews != null && !entityViews.isEmpty()) { - throw new DataValidationException("Can't delete asset that has entity views!"); - } - } catch (ExecutionException | InterruptedException e) { - log.error("Exception while finding entity views for assetId [{}]", assetId, e); - throw new RuntimeException("Exception while finding entity views for assetId [" + assetId + "]", e); + List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityId(asset.getTenantId(), assetId); + if (entityViews != null && !entityViews.isEmpty()) { + throw new DataValidationException("Can't delete asset that has entity views!"); } removeAssetFromCacheByName(asset.getTenantId(), asset.getName()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index 0f1f830a4d..778ee3e789 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -344,14 +344,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe Device device = deviceDao.findById(tenantId, deviceId.getId()); final String deviceName = device.getName(); - try { - List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(device.getTenantId(), deviceId).get(); - if (entityViews != null && !entityViews.isEmpty()) { - throw new DataValidationException("Can't delete device that has entity views!"); - } - } catch (ExecutionException | InterruptedException e) { - log.error("Exception while finding entity views for deviceId [{}]", deviceId, e); - throw new RuntimeException("Exception while finding entity views for deviceId [" + deviceId + "]", e); + List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityId(device.getTenantId(), deviceId); + if (entityViews != null && !entityViews.isEmpty()) { + throw new DataValidationException("Can't delete device that has entity views!"); } DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, deviceId); @@ -568,14 +563,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe public Device assignDeviceToTenant(TenantId tenantId, Device device) { log.trace("Executing assignDeviceToTenant [{}][{}]", tenantId, device); - try { - List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(device.getTenantId(), device.getId()).get(); - if (!CollectionUtils.isEmpty(entityViews)) { - throw new DataValidationException("Can't assign device that has entity views to another tenant!"); - } - } catch (ExecutionException | InterruptedException e) { - log.error("Exception while finding entity views for deviceId [{}]", device.getId(), e); - throw new RuntimeException("Exception while finding entity views for deviceId [" + device.getId() + "]", e); + List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityId(device.getTenantId(), device.getId()); + if (!CollectionUtils.isEmpty(entityViews)) { + throw new DataValidationException("Can't assign device that has entity views to another tenant!"); } eventService.removeEvents(device.getTenantId(), device.getId()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java index a71c1e8ec6..acb49bb730 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/AbstractEntityService.java @@ -83,7 +83,7 @@ public abstract class AbstractEntityService { protected void checkAssignedEntityViewsToEdge(TenantId tenantId, EntityId entityId, EdgeId edgeId) { try { - List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(tenantId, entityId).get(); + List entityViews = entityViewService.findEntityViewsByTenantIdAndEntityId(tenantId, entityId); if (entityViews != null && !entityViews.isEmpty()) { EntityView entityView = entityViews.get(0); // TODO: @voba - refactor this blocking operation diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java index c4a9e0d871..b7c65e7c8b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java @@ -179,4 +179,5 @@ public interface EntityViewDao extends Dao { String type, PageLink pageLink); + List findEntityViewsByTenantIdAndEntityId(UUID tenantId, UUID entityId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index 7c3d16dd1a..30b32e4caf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -302,6 +302,27 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti } } + @Override + public List findEntityViewsByTenantIdAndEntityId(TenantId tenantId, EntityId entityId) { + log.trace("Executing findEntityViewsByTenantIdAndEntityId, tenantId [{}], entityId [{}]", tenantId, entityId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + validateId(entityId.getId(), "Incorrect entityId" + entityId); + + List tenantIdAndEntityId = new ArrayList<>(); + tenantIdAndEntityId.add(tenantId); + tenantIdAndEntityId.add(entityId); + + Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE); + List fromCache = cache.get(tenantIdAndEntityId, List.class); + if (fromCache != null) { + return fromCache; + } else { + List result = entityViewDao.findEntityViewsByTenantIdAndEntityId(tenantId.getId(), entityId.getId()); + cache.putIfAbsent(tenantIdAndEntityId, result); + return result; + } + } + @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}") @Override public void deleteEntityView(TenantId tenantId, EntityViewId entityViewId) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java index 35f81a860c..676caed2ed 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java @@ -200,4 +200,12 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewsByTenantIdAndEntityId(UUID tenantId, UUID entityId) { + return DaoUtil.convertDataList( + entityViewRepository.findAllByTenantIdAndEntityId( + tenantId, entityId) + ); + } }