Device Profile Cache
This commit is contained in:
		
							parent
							
								
									ffe5b5ee91
								
							
						
					
					
						commit
						c69ba6d02d
					
				@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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<>());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ public class TenantProfileCacheKey implements Serializable {
 | 
			
		||||
        if (defaultProfile) {
 | 
			
		||||
            return "default";
 | 
			
		||||
        } else {
 | 
			
		||||
            return tenantProfileId.getId().toString();
 | 
			
		||||
            return tenantProfileId.toString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user