Browse Source

Tenant/Device profiles cache support.

pull/3477/head
Igor Kulikov 6 years ago
parent
commit
7841d11724
  1. 8
      application/src/main/resources/thingsboard.yml
  2. 2
      common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java
  3. 51
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
  4. 49
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java
  5. 10
      dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceProfileServiceTest.java
  6. 13
      dao/src/test/java/org/thingsboard/server/dao/service/BaseTenantProfileServiceTest.java
  7. 6
      dao/src/test/resources/application-test.properties

8
application/src/main/resources/thingsboard.yml

@ -372,6 +372,12 @@ caffeine:
securitySettings:
timeToLiveInMinutes: 1440
maxSize: 0
tenantProfiles:
timeToLiveInMinutes: 1440
maxSize: 0
deviceProfiles:
timeToLiveInMinutes: 1440
maxSize: 0
redis:
# standalone or cluster
@ -793,4 +799,4 @@ management:
web:
exposure:
# Expose metrics endpoint (use value 'prometheus' to enable prometheus metrics).
include: '${METRICS_ENDPOINTS_EXPOSE:info}'
include: '${METRICS_ENDPOINTS_EXPOSE:info}'

2
common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java

@ -24,4 +24,6 @@ public class CacheConstants {
public static final String ENTITY_VIEW_CACHE = "entityViews";
public static final String CLAIM_DEVICES_CACHE = "claimDevices";
public static final String SECURITY_SETTINGS_CACHE = "securitySettings";
public static final String TENANT_PROFILE_CACHE = "tenantProfiles";
public static final String DEVICE_PROFILE_CACHE = "deviceProfiles";
}

51
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -19,6 +19,9 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityInfo;
@ -35,6 +38,10 @@ import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.tenant.TenantDao;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import java.util.Arrays;
import java.util.Collections;
import static org.thingsboard.server.common.data.CacheConstants.DEVICE_PROFILE_CACHE;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Service
@ -50,6 +57,10 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
@Autowired
private TenantDao tenantDao;
@Autowired
private CacheManager cacheManager;
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#deviceProfileId}")
@Override
public DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
@ -57,6 +68,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
return deviceProfileDao.findById(tenantId, deviceProfileId.getId());
}
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'info', #deviceProfileId}")
@Override
public EntityInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
@ -79,6 +91,13 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
throw t;
}
}
Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
cache.evict(Collections.singletonList(savedDeviceProfile.getId()));
cache.evict(Arrays.asList("info", savedDeviceProfile.getId()));
if (savedDeviceProfile.isDefault()) {
cache.evict(Arrays.asList("default", savedDeviceProfile.getTenantId()));
cache.evict(Arrays.asList("default", "info", savedDeviceProfile.getTenantId()));
}
return savedDeviceProfile;
}
@ -86,8 +105,19 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
public void deleteDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing deleteDeviceProfile [{}]", deviceProfileId);
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
DeviceProfile deviceProfile = deviceProfileDao.findById(tenantId, deviceProfileId.getId());
if (deviceProfile != null && deviceProfile.isDefault()) {
throw new DataValidationException("Deletion of Default Device Profile is prohibited!");
}
this.removeDeviceProfile(tenantId, deviceProfileId);
}
private void removeDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
deleteEntityRelations(tenantId, deviceProfileId);
deviceProfileDao.removeById(tenantId, deviceProfileId.getId());
Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
cache.evict(Collections.singletonList(deviceProfileId.getId()));
cache.evict(Arrays.asList("info", deviceProfileId.getId()));
}
@Override
@ -116,9 +146,10 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
deviceProfile.setName("Default");
deviceProfile.setDescription("Default device profile");
deviceProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
return deviceProfileDao.save(tenantId, deviceProfile);
return saveDeviceProfile(deviceProfile);
}
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'default', #tenantId}")
@Override
public DeviceProfile findDefaultDeviceProfile(TenantId tenantId) {
log.trace("Executing findDefaultDeviceProfile tenantId [{}]", tenantId);
@ -126,6 +157,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
return deviceProfileDao.findDefaultDeviceProfile(tenantId);
}
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'default', 'info', #tenantId}")
@Override
public EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId) {
log.trace("Executing findDefaultDeviceProfileInfo tenantId [{}]", tenantId);
@ -139,17 +171,28 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
DeviceProfile deviceProfile = deviceProfileDao.findById(tenantId, deviceProfileId.getId());
if (!deviceProfile.isDefault()) {
Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
deviceProfile.setDefault(true);
DeviceProfile previousDefaultDeviceProfile = findDefaultDeviceProfile(tenantId);
boolean changed = false;
if (previousDefaultDeviceProfile == null) {
deviceProfileDao.save(tenantId, deviceProfile);
return true;
changed = true;
} else if (!previousDefaultDeviceProfile.getId().equals(deviceProfile.getId())) {
previousDefaultDeviceProfile.setDefault(false);
deviceProfileDao.save(tenantId, previousDefaultDeviceProfile);
deviceProfileDao.save(tenantId, deviceProfile);
return true;
cache.evict(Collections.singletonList(previousDefaultDeviceProfile.getId()));
cache.evict(Arrays.asList("info", previousDefaultDeviceProfile.getId()));
changed = true;
}
if (changed) {
cache.evict(Collections.singletonList(deviceProfile.getId()));
cache.evict(Arrays.asList("info", deviceProfile.getId()));
cache.evict(Arrays.asList("default", tenantId));
cache.evict(Arrays.asList("default", "info", tenantId));
}
return changed;
}
return false;
}
@ -195,7 +238,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
@Override
protected void removeEntity(TenantId tenantId, DeviceProfile entity) {
deleteDeviceProfile(tenantId, new DeviceProfileId(entity.getUuidId()));
removeDeviceProfile(tenantId, entity.getId());
}
};

49
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java

@ -19,6 +19,9 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.TenantProfile;
@ -33,6 +36,10 @@ import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import java.util.Arrays;
import java.util.Collections;
import static org.thingsboard.server.common.data.CacheConstants.TENANT_PROFILE_CACHE;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Service
@ -44,6 +51,10 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
@Autowired
private TenantProfileDao tenantProfileDao;
@Autowired
private CacheManager cacheManager;
@Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{#tenantProfileId}")
@Override
public TenantProfile findTenantProfileById(TenantId tenantId, TenantProfileId tenantProfileId) {
log.trace("Executing findTenantProfileById [{}]", tenantProfileId);
@ -51,6 +62,7 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
return tenantProfileDao.findById(tenantId, tenantProfileId.getId());
}
@Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{'info', #tenantProfileId}")
@Override
public EntityInfo findTenantProfileInfoById(TenantId tenantId, TenantProfileId tenantProfileId) {
log.trace("Executing findTenantProfileInfoById [{}]", tenantProfileId);
@ -73,6 +85,13 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
throw t;
}
}
Cache cache = cacheManager.getCache(TENANT_PROFILE_CACHE);
cache.evict(Collections.singletonList(savedTenantProfile.getId()));
cache.evict(Arrays.asList("info", savedTenantProfile.getId()));
if (savedTenantProfile.isDefault()) {
cache.evict(Collections.singletonList("default"));
cache.evict(Arrays.asList("default", "info"));
}
return savedTenantProfile;
}
@ -80,8 +99,19 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
public void deleteTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
log.trace("Executing deleteTenantProfile [{}]", tenantProfileId);
validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenantProfileId.getId());
if (tenantProfile != null && tenantProfile.isDefault()) {
throw new DataValidationException("Deletion of Default Tenant Profile is prohibited!");
}
this.removeTenantProfile(tenantId, tenantProfileId);
}
private void removeTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
deleteEntityRelations(tenantId, tenantProfileId);
tenantProfileDao.removeById(tenantId, tenantProfileId.getId());
Cache cache = cacheManager.getCache(TENANT_PROFILE_CACHE);
cache.evict(Collections.singletonList(tenantProfileId.getId()));
cache.evict(Arrays.asList("info", tenantProfileId.getId()));
}
@Override
@ -115,12 +145,14 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
return defaultTenantProfile;
}
@Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{'default'}")
@Override
public TenantProfile findDefaultTenantProfile(TenantId tenantId) {
log.trace("Executing findDefaultTenantProfile");
return tenantProfileDao.findDefaultTenantProfile(tenantId);
}
@Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{'default', 'info'}")
@Override
public EntityInfo findDefaultTenantProfileInfo(TenantId tenantId) {
log.trace("Executing findDefaultTenantProfileInfo");
@ -133,17 +165,28 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenantProfileId.getId());
if (!tenantProfile.isDefault()) {
Cache cache = cacheManager.getCache(TENANT_PROFILE_CACHE);
tenantProfile.setDefault(true);
TenantProfile previousDefaultTenantProfile = findDefaultTenantProfile(tenantId);
boolean changed = false;
if (previousDefaultTenantProfile == null) {
tenantProfileDao.save(tenantId, tenantProfile);
return true;
changed = true;
} else if (!previousDefaultTenantProfile.getId().equals(tenantProfile.getId())) {
previousDefaultTenantProfile.setDefault(false);
tenantProfileDao.save(tenantId, previousDefaultTenantProfile);
tenantProfileDao.save(tenantId, tenantProfile);
return true;
cache.evict(Collections.singletonList(previousDefaultTenantProfile.getId()));
cache.evict(Arrays.asList("info", previousDefaultTenantProfile.getId()));
changed = true;
}
if (changed) {
cache.evict(Collections.singletonList(tenantProfile.getId()));
cache.evict(Arrays.asList("info", tenantProfile.getId()));
cache.evict(Collections.singletonList("default"));
cache.evict(Arrays.asList("default", "info"));
}
return changed;
}
return false;
}
@ -180,7 +223,7 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
@Override
protected void removeEntity(TenantId tenantId, TenantProfile entity) {
deleteTenantProfile(tenantId, new TenantProfileId(entity.getUuidId()));
removeTenantProfile(tenantId, entity.getId());
}
};

10
dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceProfileServiceTest.java

@ -71,9 +71,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
savedDeviceProfile.setName("New device profile");
deviceProfileService.saveDeviceProfile(savedDeviceProfile);
DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
Assert.assertEquals(foundDeviceProfile.getName(), savedDeviceProfile.getName());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfile.getName());
}
@Test
@ -83,8 +81,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
Assert.assertNotNull(foundDeviceProfile);
Assert.assertEquals(savedDeviceProfile, foundDeviceProfile);
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
}
}
@Test
public void testFindDeviceProfileInfoById() {
@ -94,7 +91,6 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
Assert.assertNotNull(foundDeviceProfileInfo);
Assert.assertEquals(savedDeviceProfile.getId(), foundDeviceProfileInfo.getId());
Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfileInfo.getName());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
}
@Test
@ -131,8 +127,6 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
Assert.assertNotNull(defaultDeviceProfile);
Assert.assertEquals(savedDeviceProfile2.getId(), defaultDeviceProfile.getId());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile1.getId());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile2.getId());
}
@Test(expected = DataValidationException.class)

13
dao/src/test/java/org/thingsboard/server/dao/service/BaseTenantProfileServiceTest.java

@ -61,7 +61,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
Assert.assertEquals(foundTenantProfile.getName(), savedTenantProfile.getName());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
}
@Test
@ -71,7 +71,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
Assert.assertNotNull(foundTenantProfile);
Assert.assertEquals(savedTenantProfile, foundTenantProfile);
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
}
@Test
@ -82,7 +82,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
Assert.assertNotNull(foundTenantProfileInfo);
Assert.assertEquals(savedTenantProfile.getId(), foundTenantProfileInfo.getId());
Assert.assertEquals(savedTenantProfile.getName(), foundTenantProfileInfo.getName());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
}
@Test
@ -93,7 +93,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
TenantProfile foundDefaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
Assert.assertNotNull(foundDefaultTenantProfile);
Assert.assertEquals(savedTenantProfile, foundDefaultTenantProfile);
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
}
@Test
@ -105,7 +105,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
Assert.assertNotNull(foundDefaultTenantProfileInfo);
Assert.assertEquals(savedTenantProfile.getId(), foundDefaultTenantProfileInfo.getId());
Assert.assertEquals(savedTenantProfile.getName(), foundDefaultTenantProfileInfo.getName());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
}
@Test
@ -126,8 +126,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
defaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
Assert.assertNotNull(defaultTenantProfile);
Assert.assertEquals(savedTenantProfile2.getId(), defaultTenantProfile.getId());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile1.getId());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile2.getId());
tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
}
@Test(expected = DataValidationException.class)

6
dao/src/test/resources/application-test.properties

@ -30,6 +30,12 @@ caffeine.specs.entityViews.maxSize=100000
caffeine.specs.claimDevices.timeToLiveInMinutes=1440
caffeine.specs.claimDevices.maxSize=100000
caffeine.specs.tenantProfiles.timeToLiveInMinutes=1440
caffeine.specs.tenantProfiles.maxSize=100000
caffeine.specs.deviceProfiles.timeToLiveInMinutes=1440
caffeine.specs.deviceProfiles.maxSize=100000
redis.connection.host=localhost
redis.connection.port=6379
redis.connection.db=0

Loading…
Cancel
Save