Device Profile Cache

This commit is contained in:
Andrii Shvaika 2022-05-10 13:27:02 +03:00
parent ffe5b5ee91
commit c69ba6d02d
15 changed files with 256 additions and 103 deletions

View File

@ -1,41 +0,0 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.cache;
public class CacheKeyUtil {
public static String toString(Object... keyElements) {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (Object keyElement : keyElements) {
first = addElement(sb, first, keyElement);
}
return sb.toString();
}
private static boolean addElement(StringBuilder sb, boolean first, Object element) {
if (element != null) {
if (!first) {
sb.append("_");
}
sb.append(element);
return false;
} else {
return first;
}
}
}

View File

@ -19,8 +19,6 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serializable;
@ -31,12 +29,14 @@ import java.io.Serializable;
@Builder
public class AssetCacheKey implements Serializable {
private static final long serialVersionUID = 4196610233744512673L;
private final TenantId tenantId;
private final String name;
@Override
public String toString() {
return CacheKeyUtil.toString(tenantId, name);
return tenantId + "_" + name;
}
}

View File

@ -19,7 +19,6 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
@ -45,7 +44,11 @@ public class DeviceCacheKey implements Serializable {
@Override
public String toString() {
return CacheKeyUtil.toString(tenantId, deviceId, deviceName);
if (deviceId != null) {
return tenantId + "_" + deviceId;
} else {
return tenantId + "_n_" + deviceName;
}
}
}

View File

@ -0,0 +1,63 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.device;
import lombok.Data;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serializable;
@Data
public class DeviceProfileCacheKey implements Serializable {
private static final long serialVersionUID = 8220455917177676472L;
private final TenantId tenantId;
private final String name;
private final DeviceProfileId deviceProfileId;
private final boolean defaultProfile;
private DeviceProfileCacheKey(TenantId tenantId, String name, DeviceProfileId deviceProfileId, boolean defaultProfile) {
this.tenantId = tenantId;
this.name = name;
this.deviceProfileId = deviceProfileId;
this.defaultProfile = defaultProfile;
}
public static DeviceProfileCacheKey fromName(TenantId tenantId, String name) {
return new DeviceProfileCacheKey(tenantId, name, null, false);
}
public static DeviceProfileCacheKey fromId(DeviceProfileId id) {
return new DeviceProfileCacheKey(null, null, id, false);
}
public static DeviceProfileCacheKey defaultProfile(TenantId tenantId) {
return new DeviceProfileCacheKey(tenantId, null, null, true);
}
@Override
public String toString() {
if (deviceProfileId != null) {
return deviceProfileId.toString();
} else if (defaultProfile) {
return tenantId.toString();
} else {
return tenantId + "_" + name;
}
}
}

View File

@ -0,0 +1,34 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.device;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.dao.cache.CaffeineTbTransactionalCache;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@Service("DeviceProfileCache")
public class DeviceProfileCaffeineCache extends CaffeineTbTransactionalCache<DeviceProfileCacheKey, DeviceProfile> {
public DeviceProfileCaffeineCache(CacheManager cacheManager) {
super(cacheManager, CacheConstants.DEVICE_PROFILE_CACHE);
}
}

View File

@ -0,0 +1,31 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.device;
import lombok.Data;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
@Data
public class DeviceProfileEvictEvent {
private final TenantId tenantId;
private final String newName;
private final String oldName;
private final DeviceProfileId deviceProfileId;
private final boolean defaultProfile;
}

View File

@ -0,0 +1,36 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.device;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CacheSpecsMap;
import org.thingsboard.server.cache.TBRedisCacheConfiguration;
import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.dao.cache.RedisTbTransactionalCache;
import org.thingsboard.server.dao.cache.TbRedisSerializer;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@Service("DeviceProfileCache")
public class DeviceProfileRedisCache extends RedisTbTransactionalCache<DeviceProfileCacheKey, DeviceProfile> {
public DeviceProfileRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.DEVICE_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>());
}
}

View File

@ -17,17 +17,23 @@ package org.thingsboard.server.dao.device;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.exception.ConstraintViolationException;
import org.jetbrains.annotations.Nullable;
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.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceProfileInfo;
import org.thingsboard.server.common.data.DeviceProfileProvisionType;
import org.thingsboard.server.common.data.DeviceProfileType;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
@ -36,14 +42,20 @@ import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.asset.AssetCacheKey;
import org.thingsboard.server.dao.entity.AbstractCachedEntityService;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.tenant.TenantProfileCacheKey;
import org.thingsboard.server.dao.tenant.TenantProfileEvictEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@ -52,7 +64,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId;
@Service
@Slf4j
public class DeviceProfileServiceImpl extends AbstractEntityService implements DeviceProfileService {
public class DeviceProfileServiceImpl extends AbstractCachedEntityService<DeviceProfileCacheKey, DeviceProfile, DeviceProfileEvictEvent> implements DeviceProfileService {
private static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId ";
@ -67,51 +79,60 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
@Autowired
private DeviceService deviceService;
@Autowired
private CacheManager cacheManager;
@Autowired
private DataValidator<DeviceProfile> deviceProfileValidator;
private final Lock findOrCreateLock = new ReentrantLock();
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#deviceProfileId.id}")
@TransactionalEventListener(classes = DeviceProfileEvictEvent.class)
@Override
public void handleEvictEvent(DeviceProfileEvictEvent event) {
List<DeviceProfileCacheKey> keys = new ArrayList<>(2);
keys.add(DeviceProfileCacheKey.fromId(event.getDeviceProfileId()));
keys.add(DeviceProfileCacheKey.fromName(event.getTenantId(), event.getNewName()));
if (event.isDefaultProfile()) {
keys.add(DeviceProfileCacheKey.defaultProfile(event.getTenantId()));
}
if (StringUtils.isNotEmpty(event.getOldName()) && !event.getOldName().equals(event.getNewName())) {
keys.add(DeviceProfileCacheKey.fromName(event.getTenantId(), event.getOldName()));
}
cache.evict(keys);
}
@Override
public DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
return deviceProfileDao.findById(tenantId, deviceProfileId.getId());
return cache.getAndPutInTransaction(DeviceProfileCacheKey.fromId(deviceProfileId),
() -> deviceProfileDao.findById(tenantId, deviceProfileId.getId()), true);
}
@Override
public DeviceProfile findDeviceProfileByName(TenantId tenantId, String profileName) {
log.trace("Executing findDeviceProfileByName [{}][{}]", tenantId, profileName);
Validator.validateString(profileName, INCORRECT_DEVICE_PROFILE_NAME + profileName);
return deviceProfileDao.findByName(tenantId, profileName);
return cache.getAndPutInTransaction(DeviceProfileCacheKey.fromName(tenantId, profileName),
() -> deviceProfileDao.findByName(tenantId, profileName), true);
}
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'info', #deviceProfileId.id}")
@Override
public DeviceProfileInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
return deviceProfileDao.findDeviceProfileInfoById(tenantId, deviceProfileId.getId());
return toDeviceProfileInfo(findDeviceProfileById(tenantId, deviceProfileId));
}
@Override
public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) {
log.trace("Executing saveDeviceProfile [{}]", deviceProfile);
deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId);
DeviceProfile oldDeviceProfile = null;
if (deviceProfile.getId() != null) {
oldDeviceProfile = deviceProfileDao.findById(deviceProfile.getTenantId(), deviceProfile.getId().getId());
}
DeviceProfile oldDeviceProfile = deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId);
DeviceProfile savedDeviceProfile;
try {
savedDeviceProfile = deviceProfileDao.saveAndFlush(deviceProfile.getTenantId(), deviceProfile);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_profile_name_unq_key")) {
//TODO: refactor this to return existing device profile. If they are equal - no need to throw exception. Then we can make this call @Transactional and tests will not fail.
throw new DataValidationException("Device profile with such name already exists!");
} else if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_provision_key_unq_key")) {
throw new DataValidationException("Device profile with such provision device key already exists!");
@ -119,14 +140,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
throw t;
}
}
Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
cache.evict(Collections.singletonList(savedDeviceProfile.getId().getId()));
cache.evict(Arrays.asList("info", savedDeviceProfile.getId().getId()));
cache.evict(Arrays.asList(deviceProfile.getTenantId().getId(), deviceProfile.getName()));
if (savedDeviceProfile.isDefault()) {
cache.evict(Arrays.asList("default", savedDeviceProfile.getTenantId().getId()));
cache.evict(Arrays.asList("default", "info", savedDeviceProfile.getTenantId().getId()));
}
publishEvictEvent(new DeviceProfileEvictEvent(savedDeviceProfile.getTenantId(), savedDeviceProfile.getName(),
oldDeviceProfile != null ? oldDeviceProfile.getName() : null, savedDeviceProfile.getId(), savedDeviceProfile.isDefault()));
if (oldDeviceProfile != null && !oldDeviceProfile.getName().equals(deviceProfile.getName())) {
PageLink pageLink = new PageLink(100);
PageData<Device> pageData;
@ -142,6 +157,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
return savedDeviceProfile;
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void deleteDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing deleteDeviceProfile [{}]", deviceProfileId);
@ -157,6 +173,8 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
DeviceProfileId deviceProfileId = deviceProfile.getId();
try {
deviceProfileDao.removeById(tenantId, deviceProfileId.getId());
publishEvictEvent(new DeviceProfileEvictEvent(deviceProfile.getTenantId(), deviceProfile.getName(),
null, deviceProfile.getId(), deviceProfile.isDefault()));
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_device_profile")) {
@ -166,10 +184,6 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
}
}
deleteEntityRelations(tenantId, deviceProfileId);
Cache cache = cacheManager.getCache(DEVICE_PROFILE_CACHE);
cache.evict(Collections.singletonList(deviceProfileId.getId()));
cache.evict(Arrays.asList("info", deviceProfileId.getId()));
cache.evict(Arrays.asList(tenantId.getId(), deviceProfile.getName()));
}
@Override
@ -188,7 +202,6 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
return deviceProfileDao.findDeviceProfileInfos(tenantId, pageLink, transportType);
}
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{#tenantId.id, #name}")
@Override
public DeviceProfile findOrCreateDeviceProfile(TenantId tenantId, String name) {
log.trace("Executing findOrCreateDefaultDeviceProfile");
@ -207,6 +220,7 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
return deviceProfile;
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public DeviceProfile createDefaultDeviceProfile(TenantId tenantId) {
log.trace("Executing createDefaultDeviceProfile tenantId [{}]", tenantId);
@ -234,56 +248,49 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
return saveDeviceProfile(deviceProfile);
}
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'default', #tenantId.id}")
@Override
public DeviceProfile findDefaultDeviceProfile(TenantId tenantId) {
log.trace("Executing findDefaultDeviceProfile tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
return deviceProfileDao.findDefaultDeviceProfile(tenantId);
return cache.getAndPutInTransaction(DeviceProfileCacheKey.defaultProfile(tenantId),
() -> deviceProfileDao.findDefaultDeviceProfile(tenantId), true);
}
@Cacheable(cacheNames = DEVICE_PROFILE_CACHE, key = "{'default', 'info', #tenantId.id}")
@Override
public DeviceProfileInfo findDefaultDeviceProfileInfo(TenantId tenantId) {
log.trace("Executing findDefaultDeviceProfileInfo tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
return deviceProfileDao.findDefaultDeviceProfileInfo(tenantId);
return toDeviceProfileInfo(findDefaultDeviceProfile(tenantId));
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public boolean setDefaultDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing setDefaultDeviceProfile [{}]", deviceProfileId);
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);
publishEvictEvent(new DeviceProfileEvictEvent(deviceProfile.getTenantId(), deviceProfile.getName(), null, deviceProfile.getId(), true));
changed = true;
} else if (!previousDefaultDeviceProfile.getId().equals(deviceProfile.getId())) {
previousDefaultDeviceProfile.setDefault(false);
deviceProfileDao.save(tenantId, previousDefaultDeviceProfile);
deviceProfileDao.save(tenantId, deviceProfile);
cache.evict(Collections.singletonList(previousDefaultDeviceProfile.getId().getId()));
cache.evict(Arrays.asList("info", previousDefaultDeviceProfile.getId().getId()));
cache.evict(Arrays.asList(tenantId.getId(), previousDefaultDeviceProfile.getName()));
publishEvictEvent(new DeviceProfileEvictEvent(previousDefaultDeviceProfile.getTenantId(), previousDefaultDeviceProfile.getName(), null, previousDefaultDeviceProfile.getId(), false));
publishEvictEvent(new DeviceProfileEvictEvent(deviceProfile.getTenantId(), deviceProfile.getName(), null, deviceProfile.getId(), true));
changed = true;
}
if (changed) {
cache.evict(Collections.singletonList(deviceProfile.getId().getId()));
cache.evict(Arrays.asList("info", deviceProfile.getId().getId()));
cache.evict(Arrays.asList("default", tenantId.getId()));
cache.evict(Arrays.asList("default", "info", tenantId.getId()));
cache.evict(Arrays.asList(tenantId.getId(), deviceProfile.getName()));
}
return changed;
}
return false;
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void deleteDeviceProfilesByTenantId(TenantId tenantId) {
log.trace("Executing deleteDeviceProfilesByTenantId, tenantId [{}]", tenantId);
@ -305,4 +312,9 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
}
};
private DeviceProfileInfo toDeviceProfileInfo(DeviceProfile profile) {
return profile == null ? null : new DeviceProfileInfo(profile.getId(), profile.getName(), profile.getImage(),
profile.getDefaultDashboardId(), profile.getType(), profile.getTransportType());
}
}

View File

@ -19,7 +19,6 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serializable;
@ -35,7 +34,7 @@ public class EdgeCacheKey implements Serializable {
@Override
public String toString() {
return CacheKeyUtil.toString(tenantId, name);
return tenantId + "_" + name;
}
}

View File

@ -18,8 +18,6 @@ package org.thingsboard.server.dao.entityview;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId;
@ -57,7 +55,13 @@ public class EntityViewCacheKey implements Serializable {
@Override
public String toString() {
return CacheKeyUtil.toString(tenantId, name, entityId, entityViewId);
if (entityViewId != null) {
return entityViewId.toString();
} else if (entityId != null) {
return tenantId + "_" + entityId;
} else {
return tenantId + "_n_" + name;
}
}
}

View File

@ -18,11 +18,7 @@ package org.thingsboard.server.dao.entityview;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serializable;
import java.util.List;

View File

@ -19,9 +19,7 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId;
import java.io.Serializable;
@ -35,7 +33,7 @@ public class OtaPackageCacheKey implements Serializable {
@Override
public String toString() {
return id.getId().toString();
return id.toString();
}
}

View File

@ -19,7 +19,6 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.thingsboard.server.cache.CacheKeyUtil;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
@ -46,7 +45,24 @@ public class RelationCacheKey implements Serializable {
@Override
public String toString() {
return CacheKeyUtil.toString(from, to, typeGroup, type, direction);
StringBuilder sb = new StringBuilder();
boolean first = add(sb, true, from);
first = add(sb, first, to);
first = add(sb, first, type);
first = add(sb, first, typeGroup);
add(sb, first, direction);
return sb.toString();
}
private boolean add(StringBuilder sb, boolean first, Object param) {
if (param != null) {
if (!first) {
sb.append("_");
}
first = false;
sb.append(param);
}
return first;
}
}

View File

@ -47,7 +47,7 @@ public class TenantProfileCacheKey implements Serializable {
if (defaultProfile) {
return "default";
} else {
return tenantProfileId.getId().toString();
return tenantProfileId.toString();
}
}
}

View File

@ -56,6 +56,8 @@ public class JpaAlarmDaoTest extends AbstractJpaDaoTest {
UUID alarm3Id = UUID.fromString("d4b68f45-3e96-11e7-a884-898080180d6b");
int alarmCountBeforeSave = alarmDao.find(TenantId.fromUUID(tenantId)).size();
saveAlarm(alarm1Id, tenantId, originator1Id, "TEST_ALARM");
//The timestamp of the startTime should be different in order for test to always work
Thread.sleep(1);
saveAlarm(alarm2Id, tenantId, originator1Id, "TEST_ALARM");
saveAlarm(alarm3Id, tenantId, originator2Id, "TEST_ALARM");
int alarmCountAfterSave = alarmDao.find(TenantId.fromUUID(tenantId)).size();