Commit 7841d1172470e83bc80d5406be7b576e5d7e43f4

Authored by Igor Kulikov
1 parent 3ddf1466

Tenant/Device profiles cache support.

... ... @@ -372,6 +372,12 @@ caffeine:
372 372 securitySettings:
373 373 timeToLiveInMinutes: 1440
374 374 maxSize: 0
  375 + tenantProfiles:
  376 + timeToLiveInMinutes: 1440
  377 + maxSize: 0
  378 + deviceProfiles:
  379 + timeToLiveInMinutes: 1440
  380 + maxSize: 0
375 381
376 382 redis:
377 383 # standalone or cluster
... ... @@ -793,4 +799,4 @@ management:
793 799 web:
794 800 exposure:
795 801 # Expose metrics endpoint (use value 'prometheus' to enable prometheus metrics).
796   - include: '${METRICS_ENDPOINTS_EXPOSE:info}'
\ No newline at end of file
  802 + include: '${METRICS_ENDPOINTS_EXPOSE:info}'
... ...
... ... @@ -24,4 +24,6 @@ public class CacheConstants {
24 24 public static final String ENTITY_VIEW_CACHE = "entityViews";
25 25 public static final String CLAIM_DEVICES_CACHE = "claimDevices";
26 26 public static final String SECURITY_SETTINGS_CACHE = "securitySettings";
  27 + public static final String TENANT_PROFILE_CACHE = "tenantProfiles";
  28 + public static final String DEVICE_PROFILE_CACHE = "deviceProfiles";
27 29 }
... ...
... ... @@ -19,6 +19,9 @@ import lombok.extern.slf4j.Slf4j;
19 19 import org.apache.commons.lang3.StringUtils;
20 20 import org.hibernate.exception.ConstraintViolationException;
21 21 import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.cache.Cache;
  23 +import org.springframework.cache.CacheManager;
  24 +import org.springframework.cache.annotation.Cacheable;
22 25 import org.springframework.stereotype.Service;
23 26 import org.thingsboard.server.common.data.DeviceProfile;
24 27 import org.thingsboard.server.common.data.EntityInfo;
... ... @@ -35,6 +38,10 @@ import org.thingsboard.server.dao.service.Validator;
35 38 import org.thingsboard.server.dao.tenant.TenantDao;
36 39 import org.thingsboard.server.dao.util.mapping.JacksonUtil;
37 40
  41 +import java.util.Arrays;
  42 +import java.util.Collections;
  43 +
  44 +import static org.thingsboard.server.common.data.CacheConstants.DEVICE_PROFILE_CACHE;
38 45 import static org.thingsboard.server.dao.service.Validator.validateId;
39 46
40 47 @Service
... ... @@ -50,6 +57,10 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
50 57 @Autowired
51 58 private TenantDao tenantDao;
52 59
  60 + @Autowired
  61 + private CacheManager cacheManager;
  62 +
  63 + @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#deviceProfileId}")
53 64 @Override
54 65 public DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId) {
55 66 log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
... ... @@ -57,6 +68,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
57 68 return deviceProfileDao.findById(tenantId, deviceProfileId.getId());
58 69 }
59 70
  71 + @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'info', #deviceProfileId}")
60 72 @Override
61 73 public EntityInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId) {
62 74 log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
... ... @@ -79,6 +91,13 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
79 91 throw t;
80 92 }
81 93 }
  94 + Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
  95 + cache.evict(Collections.singletonList(savedDeviceProfile.getId()));
  96 + cache.evict(Arrays.asList("info", savedDeviceProfile.getId()));
  97 + if (savedDeviceProfile.isDefault()) {
  98 + cache.evict(Arrays.asList("default", savedDeviceProfile.getTenantId()));
  99 + cache.evict(Arrays.asList("default", "info", savedDeviceProfile.getTenantId()));
  100 + }
82 101 return savedDeviceProfile;
83 102 }
84 103
... ... @@ -86,8 +105,19 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
86 105 public void deleteDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
87 106 log.trace("Executing deleteDeviceProfile [{}]", deviceProfileId);
88 107 Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
  108 + DeviceProfile deviceProfile = deviceProfileDao.findById(tenantId, deviceProfileId.getId());
  109 + if (deviceProfile != null && deviceProfile.isDefault()) {
  110 + throw new DataValidationException("Deletion of Default Device Profile is prohibited!");
  111 + }
  112 + this.removeDeviceProfile(tenantId, deviceProfileId);
  113 + }
  114 +
  115 + private void removeDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
89 116 deleteEntityRelations(tenantId, deviceProfileId);
90 117 deviceProfileDao.removeById(tenantId, deviceProfileId.getId());
  118 + Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
  119 + cache.evict(Collections.singletonList(deviceProfileId.getId()));
  120 + cache.evict(Arrays.asList("info", deviceProfileId.getId()));
91 121 }
92 122
93 123 @Override
... ... @@ -116,9 +146,10 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
116 146 deviceProfile.setName("Default");
117 147 deviceProfile.setDescription("Default device profile");
118 148 deviceProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
119   - return deviceProfileDao.save(tenantId, deviceProfile);
  149 + return saveDeviceProfile(deviceProfile);
120 150 }
121 151
  152 + @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'default', #tenantId}")
122 153 @Override
123 154 public DeviceProfile findDefaultDeviceProfile(TenantId tenantId) {
124 155 log.trace("Executing findDefaultDeviceProfile tenantId [{}]", tenantId);
... ... @@ -126,6 +157,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
126 157 return deviceProfileDao.findDefaultDeviceProfile(tenantId);
127 158 }
128 159
  160 + @Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'default', 'info', #tenantId}")
129 161 @Override
130 162 public EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId) {
131 163 log.trace("Executing findDefaultDeviceProfileInfo tenantId [{}]", tenantId);
... ... @@ -139,17 +171,28 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
139 171 Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
140 172 DeviceProfile deviceProfile = deviceProfileDao.findById(tenantId, deviceProfileId.getId());
141 173 if (!deviceProfile.isDefault()) {
  174 + Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
142 175 deviceProfile.setDefault(true);
143 176 DeviceProfile previousDefaultDeviceProfile = findDefaultDeviceProfile(tenantId);
  177 + boolean changed = false;
144 178 if (previousDefaultDeviceProfile == null) {
145 179 deviceProfileDao.save(tenantId, deviceProfile);
146   - return true;
  180 + changed = true;
147 181 } else if (!previousDefaultDeviceProfile.getId().equals(deviceProfile.getId())) {
148 182 previousDefaultDeviceProfile.setDefault(false);
149 183 deviceProfileDao.save(tenantId, previousDefaultDeviceProfile);
150 184 deviceProfileDao.save(tenantId, deviceProfile);
151   - return true;
  185 + cache.evict(Collections.singletonList(previousDefaultDeviceProfile.getId()));
  186 + cache.evict(Arrays.asList("info", previousDefaultDeviceProfile.getId()));
  187 + changed = true;
  188 + }
  189 + if (changed) {
  190 + cache.evict(Collections.singletonList(deviceProfile.getId()));
  191 + cache.evict(Arrays.asList("info", deviceProfile.getId()));
  192 + cache.evict(Arrays.asList("default", tenantId));
  193 + cache.evict(Arrays.asList("default", "info", tenantId));
152 194 }
  195 + return changed;
153 196 }
154 197 return false;
155 198 }
... ... @@ -195,7 +238,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
195 238
196 239 @Override
197 240 protected void removeEntity(TenantId tenantId, DeviceProfile entity) {
198   - deleteDeviceProfile(tenantId, new DeviceProfileId(entity.getUuidId()));
  241 + removeDeviceProfile(tenantId, entity.getId());
199 242 }
200 243 };
201 244
... ...
... ... @@ -19,6 +19,9 @@ import lombok.extern.slf4j.Slf4j;
19 19 import org.apache.commons.lang3.StringUtils;
20 20 import org.hibernate.exception.ConstraintViolationException;
21 21 import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.cache.Cache;
  23 +import org.springframework.cache.CacheManager;
  24 +import org.springframework.cache.annotation.Cacheable;
22 25 import org.springframework.stereotype.Service;
23 26 import org.thingsboard.server.common.data.EntityInfo;
24 27 import org.thingsboard.server.common.data.TenantProfile;
... ... @@ -33,6 +36,10 @@ import org.thingsboard.server.dao.service.PaginatedRemover;
33 36 import org.thingsboard.server.dao.service.Validator;
34 37 import org.thingsboard.server.dao.util.mapping.JacksonUtil;
35 38
  39 +import java.util.Arrays;
  40 +import java.util.Collections;
  41 +
  42 +import static org.thingsboard.server.common.data.CacheConstants.TENANT_PROFILE_CACHE;
36 43 import static org.thingsboard.server.dao.service.Validator.validateId;
37 44
38 45 @Service
... ... @@ -44,6 +51,10 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
44 51 @Autowired
45 52 private TenantProfileDao tenantProfileDao;
46 53
  54 + @Autowired
  55 + private CacheManager cacheManager;
  56 +
  57 + @Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{#tenantProfileId}")
47 58 @Override
48 59 public TenantProfile findTenantProfileById(TenantId tenantId, TenantProfileId tenantProfileId) {
49 60 log.trace("Executing findTenantProfileById [{}]", tenantProfileId);
... ... @@ -51,6 +62,7 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
51 62 return tenantProfileDao.findById(tenantId, tenantProfileId.getId());
52 63 }
53 64
  65 + @Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{'info', #tenantProfileId}")
54 66 @Override
55 67 public EntityInfo findTenantProfileInfoById(TenantId tenantId, TenantProfileId tenantProfileId) {
56 68 log.trace("Executing findTenantProfileInfoById [{}]", tenantProfileId);
... ... @@ -73,6 +85,13 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
73 85 throw t;
74 86 }
75 87 }
  88 + Cache cache = cacheManager.getCache(TENANT_PROFILE_CACHE);
  89 + cache.evict(Collections.singletonList(savedTenantProfile.getId()));
  90 + cache.evict(Arrays.asList("info", savedTenantProfile.getId()));
  91 + if (savedTenantProfile.isDefault()) {
  92 + cache.evict(Collections.singletonList("default"));
  93 + cache.evict(Arrays.asList("default", "info"));
  94 + }
76 95 return savedTenantProfile;
77 96 }
78 97
... ... @@ -80,8 +99,19 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
80 99 public void deleteTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
81 100 log.trace("Executing deleteTenantProfile [{}]", tenantProfileId);
82 101 validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
  102 + TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenantProfileId.getId());
  103 + if (tenantProfile != null && tenantProfile.isDefault()) {
  104 + throw new DataValidationException("Deletion of Default Tenant Profile is prohibited!");
  105 + }
  106 + this.removeTenantProfile(tenantId, tenantProfileId);
  107 + }
  108 +
  109 + private void removeTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
83 110 deleteEntityRelations(tenantId, tenantProfileId);
84 111 tenantProfileDao.removeById(tenantId, tenantProfileId.getId());
  112 + Cache cache = cacheManager.getCache(TENANT_PROFILE_CACHE);
  113 + cache.evict(Collections.singletonList(tenantProfileId.getId()));
  114 + cache.evict(Arrays.asList("info", tenantProfileId.getId()));
85 115 }
86 116
87 117 @Override
... ... @@ -115,12 +145,14 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
115 145 return defaultTenantProfile;
116 146 }
117 147
  148 + @Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{'default'}")
118 149 @Override
119 150 public TenantProfile findDefaultTenantProfile(TenantId tenantId) {
120 151 log.trace("Executing findDefaultTenantProfile");
121 152 return tenantProfileDao.findDefaultTenantProfile(tenantId);
122 153 }
123 154
  155 + @Cacheable(cacheNames = TENANT_PROFILE_CACHE, key = "{'default', 'info'}")
124 156 @Override
125 157 public EntityInfo findDefaultTenantProfileInfo(TenantId tenantId) {
126 158 log.trace("Executing findDefaultTenantProfileInfo");
... ... @@ -133,17 +165,28 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
133 165 validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
134 166 TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenantProfileId.getId());
135 167 if (!tenantProfile.isDefault()) {
  168 + Cache cache = cacheManager.getCache(TENANT_PROFILE_CACHE);
136 169 tenantProfile.setDefault(true);
137 170 TenantProfile previousDefaultTenantProfile = findDefaultTenantProfile(tenantId);
  171 + boolean changed = false;
138 172 if (previousDefaultTenantProfile == null) {
139 173 tenantProfileDao.save(tenantId, tenantProfile);
140   - return true;
  174 + changed = true;
141 175 } else if (!previousDefaultTenantProfile.getId().equals(tenantProfile.getId())) {
142 176 previousDefaultTenantProfile.setDefault(false);
143 177 tenantProfileDao.save(tenantId, previousDefaultTenantProfile);
144 178 tenantProfileDao.save(tenantId, tenantProfile);
145   - return true;
  179 + cache.evict(Collections.singletonList(previousDefaultTenantProfile.getId()));
  180 + cache.evict(Arrays.asList("info", previousDefaultTenantProfile.getId()));
  181 + changed = true;
  182 + }
  183 + if (changed) {
  184 + cache.evict(Collections.singletonList(tenantProfile.getId()));
  185 + cache.evict(Arrays.asList("info", tenantProfile.getId()));
  186 + cache.evict(Collections.singletonList("default"));
  187 + cache.evict(Arrays.asList("default", "info"));
146 188 }
  189 + return changed;
147 190 }
148 191 return false;
149 192 }
... ... @@ -180,7 +223,7 @@ public class TenantProfileServiceImpl extends AbstractEntityService implements T
180 223
181 224 @Override
182 225 protected void removeEntity(TenantId tenantId, TenantProfile entity) {
183   - deleteTenantProfile(tenantId, new TenantProfileId(entity.getUuidId()));
  226 + removeTenantProfile(tenantId, entity.getId());
184 227 }
185 228 };
186 229
... ...
... ... @@ -71,9 +71,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
71 71 savedDeviceProfile.setName("New device profile");
72 72 deviceProfileService.saveDeviceProfile(savedDeviceProfile);
73 73 DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
74   - Assert.assertEquals(foundDeviceProfile.getName(), savedDeviceProfile.getName());
75   -
76   - deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
  74 + Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfile.getName());
77 75 }
78 76
79 77 @Test
... ... @@ -83,8 +81,7 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
83 81 DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
84 82 Assert.assertNotNull(foundDeviceProfile);
85 83 Assert.assertEquals(savedDeviceProfile, foundDeviceProfile);
86   - deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
87   - }
  84 + }
88 85
89 86 @Test
90 87 public void testFindDeviceProfileInfoById() {
... ... @@ -94,7 +91,6 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
94 91 Assert.assertNotNull(foundDeviceProfileInfo);
95 92 Assert.assertEquals(savedDeviceProfile.getId(), foundDeviceProfileInfo.getId());
96 93 Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfileInfo.getName());
97   - deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
98 94 }
99 95
100 96 @Test
... ... @@ -131,8 +127,6 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
131 127 defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
132 128 Assert.assertNotNull(defaultDeviceProfile);
133 129 Assert.assertEquals(savedDeviceProfile2.getId(), defaultDeviceProfile.getId());
134   - deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile1.getId());
135   - deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile2.getId());
136 130 }
137 131
138 132 @Test(expected = DataValidationException.class)
... ...
... ... @@ -61,7 +61,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
61 61 TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
62 62 Assert.assertEquals(foundTenantProfile.getName(), savedTenantProfile.getName());
63 63
64   - tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  64 + tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
65 65 }
66 66
67 67 @Test
... ... @@ -71,7 +71,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
71 71 TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
72 72 Assert.assertNotNull(foundTenantProfile);
73 73 Assert.assertEquals(savedTenantProfile, foundTenantProfile);
74   - tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  74 + tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
75 75 }
76 76
77 77 @Test
... ... @@ -82,7 +82,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
82 82 Assert.assertNotNull(foundTenantProfileInfo);
83 83 Assert.assertEquals(savedTenantProfile.getId(), foundTenantProfileInfo.getId());
84 84 Assert.assertEquals(savedTenantProfile.getName(), foundTenantProfileInfo.getName());
85   - tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  85 + tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
86 86 }
87 87
88 88 @Test
... ... @@ -93,7 +93,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
93 93 TenantProfile foundDefaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
94 94 Assert.assertNotNull(foundDefaultTenantProfile);
95 95 Assert.assertEquals(savedTenantProfile, foundDefaultTenantProfile);
96   - tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  96 + tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
97 97 }
98 98
99 99 @Test
... ... @@ -105,7 +105,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
105 105 Assert.assertNotNull(foundDefaultTenantProfileInfo);
106 106 Assert.assertEquals(savedTenantProfile.getId(), foundDefaultTenantProfileInfo.getId());
107 107 Assert.assertEquals(savedTenantProfile.getName(), foundDefaultTenantProfileInfo.getName());
108   - tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  108 + tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
109 109 }
110 110
111 111 @Test
... ... @@ -126,8 +126,7 @@ public class BaseTenantProfileServiceTest extends AbstractServiceTest {
126 126 defaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
127 127 Assert.assertNotNull(defaultTenantProfile);
128 128 Assert.assertEquals(savedTenantProfile2.getId(), defaultTenantProfile.getId());
129   - tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile1.getId());
130   - tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile2.getId());
  129 + tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
131 130 }
132 131
133 132 @Test(expected = DataValidationException.class)
... ...
... ... @@ -30,6 +30,12 @@ caffeine.specs.entityViews.maxSize=100000
30 30 caffeine.specs.claimDevices.timeToLiveInMinutes=1440
31 31 caffeine.specs.claimDevices.maxSize=100000
32 32
  33 +caffeine.specs.tenantProfiles.timeToLiveInMinutes=1440
  34 +caffeine.specs.tenantProfiles.maxSize=100000
  35 +
  36 +caffeine.specs.deviceProfiles.timeToLiveInMinutes=1440
  37 +caffeine.specs.deviceProfiles.maxSize=100000
  38 +
33 39 redis.connection.host=localhost
34 40 redis.connection.port=6379
35 41 redis.connection.db=0
... ...